feat(cache): per-call freshness override max_cache_age_s#85
Merged
Conversation
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a keyword-only
max_cache_age_s(int | None, default None) tofetch_relevant()and the MCPfetch_pagetool:NonefollowsTRAWL_FETCH_CACHE_TTL(unchanged default),0treats any cached entry as stale and routes through the existing conditional-GET revalidation (may still 304-reuse identical content),Naccepts entries younger than N seconds. Motivated by the field converging on per-call freshness knobs (ExamaxAgeHours, 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
hada_newsfails identically on develop with and without this diff and with rs on/off: live front-page drift (markersGeekNews/topic?idabsent today), environmental, not diff-causedReview
/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_hitis not currently emitted in telemetry JSONL (pre-existing gap, out of scope; noted for a future telemetry PR).hada_newsground truth may need principled maintenance if the drift persists — separate decision, not touched here.🤖 Generated with Claude Code