Context
apps/loopover-miner-extension/background.js's syncRankedCandidatesFromMinerUi (lines 107-124) calls fetch(\${minerUiUrl}/api/ranked-candidates`)with no timeout orAbortController— unlike the established pattern inreview-enrichment/src/external-fetch.ts`, which every outbound fetch in that part of the codebase follows. This sync runs on a 10-minute alarm (background scheduled task), so a hung connection (e.g. the local miner-ui process is running but unresponsive) would leave that alarm's invocation hanging indefinitely instead of failing fast and letting the next scheduled attempt retry.
Requirements
- Add a request timeout to the
fetch call in syncRankedCandidatesFromMinerUi, using AbortController/AbortSignal.timeout(...), following the pattern already established in review-enrichment/src/external-fetch.ts.
- A timeout must resolve to the function's existing typed
{ ok: false, error, minerUiUrl } failure shape (matching every other failure branch already in this function), not throw — per this function's own documented "never throws" contract.
- Pick a timeout duration appropriate for a same-machine localhost call (short — this isn't a network round-trip to a remote server).
Deliverables
Test Coverage Requirements
apps/** extension code — check whether this repo's coverage.include covers apps/loopover-miner-extension; if so, 99%+ Codecov patch coverage plus the regression test above; if excluded, the regression test alone suffices.
Expected Outcome
A stalled local miner-ui connection during the 10-minute background sync no longer hangs that alarm invocation indefinitely — it times out and returns the module's typed failure result, letting the next scheduled sync retry cleanly.
Links & Resources
review-enrichment/src/external-fetch.ts — the timeout pattern to follow. apps/loopover-miner-extension/background.js:107-124 — the unguarded fetch.
Context
apps/loopover-miner-extension/background.js'ssyncRankedCandidatesFromMinerUi(lines 107-124) callsfetch(\${minerUiUrl}/api/ranked-candidates`)with no timeout orAbortController— unlike the established pattern inreview-enrichment/src/external-fetch.ts`, which every outbound fetch in that part of the codebase follows. This sync runs on a 10-minute alarm (background scheduled task), so a hung connection (e.g. the local miner-ui process is running but unresponsive) would leave that alarm's invocation hanging indefinitely instead of failing fast and letting the next scheduled attempt retry.Requirements
fetchcall insyncRankedCandidatesFromMinerUi, usingAbortController/AbortSignal.timeout(...), following the pattern already established inreview-enrichment/src/external-fetch.ts.{ ok: false, error, minerUiUrl }failure shape (matching every other failure branch already in this function), not throw — per this function's own documented "never throws" contract.Deliverables
syncRankedCandidatesFromMinerUi's fetch has a bounded timeout{ ok: false, ... }instead of hangingTest Coverage Requirements
apps/**extension code — check whether this repo'scoverage.includecoversapps/loopover-miner-extension; if so, 99%+ Codecov patch coverage plus the regression test above; if excluded, the regression test alone suffices.Expected Outcome
A stalled local miner-ui connection during the 10-minute background sync no longer hangs that alarm invocation indefinitely — it times out and returns the module's typed failure result, letting the next scheduled sync retry cleanly.
Links & Resources
review-enrichment/src/external-fetch.ts— the timeout pattern to follow.apps/loopover-miner-extension/background.js:107-124— the unguarded fetch.