Skip to content

feat(review): add cached repo quality-culture profile as AI-review grounding - #3802

Merged
JSONbored merged 3 commits into
mainfrom
feat/repo-culture-profile-2995
Jul 6, 2026
Merged

feat(review): add cached repo quality-culture profile as AI-review grounding#3802
JSONbored merged 3 commits into
mainfrom
feat/repo-culture-profile-2995

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • Implements issue feat(review): infer a cached per-repo quality-culture profile as AI-review grounding context #2995: infer a cached per-repo quality-culture profile from the repo's own merge history and feed it into the AI reviewer's prompt as additive grounding context.
  • New shared module src/review/repo-culture-profile.ts (extractRepoCultureProfile, deriveRepoCultureProfile) derives a deterministic profile — typical merged-PR size (median changed-file count, banded tiny/small/medium/large), typical PR description length, and common accepted labels — purely from recent_merged_pull_requests rows already stored by this engine. Below 5 sampled merged PRs it returns an explicit present: false insufficient-data branch, never a partial guess.
  • Cached per repo in the existing signal_snapshots table (same mechanism signals/focus-manifest-loader.ts already uses for the manifest cache), invalidated on either a 6-hour TTL or a merged-PR-count drift check (a cheap COUNT(*), not a row re-scan) — matching the issue's "TTL or new commits" invalidation ask with the simplest signal already available.
  • New host adapter src/review/repo-culture-profile-wire.ts (mirrors review/rag-wire.ts's structure exactly) formats the profile into a self-labelled, reference-only prompt block and is gated by a new GITTENSORY_REVIEW_CULTURE_PROFILE env flag plus a new per-repo .gittensory.yml review.culture_profile: true opt-in (parsed/resolved in signals/focus-manifest.ts the same way review.effort_score/review.changed_files_summary are). Both default off — the reviewer prompt is byte-identical until a repo deliberately opts in on top of the global flag being enabled.
  • Wired into services/ai-review.ts (GittensoryAiReviewInput.cultureProfileContext, appended in buildUserPrompt right after the existing RAG section) and into queue/processors.ts's runAiReviewForAdvisory, following the exact same fetch/gate/pass-through pattern as the RAG feature. Explicitly ADVISORY GROUNDING ONLY — it never becomes a gate/scoring input and never changes the structured AI-review output contract.
  • Bumped AI_REVIEW_CACHE_INPUT_VERSION (ai-review-input:v1v2) since the AI-review result cache's fingerprint features object gained a cultureProfile member; every field is now explicitly enumerated (not passed through raw) so a future new feature key can't silently invalidate every existing cache entry again.
  • Confirmed via investigation (per the issue) that the existing src/review/repo-profile.ts (extractRepoProfile) is for a different epic (Roadmap: repo-specific CLAUDE.md/AGENT.md + skills generation & maintenance #2993/feat(review): extract a codebase-grounded repo profile from RAG + signals #2999, repo-doc/CLAUDE.md generation from the RAG code index) and does not carry PR-size/label/history signals — this PR does not repurpose it, it adds a new, narrowly-scoped module for the commit/PR-history signal this issue actually asks for.
  • Design decision (no ambiguity to escalate, noted for transparency): PR "size" is derived from changedFiles.length (already reliably populated by the existing merged-PR backfill), not from additions/deletions in the untyped raw GitHub payload, since the latter isn't part of the typed GitHubPullRequestPayload shape and would be a less certain source of truth.

Scope

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck
  • npm run test:coverage (targeted, on the touched/new files — see coverage numbers below); 100% statements/branches/functions/lines on the two new modules (repo-culture-profile.ts, repo-culture-profile-wire.ts).
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint (0 errors; only the pre-existing repo-wide react-refresh/only-export-components warnings, unrelated to this change)
  • npm run ui:typecheck / npm run ui:buildskipped: both fail in this sandbox with Cannot find package '@lovable.dev/vite-tanstack-config', reproduced identically on a clean origin/main checkout with no changes applied (a private-registry package unavailable in this environment), so it is a pre-existing local-environment limitation, not something introduced by this PR.
  • npm audit --audit-level=moderate (0 vulnerabilities)
  • New/changed behavior has unit tests for both branches of every conditional touched (sparse-history fallback vs. populated profile; cache hit vs. miss vs. TTL-stale vs. count-drift-stale; malformed/sparse cached-payload reconstruction; fail-safe on a throwing storage read/write; flag-on/flag-off prompt parity).

Also ran, beyond the template list, since this touches generated config surfaces: npm run cf-typegen (new GITTENSORY_REVIEW_CULTURE_PROFILE wrangler var), npm run docs:drift-check, npm run db:schema-drift:check, npm run db:migrations:check, npm run ui:openapi:settings-parity — all clean, no drift.

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; the new prompt section is explicitly labelled reference-only/non-binding and is never surfaced publicly (it only ever reaches the AI reviewer's own prompt).
  • [N/A] No auth, cookie, CORS, GitHub App, Cloudflare session changes.
  • [N/A] No API/OpenAPI/MCP surface change (a .gittensory.yml-only + env-flag-only knob, same pattern as review.effort_score).
  • [N/A] No UI changes beyond two doc pages (docs.tuning.tsx, docs.privacy-security.tsx) documenting the new env flag in prose, matching the existing flag-list format exactly — no visual/interactive change.
  • Public docs updated: .gittensory.yml.example / config/examples/gittensory.full.yml (new review.culture_profile field documented), plus the two UI docs routes above.

Notes

  • Rebased cleanly onto latest origin/main (including a real merge conflict against the concurrently-merged Boundary-safe test generation #1972 boundary-safe test-generation advisory PR, which added sibling fields to the same FocusManifestReviewConfig literals — resolved by combining both PRs' fields, verified with a full re-run of the affected test suites post-rebase).
  • Kept the diff scoped to exactly this issue: no adjacent refactors, no touching the Autonomous Miner System's merge-bar inference (out of scope per the issue's own phrasing — "the two consumers never drift" only requires the extractor be importable by both, which it now is; wiring the miner side is left to that system's own follow-up).

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 6, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gittensory-ui 94cbd15 Commit Preview URL

Branch Preview URL
Jul 06 2026, 12:36 PM

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.40%. Comparing base (ee686e0) to head (94cbd15).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3802      +/-   ##
==========================================
+ Coverage   93.38%   93.40%   +0.01%     
==========================================
  Files         323      325       +2     
  Lines       32727    32823      +96     
  Branches    11982    12022      +40     
==========================================
+ Hits        30563    30659      +96     
  Misses       1530     1530              
  Partials      634      634              
Files with missing lines Coverage Δ
src/queue/processors.ts 94.43% <100.00%> (+<0.01%) ⬆️
src/review/ai-review-cache-input.ts 100.00% <100.00%> (ø)
src/review/repo-culture-profile-wire.ts 100.00% <100.00%> (ø)
src/review/repo-culture-profile.ts 100.00% <100.00%> (ø)
src/services/ai-review.ts 97.01% <100.00%> (+0.01%) ⬆️
src/signals/focus-manifest.ts 99.12% <100.00%> (+<0.01%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/review/repo-culture-profile-wire.ts
@superagent-security superagent-security Bot added the pr:flagged PR flagged for review by security analysis. label Jul 6, 2026
@JSONbored
JSONbored force-pushed the feat/repo-culture-profile-2995 branch from 257001e to 2c1f68e Compare July 6, 2026 11:39
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@superagent-security superagent-security Bot removed the pr:flagged PR flagged for review by security analysis. label Jul 6, 2026
@JSONbored
JSONbored force-pushed the feat/repo-culture-profile-2995 branch from 2c1f68e to c704a1c Compare July 6, 2026 11:42
@JSONbored

Copy link
Copy Markdown
Owner Author

Fixed both real issues found by CI:

  1. `cf-typegen` drift — regenerated `worker-configuration.d.ts` (stale against the wrangler/workers-types versions main has moved to since this branch was last rebased).
  2. Superagent P3 — `entry.label` (user-controlled GitHub label text from merged PRs) flowed into the AI reviewer prompt with no sanitization. Fixed via the existing `neutralizePromptInjection` defense (same one `safeReviewTitle` already uses for untrusted PR titles).
  3. `codecov/patch` (97.98%, 2 partial branches) — added the missing `review.culture_profile` round-trip test in `focus-manifest.test.ts` (every sibling boolean flag already has one), and a new webhook-level test covering `dynamicReviewFeatures.cultureProfile` — unlike its env-only siblings (grounding/rag/enrichment/reputation), this one is dual-gated by both the global env flag AND the per-repo manifest opt-in, so no existing test drove both true through a real review.

1207 tests pass across all touched/related files, typecheck/actionlint/audit clean.

@JSONbored
JSONbored force-pushed the feat/repo-culture-profile-2995 branch from c704a1c to 22a896c Compare July 6, 2026 12:05
@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 6, 2026
@loopover-orb

loopover-orb Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Important

🟪🟪🟪🟪🟪🟪🟪🟪🟪🟪🟪🟪

🔍 Gittensory is reviewing…

AI analysis is in progress. This comment will update when the review is complete.

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

JSONbored added 3 commits July 6, 2026 05:29
…ounding (#2995)

Derives a deterministic per-repo signal (typical merged-PR size, common
accepted labels, description-length norms) from recent_merged_pull_requests
and caches it via signal_snapshots with TTL + merged-PR-count invalidation,
mirroring the focus-manifest cache pattern. Wired additively into the AI
reviewer's user prompt alongside RAG/grounding (review/repo-culture-profile*
.ts), gated by the GITTENSORY_REVIEW_CULTURE_PROFILE env flag and the new
review.culture_profile .gittensory.yml opt-in -- both default off, so the
change is byte-identical until deliberately enabled. Never a gate/scoring
input; degrades silently to no context on sparse history or any error.

Validated: npm run typecheck, npx vitest run on the new + touched test
files, and the affected regression suites (queue, ai-review-cache,
focus-manifest, signals-coverage) all green with 100% branch coverage on
the two new modules.

# Conflicts:
#	.gittensory.yml.example
#	apps/gittensory-ui/src/routes/docs.privacy-security.tsx
#	apps/gittensory-ui/src/routes/docs.tuning.tsx
#	config/examples/gittensory.full.yml
#	src/env.d.ts
#	src/queue/processors.ts
#	src/services/ai-review.ts
#	src/signals/focus-manifest.ts
#	test/unit/focus-manifest.test.ts
#	test/unit/signals-coverage.test.ts
#	worker-configuration.d.ts
#	wrangler.jsonc
…lose 2 coverage gaps

Superagent (P3): entry.label in formatRepoCultureProfileSection came
straight from user-controlled GitHub label text on merged PRs, with no
sanitization before it reached the AI reviewer prompt. Neutralize it
through the existing prompt-injection defense (neutralizePromptInjection),
the same way safeReviewTitle already protects an untrusted PR title.

Also closes 2 partial-branch codecov/patch gaps: focus-manifest.ts's
reviewConfigToJson had no round-trip test for review.culture_profile
(mirrors every sibling boolean flag's existing test), and
processors.ts's dynamicReviewFeatures.cultureProfile — unlike its
env-only siblings (grounding/rag/enrichment/reputation) — is dual-gated
by both the global env flag AND the per-repo manifest opt-in, so no
existing test drove both true through a real webhook.
@JSONbored
JSONbored merged commit 839398c into main Jul 6, 2026
12 checks passed
@JSONbored
JSONbored deleted the feat/repo-culture-profile-2995 branch July 6, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. manual-review Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

feat(review): infer a cached per-repo quality-culture profile as AI-review grounding context

1 participant