feat(miner-extension): show a last-synced label on the opportunity badge - #5518
Conversation
Persist a savedAt timestamp alongside rankedCandidates in chrome.storage.local whenever the options page saves, and surface it as a relative-time "last synced" label on the GitHub issue-page opportunity badge, mirroring ORB's shared RefreshMeta thresholds. A cache saved before this field existed degrades gracefully by omitting the label instead of showing NaN. Fixes JSONbored#5192
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5518 +/- ##
=======================================
Coverage 94.77% 94.77%
=======================================
Files 565 565
Lines 44964 44964
Branches 14675 14675
=======================================
Hits 42614 42614
Misses 1616 1616
Partials 734 734
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-13 00:46:19 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 5 non-blocking
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
[BETA] Chat with GittensoryAsk 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.
Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands Visual preview
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.
|
Summary
apps/gittensory-miner-extension/opportunity-badge.js) previously gave a contributor no signal at all about how stale their pasteddiscover-run data was — the badge could be showing a ranked candidate synced minutes or days ago with no way to tell which.options.jsnow writes arankedCandidatesSavedAttimestamp (Date.now()) tochrome.storage.localalongsiderankedCandidateson every save, including a re-paste/overwrite of previously-saved data.background.js'sloadIssueOpportunityContextreads that timestamp back and includes it (assavedAt) in thereadymessage payload sent to the content script.opportunity-badge.jsgets a newformatLastSyncedLabel(savedAt, nowMs)helper that reimplements the same relative-time thresholds/format as ORB's sharedRefreshMetacomponent (packages/gittensory-ui-kit/src/utils.ts'srelativeTimeFromNow: "just now" / "Xm ago" / "Xh ago" / "Xd ago") — reimplemented locally because this content script ships unbundled and cannot import that package.content.js'srenderOpportunityBadgenow takes an injectablenowMs(defaulting toDate.now()), computes the label, and renders it inside the badge markup as a.gittensory-miner-opportunity-badge__syncedline.savedAt) degrades gracefully: the label is simply omitted, neverNaNor a crash.Fixes #5192
Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #123) — a linked open issue is required for every contributor PR.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally — this change lives entirely underapps/gittensory-miner-extension/**and its dedicated test filetest/unit/miner-extension-content.test.ts, outside vitest's rootcoverage.includeglob (only rootsrc/**is Codecov-measured), socodecov/patchcannot see this diff.npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderateRan the full local gate:
npm run test:ci(796 test files / 15400+ tests, all green) andnpm audit --audit-level=moderate(0 vulnerabilities), both clean on the final rebased commit.Test coverage added to
test/unit/miner-extension-content.test.ts(18 tests total in the file, up from 10):formatLastSyncedLabelacross every relative-time bucket (just now / 1m / 59m / 1h / 23h / 1d, plus a small-positive-skew clamp), and an explicit invariant thatnull/undefined/NaN/a non-numeric string/an empty string all degrade tonullrather than being misread as epoch-zero (Number("")coerces to0, which is finite — this was caught live while writing the test and fixed by requiringtypeof savedAt === "number"rather than a bareNumber.isFinitecoercion);renderOpportunityBadgeMarkupwith and without a label, asserting the ranking-derived fields (tier/score) are unaffected either way;content.js'srenderOpportunityBadgeplumbingsavedAt+ an injectednowMsthrough to the rendered label; a regression test for a pre-existing cache with nosavedAtfield rendering cleanly with no label and noNaN;background.jsincludingsavedAtin thereadypayload and omitting it when there's no ranked signal; andoptions.jswriting a freshrankedCandidatesSavedAton every save, including a second save with a different value to prove it's rewritten on overwrite, not just written once.This branch was rebased past a concurrent PR (#5511, merged as
ec7d4c24) that touched the same two files (options.jsand this test file) to add adiscoveryIndexUrllegacy-purge feature; the rebase conflict was resolved by keeping both sets of changes/tests, and a real gap the merge exposed (a test'schrome.storage.syncmock missing theremovemethod now called fromrefreshSettings()) was fixed in the same commit.Safety
chrome.storageonly).savedAtadded) is covered by the tests above.chrome.storage.localcache; the missing-savedAtfallback is a real degrade path, not a mock.UI Evidencesection below.apps/gittensory-miner-extension/README.md's "Local ranked cache" section.UI Evidence
This is a browser extension content script injected into
github.com/*/*/issues/*pages — there is no hosted/public deployment to screenshot from this environment (no browser screenshot tooling available here). Verified functionally instead:npm run test:ciincludes the fulltest/unit/miner-extension-content.test.tssuite (18/18 passing), including a direct assertion thatrenderOpportunityBadgeMarkup/renderOpportunityBadgeproduce markup literally containinglast synced 5m ago-style text alongside the existing tier/score/why badge content, and that the label is cleanly absent (noNaN) whensavedAtis missing.Notes
.gittensory-miner-opportunity-badge__synced, styled muted/small to match the existing__read-onlytreatment) rather than a separate UI element, since the badge is already a compact fixed/sidebar-anchored card.rankedCandidatesSavedAt, since the issue only asked for it on the GitHub issue-page badge.