Skip to content

feat(miner-extension): add read-only issue-page opportunity badge - #4559

Closed
RealDiligent wants to merge 3 commits into
JSONbored:mainfrom
RealDiligent:feat/miner-extension-opportunity-badge-4308
Closed

feat(miner-extension): add read-only issue-page opportunity badge#4559
RealDiligent wants to merge 3 commits into
JSONbored:mainfrom
RealDiligent:feat/miner-extension-opportunity-badge-4308

Conversation

@RealDiligent

Copy link
Copy Markdown
Contributor

Summary

  • Adds a read-only GitHub issue-page opportunity badge to apps/gittensory-miner-extension/, mounting score/tier plus a short why on watched repositories.
  • Background looks up pre-ranked candidates from chrome.storage.local.rankedCandidates (populated via options or future miner sync) using the same repo#issue key as opportunity-ranker.js, without duplicating ranking math in extension code.
  • Omits the badge entirely when the repo is unwatched or no ranked signal exists; includes regression tests wired to real rankCandidateIssues output.

Stacks on #4557 (scaffold for #4307). Merge #4557 first, or this PR can land both together.

Closes #4308

Test plan

  • npx vitest run test/unit/miner-extension-content.test.ts
  • CI green on upstream PR

@RealDiligent
RealDiligent requested a review from JSONbored as a code owner July 10, 2026 02:21
@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.08%. Comparing base (4d8409d) to head (8c9aec9).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4559   +/-   ##
=======================================
  Coverage   94.08%   94.08%           
=======================================
  Files         427      427           
  Lines       37961    37961           
  Branches    13864    13864           
=======================================
  Hits        35715    35715           
  Misses       1586     1586           
  Partials      660      660           
🚀 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:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 10, 2026
@loopover-orb

loopover-orb Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review result - reject/close recommended

Review updated: 2026-07-10 02:53:17 UTC

9 files · 1 AI reviewer · 1 blocker · readiness 100/100 · CI green · unstable

🛑 Suggested Action - Reject/Close

  • AI reviewers agree on a likely critical defect: apps/gittensory-miner-extension/opportunity-badge.js uses top-level `export function ...` (lines 1-91) but is registered in manifest.json's content_scripts `js` array alongside content.js
  • MV3 content scripts injected via manifest are classic (non-module) scripts, so Chrome will throw a SyntaxError on `export` and the whole content-script bundle (opportunity-badge.js + content.js) will fail to load on every GitHub issue page, silently breaking the badge feature end-to-end. — Resolve the flagged defect, or override if the AI reviewers are mistaken, then re-run the gate.

Review summary
This PR wires a read-only opportunity badge into the miner extension: background.js reads chrome.storage.local.rankedCandidates and looks up the current issue via the same repo#issue key as opportunity-ranker.js, and content.js renders the resulting badge via opportunity-badge.js's escaped-HTML markup builder. The core lookup/format/render logic and XSS-escaping in opportunity-badge.js are sound and options.js plumbing to persist watched repos plus a local ranked-candidate cache is reasonable. However, opportunity-badge.js is loaded both as a manifest content_script (apps/gittensory-miner-extension/manifest.json, content_scripts[0].js) and via ESM import from background.js, but its top-level `export function ...` statements are invalid syntax for a classic (non-module) content script — the exact class of bug this file exists to avoid is instead reintroduced by the delivery mechanism, and the test suite hides it by stripping `export` before executing the script in a VM.

Blockers

  • apps/gittensory-miner-extension/opportunity-badge.js uses top-level `export function ...` (lines 1-91) but is registered in manifest.json's content_scripts `js` array alongside content.js; MV3 content scripts injected via manifest are classic (non-module) scripts, so Chrome will throw a SyntaxError on `export` and the whole content-script bundle (opportunity-badge.js + content.js) will fail to load on every GitHub issue page, silently breaking the badge feature end-to-end.
  • test/unit/miner-extension-content.test.ts's loadBadgeInternals/loadBackgroundInternals strip `export` via `badgeScript.replace(/\bexport\s+/g, "")` before executing the script in a VM context, so the suite never exercises the actual browser-loadable form of opportunity-badge.js and would pass green even though the real content script fails to parse.
