You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
apps/gittensory-miner-extension stores its ranked opportunities (rankedCandidates) in chrome.storage.local via options.js, and opportunity-badge.js already renders a badge on matching GitHub issue pages. But background.js and manifest.json's toolbar action never call chrome.action.setBadgeText, so a contributor has no way to tell whether the extension currently holds live ranked data without first opening a matching issue page. This is distinct from #4862 (which only adds missing icon image assets) - that's a static-asset gap, this is dynamic runtime state.
Dependencies
None - independently shippable. It reads the same chrome.storage.local schema options.js already writes today and does not require the sibling savedAt/last-synced candidate in this batch to land first, though it pairs naturally with it if both ship.
Requirements
In background.js, read rankedCandidates from chrome.storage.local on extension/service-worker startup, and subscribe to chrome.storage.onChanged so the badge updates live whenever the stored value changes.
Call chrome.action.setBadgeText({ text }) to show the count of currently ranked opportunities as a short string (e.g. "12"); clear it (text: "") only for the genuinely-empty-array case, not the never-populated case (see requirement 3).
Distinguish "cache never populated" (no rankedCandidates key has ever been written) from "cache populated but currently zero opportunities" - render a distinct indicator (e.g. a dash) for the former so "no data yet" is never visually confused with "zero found".
Set an appropriate chrome.action.setBadgeBackgroundColor for the "has data" vs. "empty/stale" states so the distinction is visible at a glance, not just in the text.
Verify manifest.json's existing action key already covers setBadgeText/setBadgeBackgroundColor (it should, as these are part of the action API surface) - do not request any new host permissions.
Do not change options.js's storage schema or opportunity-badge.js's own per-issue-page badge - this PR is scoped strictly to the toolbar icon, a separate UI surface.
Deliverables / Acceptance Criteria
background.js reads rankedCandidates on startup and on chrome.storage.onChanged
Toolbar badge text shows the ranked-opportunity count when data exists
Toolbar badge shows a distinct "no data yet" indicator when the cache has never been populated, separate from a genuine zero-count
Badge background color differs between "has data" and "empty/stale" states
No new permissions added to manifest.json; existing action key confirmed sufficient
options.js and opportunity-badge.js are unchanged
Test Coverage Requirements
This PR must ship with full test coverage for every changed line and branch - the repo's Codecov patch gate requires 99%+ coverage and the house standard is to aim for 100%, including both sides of every conditional/nullish-coalescing branch introduced. Add: (1) unit tests covering the new/changed logic's success and failure paths (badge text/color for populated, empty-array, and never-populated storage states, plus the onChanged listener firing correctly), (2) an invariant test for 'the toolbar badge never displays a numeric count when rankedCandidates has never been written - true no-data is never rendered as zero', and (3) no regression test is required since this is a net-new feature, not a bug fix.
Codecov visibility note:packages/gittensory-miner/**, apps/gittensory-miner-ui/**, and apps/gittensory-miner-extension/** currently sit entirely outside vitest's coverage.include glob, so codecov/patch cannot measure changes there yet — closing that gap is exactly what #4864 and #4865 (in this same milestone) do. Any part of this change under packages/gittensory-engine/src/** or the repo's own src/** remains fully Codecov-instrumented as usual. Either way, this does not lower the bar: treat the 100%-including-invariants-and-regression target above as the enforced house standard regardless of what Codecov can currently see, and it becomes gate-enforced for real once #4864/#4865 ship.
Expected Outcome
A contributor can glance at the browser toolbar icon and immediately know whether the extension currently has fresh ranked-opportunity data, without first opening a matching GitHub issue page to check.
Context
apps/gittensory-miner-extension stores its ranked opportunities (rankedCandidates) in chrome.storage.local via options.js, and opportunity-badge.js already renders a badge on matching GitHub issue pages. But background.js and manifest.json's toolbar action never call chrome.action.setBadgeText, so a contributor has no way to tell whether the extension currently holds live ranked data without first opening a matching issue page. This is distinct from #4862 (which only adds missing icon image assets) - that's a static-asset gap, this is dynamic runtime state.
Dependencies
None - independently shippable. It reads the same chrome.storage.local schema options.js already writes today and does not require the sibling savedAt/last-synced candidate in this batch to land first, though it pairs naturally with it if both ship.
Requirements
Deliverables / Acceptance Criteria
Test Coverage Requirements
This PR must ship with full test coverage for every changed line and branch - the repo's Codecov patch gate requires 99%+ coverage and the house standard is to aim for 100%, including both sides of every conditional/nullish-coalescing branch introduced. Add: (1) unit tests covering the new/changed logic's success and failure paths (badge text/color for populated, empty-array, and never-populated storage states, plus the onChanged listener firing correctly), (2) an invariant test for 'the toolbar badge never displays a numeric count when rankedCandidates has never been written - true no-data is never rendered as zero', and (3) no regression test is required since this is a net-new feature, not a bug fix.
Codecov visibility note:
packages/gittensory-miner/**,apps/gittensory-miner-ui/**, andapps/gittensory-miner-extension/**currently sit entirely outside vitest'scoverage.includeglob, socodecov/patchcannot measure changes there yet — closing that gap is exactly what #4864 and #4865 (in this same milestone) do. Any part of this change underpackages/gittensory-engine/src/**or the repo's ownsrc/**remains fully Codecov-instrumented as usual. Either way, this does not lower the bar: treat the 100%-including-invariants-and-regression target above as the enforced house standard regardless of what Codecov can currently see, and it becomes gate-enforced for real once #4864/#4865 ship.Expected Outcome
A contributor can glance at the browser toolbar icon and immediately know whether the extension currently has fresh ranked-opportunity data, without first opening a matching GitHub issue page to check.
Links & Resources