Skip to content

fix(review): scope the bare-score public-safety check per repo (metagraphed#8038)#8562

Merged
JSONbored merged 3 commits into
mainfrom
fix/public-score-terms-repo-scoping-clean
Jul 24, 2026
Merged

fix(review): scope the bare-score public-safety check per repo (metagraphed#8038)#8562
JSONbored merged 3 commits into
mainfrom
fix/public-score-terms-repo-scoping-clean

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

Live, recurring issue: metagraphed#8038 (and many others) got "The AI review returned non-blocking notes for this change but did not include a separate narrative summary" instead of a real review write-up, despite the model producing one.

Root cause: sanitizePublicComment throws (by design — never redacts) whenever public-facing AI text matches a bare \bscore\w*\b, to stop loopover's own private gittensor miner trust/reward values from leaking. toPublicSafe catches that throw and returns null, and composeAdvisoryNotes silently discards the entire narrative assessment in favor of the generic fallback text. This filter is applied identically across every repo the shared engine serves — but metagraphed's own public schema legitimately has fields named totalScore, credibility, baseTotalScore, etc. Any AI review that naturally describes this code in prose ("the resolver filters results by their score...") is near-certain to trip the filter and lose its whole write-up.

Fix, scoped as narrowly as possible:

  • sanitizePublicComment gains an optional { allowBareScoreTerm?: boolean }, default false (today's unchanged behavior for every existing caller that doesn't pass it). Every other forbidden phrase — wallet, hotkey, coldkey, trust score, reward, scoreability, etc. — stays enforced unconditionally, everywhere, regardless of this flag. Only the over-broad bare-word check is ever relaxable, and only where a caller has positively confirmed it's safe.
  • New isPublicScoreTermSafeForRepo(env, repoFullName): a fail-closed (deny-by-default), config-as-code repo allowlist (LOOPOVER_PUBLIC_SCORE_TERMS_ALLOWED_REPOS, comma/whitespace owner/repo list). Unset ⇒ the check stays enforced for every repo, unchanged from today. Deliberately no */all wildcard (unlike the MCP allowlists) — this is a safety-relevant exemption, and a blanket opt-in-everything value would silently cover a future repo that does have private trust/reward data.
  • composeAdvisoryNotes threads the flag through to its 3 relevant toPublicSafe calls (assessment, blockers, nits) only — the other 11 toPublicSafe call sites in ai-review.ts (blocker titles, tie-break judge output, consensus titles) are untouched.
  • runLoopOverAiReview resolves the flag once, from isPublicScoreTermSafeForRepo(env, input.repoFullName).

This is additive and inert until an operator sets the env var for a specific repo — no behavior changes for any repo today.

Validation

  • New tests in queue-intelligence.test.ts: the option passes a bare "score" through when true; still throws when false; every OTHER forbidden phrase still throws even when the flag is true; isPublicScoreTermSafeForRepo's allow/deny/no-wildcard behavior.
  • New regression tests in ai-review.test.ts: a bare "score" mention drops the whole assessment by default but survives when allowlisted (with a surviving, score-free nit proving the drop doesn't silently empty unrelated findings); the explicit-phrase bans (raw trust score) stay enforced even with the flag on.
  • npm run typecheck clean; npm run test:coverage (full, unsharded): all tests passing.

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Logic backtest

Replayed 0 historical case(s) for linked_issue_scope_mismatch through the base (c4a6426) and head (0a076df) versions of its detection logic (corpus checksum 4f53cda18c2b).

Backtest comparison: linked_issue_scope_mismatch

Verdict: unchanged — no comparable axis moved.

Advisory only — this check never blocks merge (#8105).

@JSONbored JSONbored self-assigned this Jul 24, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

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

…raphed#8038)

sanitizePublicComment throws (never redacts) whenever public-facing AI text
matches a bare \bscore\w*\b, to stop loopover's own private gittensor miner
trust/reward VALUES from leaking. toPublicSafe catches the throw and returns
null, and composeAdvisoryNotes silently discards the whole narrative
assessment in favor of the generic "did not include a separate narrative
summary" fallback. This filter applied identically across every repo the
shared engine serves, but metagraphed's own public schema legitimately has
fields named totalScore/credibility/baseTotalScore -- any AI review that
naturally describes this code in prose is near-certain to trip the filter
and lose its whole write-up. Observed live, recurring.

sanitizePublicComment gains an optional allowBareScoreTerm flag, default
false (unchanged behavior for every existing caller). Every OTHER forbidden
phrase (wallet, hotkey, coldkey, trust score, reward, scoreability, ...)
stays enforced unconditionally regardless of this flag -- only the
over-broad bare-word check is ever relaxable. New
isPublicScoreTermSafeForRepo resolves a fail-closed, config-as-code repo
allowlist (LOOPOVER_PUBLIC_SCORE_TERMS_ALLOWED_REPOS) with no '*'/'all'
wildcard, since a blanket opt-in would silently cover a future repo that
DOES have private trust/reward data. composeAdvisoryNotes threads the flag
through to its 3 relevant call sites only; the other 11 toPublicSafe call
sites in ai-review.ts are untouched.

Additive and inert until an operator sets the env var for a specific repo.
@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 24, 2026
@loopover-orb

loopover-orb Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - fixes required

Review updated: 2026-07-24 21:22:44 UTC

5 files · 1 AI reviewer · 2 blockers · CI failing · unstable

🛑 Suggested Action - Manual Review

Review summary
The AI review returned non-blocking notes for this change but did not include a separate narrative summary. Review the nits below before deciding this PR.

Nits — 5 non-blocking
  • src/queue-intelligence.ts's new `isPublicScoreTermSafeForRepo` and `sanitizePublicComment` doc comments are quite long relative to the function bodies; could be trimmed without losing the safety rationale.
  • The magic number 8038 appears only in a doc comment reference (metagraphed#8038), not in logic, so it's not a real magic-number concern despite the external brief flagging it.
  • Consider whether `LOOPOVER_PUBLIC_SCORE_TERMS_ALLOWED_REPOS` documentation in env.d.ts and queue-intelligence.ts could link to each other via a shared anchor for discoverability.
  • src/queue-intelligence.ts:157 — the allowlist parsing duplicates the comma/whitespace-split pattern used elsewhere (MCP allowlists); if that pattern changes again, keep both in sync manually since they're intentionally separate per the doc comment.
  • test/unit/ai-review.test.ts's two new REGRESSION tests are a good template if other repo-scoped safety exemptions are added later.

Why this is blocked

  • No linked issue detected: No closing reference or linked issue number was found in the PR metadata/body. — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • Maintainer requires a linked issue: This repo's maintainer focus manifest requires every PR to reference a tracked issue. — Link the relevant issue (for example Closes #123) before opening the PR.
📋 Copy for AI agents — paste into your coding agent
Fix the following blocker(s) from this PR review:

1. No linked issue detected: No closing reference or linked issue number was found in the PR metadata/body. — If this PR is intended to solve an issue, link it explicitly in the PR body.

2. Maintainer requires a linked issue: This repo's maintainer focus manifest requires every PR to reference a tracked issue. — Link the relevant issue (for example `Closes #123`) before opening the PR.

CI checks failing

  • codecov/patch — 91.66% of diff hit (target 99.00%)

Decision drivers

  • ❌ Code review — 2 blockers (1 reviewer)
  • ❌ Gate result — Blocking (Repo-configured hard blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
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: 13 registered-repo PR(s), 13 merged, 272 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 13 PR(s), 272 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, Ruby, Go, MDX, Shell, Solidity, JavaScript
  • Official Gittensor activity: 13 PR(s), 272 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Then work through the remaining 2 steps in the Signals table above.
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.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 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 LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.36364% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.93%. Comparing base (bd273c1) to head (0a076df).
⚠️ Report is 5 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/queue/processors.ts 70.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8562      +/-   ##
==========================================
+ Coverage   89.58%   91.93%   +2.35%     
==========================================
  Files          97      795     +698     
  Lines       22706    79669   +56963     
  Branches     3872    24075   +20203     
==========================================
+ Hits        20341    73246   +52905     
- Misses       2187     5309    +3122     
- Partials      178     1114     +936     
Flag Coverage Δ
backend 92.87% <86.36%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/queue-intelligence.ts 100.00% <100.00%> (ø)
src/services/ai-review.ts 97.08% <100.00%> (ø)
src/queue/processors.ts 95.66% <70.00%> (ø)

... and 695 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 24, 2026
…ate stays unknown

refreshLiveMergeState's own short inline retry (previous commit, ~4s total)
resolves most GitHub mergeable_state "still computing" reads within the
same pass, but not all -- on a large PR or under load, GitHub can take
longer. Without this, the only remaining catch-up was the periodic
agent-regate-sweep, which is NOT a reliable fixed interval: it throttles
under GitHub REST-budget backpressure and skips re-arming while a previous
sweep trigger is still in flight (index.ts's own backpressure comment) --
under sustained cross-repo load this can stretch well past minutes, during
which an overlapping sibling PR can land first and base-conflict the
original PR out from under it (observed live, metagraphed#8037).

Schedules ONE targeted, single-PR follow-up (60s delay) specifically when a
PR holds because mergeableState is "unknown" -- the one genuinely transient
value; "dirty"/"blocked"/"behind" are real, stable holds a re-check
moments later would only reproduce, so they're deliberately excluded.
Reuses the exact delayed-JOBS.send + check-then-claim-after-success dedup
pattern scheduleTrailingIssueLinkedReReview already established in this
file for an analogous problem, not a new mechanism.

Also closes a Codecov branch-coverage gap on the prior score-terms commit:
composeAdvisoryNotes' isPublicScoreTermSafeForRepo call site had only its
false arm exercised end-to-end through runLoopOverAiReview; added the
companion allowed-repo case.
@JSONbored
JSONbored force-pushed the fix/public-score-terms-repo-scoping-clean branch from afc09c0 to f60a14c Compare July 24, 2026 21:23
… (Codecov branch gap)

The composeAdvisoryNotes(...) ?? composeFallbackAdvisoryNotes(fallbackNotes)
line's right-hand branch was never exercised through runLoopOverAiReview --
the prior score-terms tests only ever hit composeAdvisoryNotes' own internal
non-null fallback text, never this outer nullish-coalescing fallthrough.
Mirrors the existing "composeAdvisoryNotes returns null when no assessment
or finding is public-safe" unit fixture, driven end-to-end instead.
@JSONbored
JSONbored merged commit a864c0e into main Jul 24, 2026
6 checks passed
@JSONbored
JSONbored deleted the fix/public-score-terms-repo-scoping-clean branch July 24, 2026 21:34
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. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant