Skip to content

feat(enrichment): blame-to-PR regression linker analyzer (#2034)#2620

Merged
JSONbored merged 7 commits into
JSONbored:mainfrom
nickmopen:feat/blame-link-analyzer
Jul 2, 2026
Merged

feat(enrichment): blame-to-PR regression linker analyzer (#2034)#2620
JSONbored merged 7 commits into
JSONbored:mainfrom
nickmopen:feat/blame-link-analyzer

Conversation

@nickmopen

Copy link
Copy Markdown
Contributor

Closes #2034 (part of #1499).

New REES github-light analyzer: for files a PR modifies or deletes, it resolves which prior PR most recently introduced that region and surfaces it — giving the reviewer instant context on what the change is altering. Not per-line blame (no checkout/blame API): it attributes each touched file's most recent base-branch commit and maps it to its PR. Bounded and fail-safe.

Deliverables

  • review-enrichment/src/types.tsBlameLinkFinding ({ file, line, introducedByPr?, introducedByShaPrefix? }, SHA prefix only, never contents) + blameLink? on BriefFindings.
  • review-enrichment/src/analyzers/blame-link.tsfirstTouchedOldLine() parses the unified-diff patch for a representative modified/deleted old line; per file it reads the path's most recent commit on baseSha and maps it to a PR via the commit→PR association API (injected fetch). Strict maxFilesProbed (6) + maxLookups (12) caps; emits partial on cap; skips added files & pure additions (nothing to blame); no-token / bad-slug / fetch-error → no finding, never throws.
  • registry.ts — descriptor (category: history, cost: github-light, requires: ['files','github-token']) with an inline render().
  • render.ts — dispatches the blameLink section via renderDescriptorSection.
  • Regenerated analyzer-metadata.json, .env.example, and the UI metadata; added blameLink to the registry meta-test's expected list.
  • test/blame-link.test.ts — resolved originating PR (+ brief render), SHA-only fallback, unresolvable line (no finding), added/pure-addition skip, file-probe cap, and token-absent skip; plus pure firstTouchedOldLine cases.

Validation

Full review-enrichment suite (build + sourcemaps + metadata --check + node:test):

ℹ tests 400
ℹ pass 400
ℹ fail 0

Includes the 7 blame-link tests and the "generated analyzer metadata matches the runtime registry and profiles" check, so the metadata/.env/UI regeneration is consistent with the descriptor.

)

New REES github-light analyzer: for files a PR modifies/deletes, resolves which
prior PR most recently introduced that region and surfaces it, giving the reviewer
instant context on what the change is altering. Bounded + fail-safe.

- types.ts: BlameLinkFinding ({ file, line, introducedByPr?, introducedByShaPrefix? })
  + blameLink? key on BriefFindings (sha prefix only, never contents).
- analyzers/blame-link.ts: firstTouchedOldLine() parses the patch for a
  representative modified/deleted old line; per file, reads the path's most recent
  base-branch commit and maps it to its PR via the commit->PR association API.
  Strict maxFilesProbed (6) + maxLookups (12) caps; emits partial on cap; skips
  added files and pure additions; no-token/bad-slug/fetch-error -> no finding.
- registry.ts: descriptor (category history, cost github-light, requires
  files+github-token) with an inline render().
- render.ts: dispatch the blameLink section via renderDescriptorSection.
- Regenerated analyzer-metadata.json, .env.example, and the UI metadata; added
  blameLink to the registry meta-test's expected list.
- test/blame-link.test.ts: resolved PR, sha-only fallback, unresolvable (no
  finding), added/pure-addition skip, file-probe cap, token-absent skip.

review-enrichment test suite: 400/400 pass.
@nickmopen
nickmopen requested a review from JSONbored as a code owner July 2, 2026 16:24
@dosubot dosubot Bot added the size:L label Jul 2, 2026
@loopover-orb

loopover-orb Bot commented Jul 2, 2026

Copy link
Copy Markdown

Warning

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

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-02 23:16:50 UTC

9 files · 1 AI reviewer · no blockers · readiness 60/100 · CI green · clean

⏸️ Suggested Action - Manual Review

Review summary
This adds a bounded REES analyzer that turns changed-file patches into file-level last-touch history and wires it through the registry, generated metadata, render path, and tests. The implementation is coherent with the existing churn-hotspot analyzer pattern: it skips added/generated files, anchors lookups to the base SHA, falls back to a SHA prefix when the commit has no associated PR, and keeps the rendered copy from claiming per-line blame. I do not see a reachable correctness break in the visible diff.

Nits — 5 non-blocking
  • nit: review-enrichment/src/analyzers/blame-link.ts:163 skips generated/binary paths using the displayed `file.path`, but for renamed files the actual lookup is `previousPath`, so a generated old path renamed into a normal-looking path can still spend GitHub calls; consider checking `lookupPath` before enqueueing renamed candidates.
  • nit: review-enrichment/src/analyzers/blame-link.ts:186 pushes a finding when the PR lookup is skipped by the lookup cap, which is intentional, but there is no explicit marker that the PR association was not attempted versus absent; consider a small internal comment or test assertion for that cap-edge fallback so future refactors preserve the distinction.
  • In review-enrichment/src/analyzers/blame-link.ts:163, compute `lookupPath` before the skip decision for renamed files and apply `SKIP_RE` to the path actually queried.
  • Add a focused test for the `lookups === MAX_LOOKUPS - 1` edge in review-enrichment/test/blame-link.test.ts so the SHA-only partial result path stays covered.
  • Readiness score is below the configured threshold — Use the readiness panel as advisory maintainer context; the score does not block this PR.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #2034
Related work ⚠️ 3 scoped overlaps Top overlaps are listed below; lower-confidence bulk is hidden.
Change scope ❌ 8/20 High review scope from cached public metadata (size label size:L; 1 linked issue).
Validation posture ❌ 5/25 Preflight is holding this PR: the review lane is unavailable, so it is not ready for automated review.
Contributor workload ✅ 10/10 Author activity: 100 registered-repo PR(s), 65 merged, 1 issue(s).
Contributor context ✅ Confirmed Gittensor contributor nickmopen; Gittensor profile; 100 PR(s), 1 issue(s).
Gate result ✅ Passing No configured blocker found.
Review context
Contributor next steps
  • Review top overlaps.
  • Add a concise scope and risk note.
  • Await review-lane availability.
  • Refresh registry data or choose a registered active repo.
  • Check active issues and PRs before submitting.
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

@loopover-orb loopover-orb Bot added gittensor gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. labels Jul 2, 2026
…parser (JSONbored#2034)

firstTouchedOldLine treated a `\ No newline at end of file` marker line as a
context line, wrongly advancing the old-file line counter. Skip it as metadata
(like the stray ---/+++ headers). Added a test covering the marker.

review-enrichment: 400/400 pass.
…ONbored#2034)

Address review nits:
- Handle removed files without requiring a patch: status === "removed" now
  blames via the file path alone (anchored to line 1), so a deleted file with a
  binary/truncated diff is no longer silently skipped despite the analyzer
  claiming to cover deletes.
- Render the coordinate explicitly as `(old line N)` instead of `file:line`,
  which read like a current line — the value is the OLD-file line.
- Give the commit→PR association call its own diagnostics subcall
  ("github-commit-pulls") instead of sharing "github-commits", for precise
  per-subcall diagnostics (shared endpoint budget unchanged).
- Tests: a shifted-hunk case pinning the old-line semantics (+ its render) and a
  patchless removed-file case.

review-enrichment: 402/402 pass.
…tighter cap test (JSONbored#2034)

Final review nits (all non-blocking):
- Render says the file "was most recently touched by" instead of "introduced by"
  a specific line — accurate to the file-level path-history lookup this does.
- Give the commit→PR association call its own endpointCategory
  ("github-commit-pulls") for precise rate attribution (loop-level MAX_LOOKUPS
  still bounds the total).
- Cap test now asserts exactly 12 fetch calls and that files past the probe cap
  (f6..f9) are never queried, pinning the bound.

review-enrichment: 402/402 pass.
…t line origin (JSONbored#2034)

Resolve the reviewer's false-attribution concern: the analyzer only does a
file-level latest-commit lookup, so it must not word its result as introducing a
specific line. Make the claim match the behavior (no line-aware blame added).

- Rename BlameLinkFinding.introducedBy{Pr,ShaPrefix} → lastTouchedBy{Pr,ShaPrefix};
  the `line` field is now documented as a pointer to where THIS PR changes the
  file, not a line attributed to the PR.
- Reframe type doc, analyzer docstring, descriptor title/docs, and the rendered
  section as "last PR to touch each file — file-level context, bounded scan".
- Harden firstTouchedOldLine: only a space-prefixed context line advances the old
  cursor; additions, the `\` marker, and malformed/extended text no longer count,
  so a garbled patch fails closed.
- Tests: rename fields; add a false-attribution regression (latest file commit
  touched a different region than the changed line → reported file-level, never
  attributed to the line) and a malformed-patch fail-closed case.

review-enrichment: 403/403 pass.
…SONbored#2034)

A renamed file lives under its OLD path in the base tree, so blame-link now looks
up commit history via `previousPath` for status === "renamed" (falling back to
line 1 when a pure rename carries no usable patch), while still displaying the new
path to the reviewer. Also trims the rendered section title (was em-dash-heavy and
longer than neighboring headings).

- Test: a renamed file is probed under its old path and rendered as the new path.

review-enrichment: 404/404 pass.
…-`/`---` content (JSONbored#2034)

The previous hardening added a `!startsWith("---")` guard to firstTouchedOldLine,
but inside a hunk that wrongly skips a real deletion whose CONTENT begins with two
hyphens (git renders a deleted `--x` line as `---x`). File headers only appear
before a hunk, which the inHunk flag already excludes, so the guard was both wrong
and unnecessary — dropped it. Added assertions for `---`/`--`-content deletions.

review-enrichment: 404/404 pass.
@dosubot dosubot Bot added the lgtm label Jul 2, 2026
@JSONbored
JSONbored merged commit 044c77a into JSONbored:main Jul 2, 2026
8 checks passed
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.

Development

Successfully merging this pull request may close these issues.

feat(enrichment): blame-to-PR regression linker analyzer

2 participants