Nits — 5 non-blocking
  • opportunity-badge.js:22-33 hardcodes tier/why thresholds (0.75, 0.5, 0.7, 0.3) as magic numbers with no named constants or comments explaining the cutoffs.
  • content.js's findIssueSidebar duplicates the identical selector list from apps/gittensory-extension/content.js's findPullRequestSidebar verbatim; consider extracting a shared helper if both extensions are meant to stay in sync on GitHub DOM changes.
  • options.js's parseRankedCandidatesJson accepts any array without validating element shape (repoFullName/issueNumber/rankScore), so malformed pasted JSON will silently produce a cache that never matches lookupRankedOpportunity — consider surfacing a clearer validation error at save time.
  • README.md's 'Local ranked cache' section describes a 'hosted discovery-index URL' as future client support, but discoveryIndexUrl is currently stored and never read anywhere in background.js/content.js — worth a one-line note that it's inert for now.
  • Fix the export/content-script mismatch by either dropping `export` from opportunity-badge.js and relying solely on the `globalThis.__gittensoryMinerOpportunityBadge` attachment (matching how content.js already consumes it), or by using dynamic `import()`/`chrome.scripting.executeScript` with `world`/module support if ESM is required; then re-run the vitest suite without stripping `export` so it actually validates the shippable file.

Why this is blocked

  • apps/gittensory-miner-extension/opportunity-badge.js uses top-level `export function ...` (lines 1-91) but is registered in manifest.json's content_scripts `js` array alongside content.js; MV3 content scripts injected via manifest are classic (non-module) scripts, so Chrome will throw a SyntaxError on `export` and the whole content-script bundle (opportunity-badge.js + content.js) will fail to load on every GitHub issue page, silently breaking the badge feature end-to-end.
Signal Result Evidence
Code review ❌ 1 blocker 1 reviewer
Linked issue ✅ Linked #4308
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: 300 registered-repo PR(s), 122 merged, 17 issue(s).
Contributor context ✅ Confirmed Gittensor contributor RealDiligent; Gittensor profile; 300 PR(s), 17 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Linked issue satisfaction

Partially addressed
The PR delivers a solid read-only badge UI (content-script mount with sidebar/floating fallback, tier/score/why formatting, graceful omission when unwatched or unranked) that satisfies most deliverables, but the actual signal-sourcing path described in the issue — calling into opportunity-ranker.js's exports via the background script, or falling back to the hosted discovery-index — isn't wired up;

Review context
  • Author: RealDiligent
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 300 PR(s), 17 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.
Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop after /
/ mobile after / (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

🟩 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

@superagent-security superagent-security Bot added pr:flagged PR flagged for review by security analysis. and removed pr:flagged PR flagged for review by security analysis. labels Jul 10, 2026
@RealDiligent
RealDiligent force-pushed the feat/miner-extension-opportunity-badge-4308 branch from 14ee740 to 8c9aec9 Compare July 10, 2026 02:40
RealDiligent and others added 3 commits July 10, 2026 10:45
Surface pre-ranked miner opportunity signals on GitHub issue pages via cached ranked candidates, with tier/score/why formatting and graceful omission when no signal is available. Builds on the miner extension scaffold.

Co-authored-by: Cursor <cursoragent@cursor.com>
… tests

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 10, 2026
@loopover-orb

loopover-orb Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Gittensory is closing this pull request on the maintainer's behalf (AI reviewers agree on a likely critical defect: apps/gittensory-miner-extension/opportunity-badge.js uses top-level `export function ...` (lines 1-91) but is registered in manifest.json's content_scripts `js` array alongside content.js; MV3 content scripts injected via manifest are classic (non-module) scripts, so Chrome will throw a SyntaxError on `export` and the whole content-script bundle (opportunity-badge.js + content.js) will fail to load on every GitHub issue page, silently breaking the badge feature end-to-end.). 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.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(miner-extension): add read-only issue-page opportunity badge

1 participant