Skip to content

feat(miner-extension): dynamic toolbar badge for local cache state - #5449

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
davion-knight:feat-miner-ext-toolbar-badge
Jul 12, 2026
Merged

feat(miner-extension): dynamic toolbar badge for local cache state#5449
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
davion-knight:feat-miner-ext-toolbar-badge

Conversation

@davion-knight

Copy link
Copy Markdown
Contributor

What

Adds dynamic badge text to the miner extension's toolbar icon reflecting the local rankedCandidates cache, per #5193.

  • New pure computeToolbarBadge(rankedCandidates) (toolbar-badge.js) maps the raw chrome.storage.local value to { text, backgroundColor }, distinguishing three states:
    • never populated (key never written ⇒ undefined, or any malformed value) → a dash (TOOLBAR_BADGE_NO_DATA_TEXT), never a count
    • populated but empty ([]) → cleared text
    • populated ([…]) → the count
  • background.js reads the cache without a default (so undefined survives as never-populated), paints on service-worker startup, and stays live via chrome.storage.onChanged (only for local rankedCandidates changes). Distinct setBadgeBackgroundColor for has-data vs empty/stale. The refresh is wrapped in try/catch so a transient chrome.action/storage rejection can't leak an unhandled rejection in the service worker.
  • Reuses the manifest's existing action key — no new host permissions. Scoped strictly to the toolbar icon; the per-issue-page badge and options schema are untouched.

Tests

test/unit/miner-toolbar-badge.test.ts — full coverage of the pure state map (populated / empty / never-populated / malformed) incl. the invariant that a never-written cache is never rendered as a numeric count, plus VM-harness wiring tests for startup paint, live onChanged repaint (ignoring unrelated keys/areas), the error-path swallow, and clean no-op when the action API is unavailable.

Fixes #5193

Show the count of currently ranked opportunities on the extension's toolbar
icon, painted on service-worker startup and kept live via chrome.storage.onChanged.
Distinguishes a never-populated cache (a dash) from a populated-but-empty one
(cleared text) so "no data yet" is never shown as a zero, with distinct badge
colors for the has-data vs empty/stale states. Reuses the existing action key,
so no new host permissions are requested.

Fixes JSONbored#5193
@davion-knight
davion-knight requested a review from JSONbored as a code owner July 12, 2026 19:52
@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.42%. Comparing base (e0c1000) to head (d94b8e0).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5449      +/-   ##
==========================================
- Coverage   94.46%   94.42%   -0.04%     
==========================================
  Files         554      554              
  Lines       44438    44438              
  Branches    14663    14663              
==========================================
- Hits        41979    41962      -17     
- Misses       1784     1801      +17     
  Partials      675      675              
Flag Coverage Δ
shard-1 43.84% <ø> (-0.27%) ⬇️
shard-2 34.91% <ø> (+0.04%) ⬆️
shard-3 31.69% <ø> (+0.10%) ⬆️
shard-4 31.35% <ø> (-0.06%) ⬇️
shard-5 32.88% <ø> (-0.39%) ⬇️
shard-6 43.83% <ø> (+0.46%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 1 file with indirect coverage changes

🚀 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 12, 2026
@loopover-orb

loopover-orb Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Tip

🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩

✅ Gittensory review result - approve/merge recommended

Review updated: 2026-07-12 20:00:49 UTC

5 files · 2 AI reviewers · no blockers · readiness 100/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This adds a pure computeToolbarBadge() state map plus background.js wiring to paint the toolbar badge on startup and on storage.onChanged, correctly distinguishing never-populated (undefined/malformed → dash) from populated-but-empty ([] → cleared) from populated (count). The logic is sound, the refresh is wrapped in try/catch to avoid unhandled rejections in the service worker, and the listener correctly filters on areaName === 'local' and the specific key. Tests cover the pure function's states/invariant plus VM-harness wiring for startup paint, live repaint, error swallowing, and the no-action-API no-op path, all exercising the real background.js code path via the same load mechanism the existing suite uses.

Nits — 5 non-blocking
  • console.warn at background.js:87 is intentional error-swallow logging, not a debug leftover, but worth confirming it's acceptable telemetry for a shipped extension.
  • toolbar-badge.js: the global exposure pattern duplicates opportunity-badge.js's convention (mentioned in the comment) — fine, but consider a small shared helper if a third badge type is added later.
  • background.js:83 reads chrome.storage.local.get('rankedCandidates') without a default while loadRankedCandidates() above it uses a default object — worth a one-line comment there too (already present) so future editors don't 'fix' the inconsistency.
  • Consider debouncing refreshToolbarBadge if rankedCandidates writes happen in rapid bursts, though this isn't currently a problem given typical miner write frequency.
  • The PR could link more directly to how rankedCandidates is written elsewhere (e.g., options.js) to make the never-populated vs empty distinction easier to audit end-to-end.
Signal Result Evidence
Code review ✅ No blockers 2 reviewers, synthesized
Linked issue ✅ Linked #5193
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: 124 registered-repo PR(s), 89 merged, 2 issue(s).
Contributor context ✅ Confirmed Gittensor contributor davion-knight; Gittensor profile; 124 PR(s), 2 issue(s).
Gate result ✅ Passing No configured blocker found.
Improvement ✅ Minor risk: clean · value: minor — Code changes are accompanied by test evidence. LLM value judgment: moderate — The diff adds a small, well-tested, correctly-scoped feature (toolbar badge reflecting cache state) that directly closes the linked issue #5193 without touching unrelated surfaces or requiring new permissions.
Linked issue satisfaction

Addressed
The PR adds background.js startup + chrome.storage.onChanged wiring, a pure computeToolbarBadge helper distinguishing never-populated/empty/populated states with distinct badge text and background colors, leaves options.js and opportunity-badge.js untouched, and adds no new manifest permissions, directly satisfying all six requirements.

Review context
  • Author: davion-knight
  • 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: 124 PR(s), 2 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.
[BETA] Chat with Gittensory

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

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

Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands

Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before / after /
/ mobile before / (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

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 558d4d3 into JSONbored:main Jul 12, 2026
15 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add dynamic badge text to the miner extension's toolbar icon reflecting local cache state

1 participant