feat(stats): cache staleness/age fields for dep-scan + linear caches (TAP-4558)#199
Conversation
…(TAP-4558) The unified tapps_stats.caches surface (TAP-4561) reported raw hit/miss counters only for the dependency-scan and Linear-snapshot caches. Add age_seconds + stale telemetry to both, following the existing age/stale shape the code-graph cache surface already exposes — closing AC1 (hit-rate PLUS staleness) and AC4 (a committed real-cache test, not synthetic registry providers, asserting staleness fields for >=2 caches). - dependency_scan: provider computes age/staleness of the freshest cache entry from its monotonic timestamps against the TTL. - linear_snapshot: record the newest write timestamp on _cache_write; provider derives age + staleness vs the open-bucket TTL. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7b2d2e460d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ttl_open = load_settings().linear_cache_ttl_open_seconds | ||
| age = time.time() - _snapshot_last_write_ts | ||
| out["age_seconds"] = round(age, 1) | ||
| out["stale"] = TTLStaleness(float(ttl_open)).is_stale(_snapshot_last_write_ts) |
There was a problem hiding this comment.
Use each snapshot's actual expiry for Linear staleness
When the freshest Linear cache write is for a completed or canceled slice, tapps_linear_snapshot_put stores it with linear_cache_ttl_closed_seconds (default 3600s), but this stats provider always evaluates staleness against linear_cache_ttl_open_seconds (default 300s). After five minutes tapps_stats.caches.linear_snapshot.stale reports true even though reads for that snapshot remain valid for another 55 minutes, so cache health telemetry is falsely stale for closed-issue workflows; base this on the written payload's expires_at/TTL or the matching state bucket instead.
Useful? React with 👍 / 👎.
What
Remaining sliver of TAP-4558. Bulk shipped under TAP-4561 / #190 (unified
CacheStatsregistry,payload['caches'], 5 registrations, single warmer). This closes the two residual ACs the 2026-07-02 adversarial re-verification flagged:age_seconds+staleto the dependency-scan and Linear-snapshot cache providers intapps_stats.caches— they previously reported raw hit/miss counters only. Follows the existingage/staleshape the code-graph cache surface already exposes (no new field shape invented).test_cache_staleness_stats.pydrives the actual dep-scan + Linear caches and asserts the staleness fields surface for ≥2 real caches viacollect_cache_stats().How
dependency_scan: provider computes freshest-entry age/staleness from the cache's monotonic timestamps vs the TTL.linear_snapshot: record newest write timestamp on_cache_write; provider derives age + staleness vs the open-bucket TTL.Tests
80 passed— new staleness tests + touched dep-scan/substrate/linear-gate suites. Pre-commit gate: all 3 files pass (score 90/100/100, security pass).Related: TAP-4561.
🤖 Generated with Claude Code