Skip to content

perf(grounding): the file cache is keyed on the commit SHA, so an unchanged context file misses on every push — 42% of misses are repeat reads #10219

Description

@JSONbored

Follow-up to #10208, which identified grounding as the one genuinely underperforming cache: 15.9% hit rate (142 hits / 753 misses in 24h) against 74-86% for every other surface, while being the highest-volume one.

Root cause

getFileContent in src/review/grounding-wire.ts keys the cache on (repo, path, ref), where ref is the commit SHA. The comment there is correct that this is safe — a blob at an immutable commit never changes, so a hit is always reusable verbatim.

But it is keyed on the wrong immutable thing. Grounding reads context files (type declarations, generated schemas, manifests), which are usually not the files the PR changed. Those files are byte-identical across commits — yet every push mints a new ref, so every one of them misses again.

The cache is therefore invalidated by commits that did not touch the file it is caching.

Evidence (Orb, 24h to 2026-07-31T12:35Z)

total grounding misses 762
distinct (repo, path) pairs 441
misses that are a repeat read of a file already fetched 321 (42%)

Worst offenders — each row is one file, re-fetched from the GitHub Contents API this many times in a day:

repo path misses/24h
JSONbored/metagraphed packages/contract/index.d.ts 31
JSONbored/metagraphed public/metagraph/openapi.json 22
JSONbored/metagraphed public/metagraph/api-index.json 15
JSONbored/metagraphed public/metagraph/types.d.ts 15
JSONbored/metagraphed apps/ui/src/routes/-subnets-netuid-page.tsx 11
JSONbored/loopover .release-please-manifest.json 9
JSONbored/loopover package.json 7
JSONbored/loopover apps/loopover-ui/public/openapi.json 7

A generated index.d.ts did not change 31 times in a day. Each of those is a real Contents API call against the installation's REST quota — the same quota #10184 is separately trying to stop burning.

Recommended fix: conditional requests

Store the response ETag alongside the cached content under a (repo, path) key, and send If-None-Match when the ref-keyed lookup misses. GitHub answers 304 Not Modified for an unchanged file, and a 304 does not count against the REST rate limit. So:

  • unchanged file, new commit → 304, reuse cached content, zero quota spent
  • genuinely changed file → 200 with fresh content, exactly as today
  • correctness is delegated to GitHub's own validator rather than to our guess about what changed

This keeps the existing (repo, path, ref) fast path untouched for a true same-ref hit.

A cheaper variant worth considering first, if ETag plumbing is too much: keep a (repo, path, ref) -> blobSha mapping plus a content-addressed (repo, path, blobSha) -> content store. That de-duplicates storage but still costs one call per new ref, so it does not save quota — the ETag route is the one that does.

Instrumentation note

Whatever lands should emit a distinct outcome for "revalidated 304" rather than folding it into either grounding_cache_hit or grounding_cache_miss — otherwise this cache acquires a fourth vocabulary for reuse, which is the exact problem #10208 is about.

Verification

All figures queried directly against the Orb Postgres primary. The repeat-read count is total misses - distinct (repoFullName, path) from audit_events where event_type = 'github_app.grounding_cache_miss', which is a lower bound on the waste: it counts a file re-fetched N times as N-1 avoidable calls only if all N shared content, which the top rows above make near-certain but do not strictly prove.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions