Spec: Fowler-style refactoring review (cloud agent, 2026-08-05). Refactor only — no behavior change beyond deleting unreachable code.
What to change
Small mechanical consolidations, one PR:
sha256Hex ×3 — lib/export/checksum.ts, lib/offline-region/checksum.ts, and a private copy in lib/offline-region/store.ts (~38–43). One shared implementation (keep export's fail-closed policy via an option).
- IDB promise helpers ×3 —
requestToPromise/transactionDone in lib/local-capture/store.ts, lib/local-capture/media-store.ts (~49–65), lib/offline-region/pack-store.ts (~128–144). Extract lib/idb/promises.ts.
- Byte formatters ×3, mutually incompatible —
components/region-tracer.tsx formatBytes (decimal MB), components/offline-region-panel.tsx formatBytes (binary KB/MB), lib/offline-region/download-copy.ts formatRegionMegabytes. One policy in download-copy.ts; delete the locals.
- Close-X SVG ×4+ — the
m6 6 12 12M18 6 6 18 path in map-journal.tsx, daily-digest-panel.tsx, artifact-lightbox.tsx, media-lightbox.tsx, thread-chat.tsx. Extract a CloseIcon.
- Lightbox chrome ×2 —
ArtifactLightbox and MediaLightbox duplicate the Escape handling, scroll lock, and dialog frame. Extract LightboxShell (and/or a useModalLayer(onClose) hook).
- Slugify ×2 —
readTopics in lib/enrichment/system-instruction.ts (~188–200) inlines the algorithm mentionSlug (~205–212) already provides; call it. Likewise lib/artifacts/document.ts escape duplicates escapeText from lib/artifacts/sanitize.ts — export and reuse.
- Dead code —
components/offline-region-panel.tsx (OfflineRegionPanel), SheetMasthead and InstrumentStrip in components/sheet.tsx have zero product imports. Delete them (which also removes one of the byte formatters).
Out of scope: anything under app/prototype/ (throwaway by design).
Acceptance criteria
Spec: Fowler-style refactoring review (cloud agent, 2026-08-05). Refactor only — no behavior change beyond deleting unreachable code.
What to change
Small mechanical consolidations, one PR:
sha256Hex×3 —lib/export/checksum.ts,lib/offline-region/checksum.ts, and a private copy inlib/offline-region/store.ts(~38–43). One shared implementation (keep export's fail-closed policy via an option).requestToPromise/transactionDoneinlib/local-capture/store.ts,lib/local-capture/media-store.ts(~49–65),lib/offline-region/pack-store.ts(~128–144). Extractlib/idb/promises.ts.components/region-tracer.tsxformatBytes(decimal MB),components/offline-region-panel.tsxformatBytes(binary KB/MB),lib/offline-region/download-copy.tsformatRegionMegabytes. One policy indownload-copy.ts; delete the locals.m6 6 12 12M18 6 6 18path inmap-journal.tsx,daily-digest-panel.tsx,artifact-lightbox.tsx,media-lightbox.tsx,thread-chat.tsx. Extract aCloseIcon.ArtifactLightboxandMediaLightboxduplicate the Escape handling, scroll lock, and dialog frame. ExtractLightboxShell(and/or auseModalLayer(onClose)hook).readTopicsinlib/enrichment/system-instruction.ts(~188–200) inlines the algorithmmentionSlug(~205–212) already provides; call it. Likewiselib/artifacts/document.tsescapeduplicatesescapeTextfromlib/artifacts/sanitize.ts— export and reuse.components/offline-region-panel.tsx(OfflineRegionPanel),SheetMastheadandInstrumentStripincomponents/sheet.tsxhave zero product imports. Delete them (which also removes one of the byte formatters).Out of scope: anything under
app/prototype/(throwaway by design).Acceptance criteria
mise run lintandmise run testpass