Skip to content

fix(review): grounding re-fetches every changed file's full body every 30 min with zero caching #4499

Description

@JSONbored

Part of #4496. P3 — medium severity, high confidence.

Context

buildReviewGroundingText's file-content half (src/review/grounding-wire.ts:224-225) re-fetches the ENTIRE post-change content of every changed file via a live GitHub Contents API call on every invocation:

const fetcher = await makeGithubFileFetcher(env, args.repoFullName, args.installationId);
const fileContents = await fetchFullFileContents(flags, args.headSha ?? undefined, toGroundingFiles(args.files), fetcher);

makeGithubFileFetcher (grounding-wire.ts:126-170) issues a live GET /repos/{owner}/{repo}/contents/{path}?ref={ref} GET per file with NO cache/memoization keyed by (repo, path, ref) anywhere in the file — contrast the CI half of the same feature, which explicitly reuses cached data ("reuses the already-cached CI check summaries", file header lines 10-11). The shared GitHub response cache (src/github/client.ts:107-132, githubCacheClassForUrl) doesn't help either — it only classifies branch-protection, bare commit, and bare user/repo lookups as cacheable; the contents/{path} endpoint matches none of those.

Grounding is listed in dynamicReviewFeatures (processors.ts:9724-9725), which unconditionally bypasses the durable ai_review cache (processors.ts:9919, !dynamicReviewContextActive) — a known, deliberate tradeoff for features whose context can go stale for an unchanged head SHA. That leaves only the 30-minute AI_REVIEW_NON_CACHEABLE_RETRY_COOLDOWN_MS (processors.ts:4089) as protection. Once that cooldown lapses, the full multi-file GitHub content re-fetch repeats from scratch for the identical head SHA — and this isn't limited to sweep ticks: maybePublishPrPublicSurface is also invoked from real webhook triggers unrelated to code changes (pull_request_review_comment, pull_request_review, pull_request_review_thread, per PR_PUBLIC_SURFACE_ACTIONS/PR_GATE_CLOSED_ACTIONS, processors.ts:6597-6614), none of which change the head SHA — so any actively-discussed PR with grounding enabled re-triggers the full re-fetch every time a comment/review event lands past the cooldown.

Note: GITTENSORY_REVIEW_GROUNDING defaults false on hosted (wrangler.jsonc) but true in .env.selfhost.example — so the affected population is real specifically for self-host deployments, where grounding is the suggested default.

Requirements

  • Cache fetched file content keyed by (repoFullName, path, headSha) — content for an unchanged head SHA never needs re-fetching. A short-TTL or durable table (mirroring the signal_snapshots-style store repo-culture-profile.ts already uses) both work; durable is preferable since the key includes an immutable head SHA.
  • Ensure a NEW head SHA (a genuine push) still gets a fresh fetch — this must not accidentally suppress re-grounding on real code changes.
  • Ensure the fix doesn't interfere with the deliberate "dynamic feature bypasses the ai_review cache" design — this is a narrower, file-content-level cache underneath that decision, not a replacement for it.
  • Invariant + regression tests (non-negotiable): an invariant test asserting a second buildReviewGroundingText call for the SAME (repo, path, headSha) triple makes zero additional GitHub fetch calls; a regression test reproducing the exact bug shape (repeated non-push webhook events — e.g. two pull_request_review submissions 31+ minutes apart — on an unchanged head SHA, asserting the file-content fetch only happens once); a test confirming a genuinely new head SHA DOES trigger a fresh fetch (the negative case, so the cache can't accidentally go stale).

Deliverables

  • File content cache keyed by (repoFullName, path, headSha), reused across calls for an unchanged head
  • Fresh fetch still occurs on a new head SHA
  • Invariant test: repeat call for same key = zero extra fetches
  • Regression test: repeated non-push webhook events on an unchanged head don't re-fetch
  • Negative-path test: new head SHA does re-fetch

Expected outcome

Grounding's file-content fetch reuses prior file bodies for an unchanged head SHA instead of re-fetching every changed file from GitHub on every cooldown-expiry cycle or non-push webhook event, cutting real GitHub API load on any actively-discussed PR with grounding enabled — the exact population self-host deployments are pointed at by default.

References

  • src/review/grounding-wire.ts:126-170, 224-225 (the fetcher + call site)
  • src/review/review-grounding.ts:195-234 (fetchFullFileContents)
  • src/github/client.ts:107-132 (the shared cache class that doesn't cover this endpoint)
  • src/queue/processors.ts:9724-9725, 9811-9824, 9919 (dynamic-feature cache-bypass rationale)
  • src/review/rag.ts:439 (chunkCountCache — a precedent short-TTL cache pattern in a sibling feature)
  • wrangler.jsonc vs .env.selfhost.example (hosted-off / self-host-on default)

Effort

M

Metadata

Metadata

Assignees

Labels

gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.maintainer-onlyOwner-only work — yields no Gittensor points.orbGittensory Orb related - maintainer self-hosting analytics.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions