Skip to content

fix(miner): drop discovery-index candidates whose repo bans AI contributions (#9680) - #9907

Closed
kai392 wants to merge 1 commit into
JSONbored:mainfrom
kai392:fix/9680-drop-ai-banned-index
Closed

fix(miner): drop discovery-index candidates whose repo bans AI contributions (#9680)#9907
kai392 wants to merge 1 commit into
JSONbored:mainfrom
kai392:fix/9680-drop-ai-banned-index

Conversation

@kai392

@kai392 kai392 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What

supplementWithDiscoveryIndex folded hosted discovery-index candidates into the local fan-out with dedupe as the only filter. The index client deliberately preserves a repo's AI-contribution ban (normalizeDiscoveryIndexCandidate writes aiPolicyAllowed: candidate.aiPolicyAllowed !== false), but nothing downstream re-checks it — and the as RawCandidateIssue cast (whose aiPolicyAllowed is declared as the literal true) laundered a false straight through. So an index-served candidate flagged "this repo bans automated contributions" was ranked and enqueued into the miner's own portfolio backlog, where the loop would later claim and attempt it. The local path enforces the ban hard (fetchTargetIssues: if (!verdict.allowed) return []); the index path did not.

How

  • discover-cli.ts: filter out aiPolicyAllowed === false candidates before the dedupe filter / cast, mirroring fetchTargetIssues's own drop. The predicate is !== false, so a candidate that omits the field entirely is still kept (matching normalizeDiscoveryIndexCandidate's default).
  • discovery-index-client.ts: recordDiscoveryTelemetry now accepts an optional droppedAiBanned count, spread conditionally into the log payload so every existing caller keeps its exact { event, outcome } shape; the discover_query telemetry call reports the number dropped.

No change to the local fan-out path, the ranker, portfolio-discovery.ts, or RawCandidateIssue's declared type.

Tests

Two named cases in test/unit/miner-discover-cli.test.ts:

  1. One index candidate aiPolicyAllowed: false + one true → only the allowed one reaches the ranked/enqueued output, and droppedAiBanned: 1 is reported (fails against the current code).
  2. A candidate that omits aiPolicyAllowed entirely is still kept (proves the filter didn't become a fail-closed drop of every index candidate).

Together they cover all three arms of aiPolicyAllowed !== false (dropped / kept / field-absent) plus the telemetry count. The shared-module test miner-discovery-index-client.test.ts (which asserts the exact telemetry payload) still passes.

Closes #9680

@kai392
kai392 requested a review from JSONbored as a code owner July 29, 2026 21:29
@loopover-orb

loopover-orb Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - fixes required

Review updated: 2026-07-29 21:35:09 UTC

3 files · 1 AI reviewer · no blockers · CI failing · unstable

🛑 Suggested Action - Fix Blockers

Review summary
This closes a real hole: `supplementWithDiscoveryIndex` in discover-cli.ts previously folded hosted discovery-index candidates into the local fan-out with only dedupe as a filter, letting a candidate flagged `aiPolicyAllowed: false` (an explicit AI-contribution ban) get laundered through the `as RawCandidateIssue` cast and enqueued into the miner's backlog. The fix filters `response.candidates` on `aiPolicyAllowed !== false` before dedupe/cast, matches the local path's fail-closed posture in `fetchTargetIssues`, and threads a `droppedAiBanned` count through `recordDiscoveryTelemetry` via a conditional spread that preserves the exact `{event, outcome}` shape for existing callers. The two new tests exercise the drop case, the kept-when-omitted case, and the telemetry count, and directly correspond to the described defect and its reachable path (an index-served AI-banned issue reaching `payload.ranked`/the portfolio queue).

Nits — 3 non-blocking
  • nit: the large inline comment block in discover-cli.ts:190-196 repeats most of what the JSDoc above the function already documents; could be trimmed to the non-obvious part (the cast laundering `false` through a `true`-typed field).
  • nit: `droppedAiBanned` is computed but not included in the `DiscoverResult`/JSON payload returned to callers — only exposed via telemetry, so an operator inspecting `--json` output has no visibility into how many candidates were dropped for this run.
  • Consider surfacing `droppedAiBanned` in the CLI's `--json`/text summary (renderDiscoverSummary) alongside the existing eligibility-exclusion reporting, for parity with how excluded candidates are already surfaced to a human operator.

CI checks failing

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

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #9680
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 (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 95 registered-repo PR(s), 50 merged, 7 issue(s).
Contributor context ✅ Confirmed Gittensor contributor kai392; Gittensor profile; 95 PR(s), 7 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The diff filters out candidates with aiPolicyAllowed === false before dedupe/cast in supplementWithDiscoveryIndex, threads a droppedAiBanned count through recordDiscoveryTelemetry's existing discover_query call, and adds the two required regression tests covering dropped/kept/field-absent arms plus the telemetry count assertion.

Review context
  • Author: kai392
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, Cuda, JavaScript, Kotlin, MDX, Perl, Ruby, TypeScript
  • Official Gittensor activity: 95 PR(s), 7 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
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

@superagent-security

Copy link
Copy Markdown
Contributor

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

…butions (JSONbored#9680)

`supplementWithDiscoveryIndex` folded hosted-index candidates into the
local fan-out with dedupe as the only filter. The index client deliberately
preserves a repo's AI-contribution ban (`aiPolicyAllowed !== false`), but
nothing downstream re-checks it -- the `as RawCandidateIssue` cast (the type
declares `aiPolicyAllowed: true`) laundered a `false` straight through, so an
AI-banned repo's issue was ranked and enqueued into the miner's own
portfolio backlog, where the loop would later claim and attempt it. The
local path enforces the ban hard (`fetchTargetIssues`: `if (!verdict.allowed)
return []`); the index path did not.

- discover-cli.ts: filter out `aiPolicyAllowed === false` candidates before
  the dedupe/cast, using `!== false` so a candidate omitting the field is
  still kept (matching normalizeDiscoveryIndexCandidate's own default).
- discovery-index-client.ts: `recordDiscoveryTelemetry` now carries an
  optional `droppedAiBanned` count, spread conditionally so existing callers
  keep their exact `{ event, outcome }` payload; the `discover_query` call
  reports the number dropped.

Two named cases: one index candidate `aiPolicyAllowed:false` + one `true` →
only the allowed one is ranked and `droppedAiBanned:1` is reported (fails
against current code); a candidate omitting the field is still kept.

Closes JSONbored#9680

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 29, 2026
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.50000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 79.37%. Comparing base (8b44697) to head (4939b33).

Files with missing lines Patch % Lines
...kages/loopover-miner/lib/discovery-index-client.ts 66.66% 0 Missing and 1 partial ⚠️

❌ Your patch check has failed because the patch coverage (87.50%) is below the target coverage (99.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9907      +/-   ##
==========================================
+ Coverage   79.29%   79.37%   +0.08%     
==========================================
  Files         281      283       +2     
  Lines       58566    58868     +302     
  Branches     6785     6898     +113     
==========================================
+ Hits        46440    46728     +288     
- Misses      11843    11844       +1     
- Partials      283      296      +13     
Flag Coverage Δ
backend 95.36% <87.50%> (?)

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

Files with missing lines Coverage Δ
packages/loopover-miner/lib/discover-cli.ts 94.86% <100.00%> (ø)
...kages/loopover-miner/lib/discovery-index-client.ts 97.95% <66.66%> (ø)

@loopover-orb

loopover-orb Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

LoopOver is closing this pull request on the maintainer's behalf (CI is failing (codecov/patch)). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed.

@loopover-orb loopover-orb Bot closed this Jul 29, 2026
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.

miner(discover): drop discovery-index candidates whose repo bans AI contributions

2 participants