Summary
lastScanAt is reconstructed on panel init from persisted connector statuses, but background/index.ts writes no status row when a connector returns zero missions with no error. When an entire scan returns zero missions across all connectors, no durable trace is written, so on panel reopen controller.lastScanAt reverts to null and hasCompletedScan is false. As a result the feed's scanned-empty operational story (added in PR #270) never appears for its target scenario after a reopen — the user instead sees the never-scanned-empty "Lancez un premier scan" state despite having just scanned.
Surfaced by Codex review on PR #270 (thread on apps/extension/src/ui/pages/FeedPage.svelte:447).
Steps to reproduce
- Ensure every configured connector is connected but returns zero missions for the current profile (or temporarily point connectors at empty result sets).
- Trigger a scan from the side panel and let it complete successfully.
- Observe the hero shows the
scanned-empty / "Aucune correspondance" story (correct, in-memory lastScanAt is set).
- Close the side panel and reopen it.
- Observe the hero now shows the
never-scanned-empty / "Lancez un premier scan" story.
Expected behavior
A successfully completed scan should leave a durable trace so hasCompletedScan stays true after a panel reopen, and the scanned-empty story continues to render until the next state change.
Area
Extension
Browser
Chrome (MV3)
Logs or screenshots
Design decision required (do not implement blindly): pick one approach and reconcile it with src/models/scan-lifecycle.model.md.
- Option A — scan-level timestamp: persist a
lastScanCompletedAt value in chrome.storage.local, written by the background after every successful scan regardless of mission count, and read on init. Additive and low-risk, but introduces a parallel signal next to the connector-status-derived lastScanAt; the model must define which is canonical.
- Option B — durable zero-result connector rows: make
background/index.ts write a done / missionsCount: 0 status row for connectors that were scanned successfully but returned nothing. This requires the scan result to carry the list of attempted connectors (today the status map is built only from missions + errors). Touches the scan-result persistence shape; higher risk.
Either way, update scan-lifecycle.model.md to specify whether "scan completed" is a connector-level or scan-level fact and how it coexists with the existing connector-status-derived lastScanAt.
Within-session behavior already works (handleScanFeedComplete sets lastScanAt in memory); only cross-session durability is broken.
Summary
lastScanAtis reconstructed on panel init from persisted connector statuses, butbackground/index.tswrites no status row when a connector returns zero missions with no error. When an entire scan returns zero missions across all connectors, no durable trace is written, so on panel reopencontroller.lastScanAtreverts tonullandhasCompletedScanisfalse. As a result the feed'sscanned-emptyoperational story (added in PR #270) never appears for its target scenario after a reopen — the user instead sees thenever-scanned-empty"Lancez un premier scan" state despite having just scanned.Surfaced by Codex review on PR #270 (thread on
apps/extension/src/ui/pages/FeedPage.svelte:447).Steps to reproduce
scanned-empty/ "Aucune correspondance" story (correct, in-memorylastScanAtis set).never-scanned-empty/ "Lancez un premier scan" story.Expected behavior
A successfully completed scan should leave a durable trace so
hasCompletedScanstaystrueafter a panel reopen, and thescanned-emptystory continues to render until the next state change.Area
Extension
Browser
Chrome (MV3)
Logs or screenshots
Design decision required (do not implement blindly): pick one approach and reconcile it with
src/models/scan-lifecycle.model.md.lastScanCompletedAtvalue inchrome.storage.local, written by the background after every successful scan regardless of mission count, and read on init. Additive and low-risk, but introduces a parallel signal next to the connector-status-derivedlastScanAt; the model must define which is canonical.background/index.tswrite adone/missionsCount: 0status row for connectors that were scanned successfully but returned nothing. This requires the scan result to carry the list of attempted connectors (today the status map is built only from missions + errors). Touches the scan-result persistence shape; higher risk.Either way, update
scan-lifecycle.model.mdto specify whether "scan completed" is a connector-level or scan-level fact and how it coexists with the existing connector-status-derivedlastScanAt.Within-session behavior already works (
handleScanFeedCompletesetslastScanAtin memory); only cross-session durability is broken.