// ── canonical identifiers ──────────────────────────────────────────── const CANONICAL_KEY = "confidence-engine-investigation"; const LEGACY_KEY = "confidence-engine-session"; const SCHEMA_VERSION = 1; // ── helpers ────────────────────────────────────────────────────────── function safeGet(storage, key) { if (!storage || typeof storage.getItem !== "function") return null; try { return storage.getItem(key); } catch (_) { return null; } } function isPlainObject(value) { return ( value !== null && typeof value === "object" && !Array.isArray(value) && Object.prototype.toString.call(value) === "[object Object]" ); } // ── loadInvestigation ──────────────────────────────────────────────── /** * Returns the persisted investigation snapshot (normalised to current schema) * or null when no usable state exists. */ export function loadInvestigation() { const storage = _getTargetStorage(); if (!storage) return null; // 1 – canonical key first let raw = safeGet(storage, CANONICAL_KEY); if (raw !== null) { try { const parsed = JSON.parse(raw); if (isPlainObject(parsed)) { if (!("schemaVersion" in parsed)) parsed.schemaVersion = SCHEMA_VERSION; return parsed; } } catch (_) { /* malformed — fall through to legacy */ } } // 2 – legacy fallback const legacyStorage = _getLegacyStorage(); if (!legacyStorage) return null; raw = safeGet(legacyStorage, LEGACY_KEY); if (raw === null) return null; let parsed; try { parsed = JSON.parse(raw); } catch (_) { return null; } if (!isPlainObject(parsed)) return null; // Normalise schemaVersion for legacy data if (!("schemaVersion" in parsed)) parsed.schemaVersion = SCHEMA_VERSION; // Migrate into canonical key _persist(storage, CANONICAL_KEY, JSON.stringify(parsed)); return parsed; } // ── saveInvestigation ──────────────────────────────────────────────── /** * Persists the supplied snapshot to the canonical localStorage key. * The caller's object is never mutated. */ export function saveInvestigation(snapshot) { const storage = _getTargetStorage(); if (!storage) return; // silently no-op in non-browser try { const record = JSON.parse(JSON.stringify(snapshot)); record.schemaVersion = SCHEMA_VERSION; _persist(storage, CANONICAL_KEY, JSON.stringify(record)); } catch (_) { /* storage errors must not crash caller */ } } // ── clearInvestigation ─────────────────────────────────────────────── /** Removes only the canonical investigation key. */ export function clearInvestigation() { const storage = _getTargetStorage(); if (!storage) return; try { storage.removeItem(CANONICAL_KEY); } catch (_) {} } // ── internals ──────────────────────────────────────────────────────── function _persist(storage, key, value) { try { storage.setItem(key, value); } catch (_) {} } function _getTargetStorage() { if (typeof globalThis.window === "undefined") return null; const s = globalThis.window.localStorage; if (!s || typeof s.getItem !== "function") return null; return s; } function _getLegacyStorage() { if (typeof globalThis.window === "undefined") return null; const s = globalThis.window.sessionStorage; if (!s || typeof s.getItem !== "function") return null; return s; }