Skip to content

fix(review): key the durable CI-state cache on resolved required contexts - #3036

Merged
JSONbored merged 1 commit into
mainfrom
claude/ci-cache-resolved-contexts-key
Jul 4, 2026
Merged

fix(review): key the durable CI-state cache on resolved required contexts#3036
JSONbored merged 1 commit into
mainfrom
claude/ci-cache-resolved-contexts-key

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • PR feat(review): add durable webhook-invalidated CI-state snapshot cache #2984 added a durable, webhook-invalidated CI-state snapshot cache (pull_request_detail_sync_state), but cachedFetchLiveCiAggregate's durable-row key was derived from the raw, unresolved settings.expectedCiContexts config instead of the actually-resolved required-contexts set that cachedRequiredStatusContexts computes (branch protection merged with config, via mergeRequiredCiContexts).
  • If branch protection changes server-side (a maintainer adds/removes a required check in GitHub's UI) while expectedCiContexts config and the PR's head_sha stay the same, the durable cache key was unchanged, so the readiness path could keep serving a stale aggregate computed against the old required-context set for up to the cache's 60s TTL — a wrong merge/close verdict window. This PR derives the durable key from the resolved set (resolvedRequiredContextsKeyPart) instead.
  • Also hardens deserializeCachedCiAggregate: JSON.parse succeeding does not guarantee the parsed value is an array, so a corrupted/malformed row's failingDetails/nonRequiredFailingDetails now fail open to a cache miss via an explicit Array.isArray check rather than handing callers a wrong shape.
  • Generic self-host engine behavior only; no repo-specific logic.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked an issue, or this is small enough that the summary explains why an issue is not needed. (Direct follow-up correctness fix to the durable CI-state cache landed in feat(review): add durable webhook-invalidated CI-state snapshot cache #2984; no separate issue needed.)

Validation

  • git diff --check
  • npm run actionlint (not run — no workflow files touched)
  • npm run typecheck
  • Ran the affected test files directly and confirmed the new regression tests fail against the pre-fix code and pass against the fix (npx vitest run test/unit/queue.test.ts test/unit/pr-detail-durable-cache.test.ts, 527/527 passing); full unsharded npm run test:coverage not re-run locally per this repo's own guidance to trust CI for the full suite on a narrowly-scoped fix.
  • npm run test:workers (not run — no Cloudflare-Workers-pool-specific code touched)
  • npm run build:mcp / npm run test:mcp-pack (not run — no MCP package changes)
  • npm run ui:openapi:check / npm run ui:lint / npm run ui:typecheck / npm run ui:build (not run — no API/OpenAPI surface or apps/gittensory-ui changes)
  • npm audit --audit-level=moderate (unaffected by this diff; last known-clean from the same working tree)
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

If any required check was skipped, explain why:

  • Skipped checks above are for UI/MCP/Workers surfaces this PR does not touch (backend-only fix to the CI-state cache key derivation); CI's validate job runs them as a backstop.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests. (N/A — no auth/session/CORS changes.)
  • API/OpenAPI/MCP behavior is updated and tested where needed. (N/A — no API/OpenAPI/MCP surface changed; this is an internal cache.)
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks. (N/A — no UI changes.)
  • Visible UI changes include a UI Evidence section below with screenshots. (N/A — no visible UI changes.)
  • Public docs/changelogs are updated where needed; changelogs are only edited for release-prep PRs. (N/A.)

Notes

…exts

cachedFetchLiveCiAggregate (#2984) keyed its durable
pull_request_detail_sync_state row from the raw, unresolved
settings.expectedCiContexts config instead of the actually-resolved
required-contexts set that cachedRequiredStatusContexts returns (branch
protection merged with config, via mergeRequiredCiContexts). If branch
protection changes server-side while expectedCiContexts config and head_sha
stay the same, the durable key was unchanged, so the readiness path could
keep serving a stale aggregate computed against the old required-context set
for up to the cache's TTL. Derive the key from the resolved set instead.

Also hardens deserializeCachedCiAggregate: JSON.parse succeeding does not
guarantee the parsed value is an array, so a corrupted/malformed row's
failingDetails/nonRequiredFailingDetails now fail open to a cache miss via an
explicit Array.isArray check rather than handing callers a wrong shape.
@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.08%. Comparing base (75fe997) to head (dab4ace).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3036   +/-   ##
=======================================
  Coverage   96.08%   96.08%           
=======================================
  Files         260      260           
  Lines       28774    28777    +3     
  Branches    10475    10477    +2     
=======================================
+ Hits        27647    27650    +3     
  Misses        492      492           
  Partials      635      635           
Files with missing lines Coverage Δ
src/github/backfill.ts 96.74% <100.00%> (+<0.01%) ⬆️
src/queue/processors.ts 92.93% <ø> (+<0.01%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 4, 2026
@loopover-orb

loopover-orb Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-04 09:45:32 UTC

4 files · 1 AI reviewer · 1 blocker · readiness 93/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Possible leaked secret in the diff (generic_secret_assignment) — Remove the secret from the diff, rotate the exposed credential, then re-run the gate.

Review summary
This change fixes the durable CI aggregate cache key by deriving it from the resolved required-context set, so branch-protection drift can no longer reuse a row computed against an older required check set while the PR SHA and configured expected contexts stay unchanged. The deserializer hardening is also correct: valid JSON with the wrong top-level shape now fails open as a cache miss instead of returning malformed detail arrays. The visible regression tests exercise the real queue path and the new parse-shape guards, and I do not see a reachable correctness defect in the provided diff.

Nits — 4 non-blocking
  • nit: test/unit/queue.test.ts:2171 has an unusually large explanatory comment and test name that duplicate each other; keep the failure scenario, but trim one of them so future failures are easier to scan.
  • nit: src/github/backfill.ts:3324 only validates that the parsed failing-detail fields are arrays, not that the elements have the expected detail shape; that is acceptable for this fix but leaves malformed array contents to downstream callers.
  • test/unit/queue.test.ts:2171 could add an explicit fetch-count assertion for the check-runs/status endpoints to make the intended durable-cache miss behavior obvious, not just inferred from the final row state.
  • src/github/backfill.ts:3324 could use a small helper such as `parseCachedJsonArray` if more cached JSON array fields get added, so the fail-open shape check stays consistent.

Concerns raised — review before merging

  • Possible leaked secret in the diff (generic_secret_assignment) — Remove the secret from the diff, rotate the exposed credential, then re-run the gate.
Signal Result Evidence
Code review ❌ 1 blocker 1 reviewer
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 60 registered-repo PR(s), 51 merged, 421 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 60 PR(s), 421 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: not available
  • Official Gittensor activity: 60 PR(s), 421 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Explain no-issue PR.
  • No action.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@JSONbored
JSONbored merged commit f947020 into main Jul 4, 2026
11 checks passed
@JSONbored
JSONbored deleted the claude/ci-cache-resolved-contexts-key branch July 4, 2026 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant