Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
One-time setup that gathers your project's design context and saves it to CLAUDE.md for future sessions.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/live-browser-session.js
1/**2* Browser-side durable session helpers for Impeccable live mode.3*4* Kept separate from live-browser.js so recovery state can be tested without5* booting the full overlay UI. Served before live-browser.js and attached to6* window.__IMPECCABLE_LIVE_SESSION__.7*/8(function (root) {9'use strict';1011function createLiveBrowserSessionState({ prefix, storage, idFactory }) {12if (!prefix) throw new Error('prefix required');13const store = storage || root.localStorage;14const makeId = idFactory || function () { return Math.random().toString(16).slice(2, 10); };15const sessionKey = prefix + '-session';16const handledKey = sessionKey + '-handled';17const scrollKey = sessionKey + '-scroll';18let checkpointRevision = 0;19const owner = makeId();2021function safeRead(key) {22try { return store.getItem(key); } catch { return null; }23}2425function safeWrite(key, value) {26try { store.setItem(key, value); } catch { /* quota exceeded or private mode */ }27}2829function safeRemove(key) {30try { store.removeItem(key); } catch { /* unavailable storage */ }31}3233function loadSession() {34try {35const raw = safeRead(sessionKey);36if (!raw) return null;37const parsed = JSON.parse(raw);38if (Number.isInteger(parsed.checkpointRevision)) {39checkpointRevision = Math.max(checkpointRevision, parsed.checkpointRevision);40}41return parsed;42} catch { return null; }43}4445function saveSession(session) {46if (!session || !session.id) return;47const payload = {48...session,49checkpointRevision,50};51safeWrite(sessionKey, JSON.stringify(payload));52}5354function clearSession() {55safeRemove(sessionKey);56}5758function nextCheckpointRevision() {59checkpointRevision += 1;60const existing = loadSession();61if (existing?.id) saveSession(existing);62return checkpointRevision;63}6465function seedCheckpointRevision(value) {66if (Number.isInteger(value)) checkpointRevision = Math.max(checkpointRevision, value);67return checkpointRevision;68}6970function currentCheckpointRevision() {71return checkpointRevision;72}7374function markHandled(id) {75if (!id) return;76safeWrite(handledKey, id);77}7879function isHandled(id) {80return !!id && safeRead(handledKey) === id;81}8283function clearHandled() {84safeRemove(handledKey);85}8687function writeScrollY(y) {88safeWrite(scrollKey, String(y));89}9091function readScrollY() {92const raw = safeRead(scrollKey);93if (raw == null) return null;94const n = parseFloat(raw);95return isFinite(n) ? n : null;96}9798function clearScrollY() {99safeRemove(scrollKey);100}101102return {103owner,104sessionKey,105handledKey,106scrollKey,107saveSession,108loadSession,109clearSession,110nextCheckpointRevision,111seedCheckpointRevision,112currentCheckpointRevision,113markHandled,114isHandled,115clearHandled,116writeScrollY,117readScrollY,118clearScrollY,119};120}121122root.__IMPECCABLE_LIVE_SESSION__ = { createLiveBrowserSessionState };123})(typeof window !== 'undefined' ? window : globalThis);124