{"record":{"id":"7a50bac3fec6d9f1","repo":"pbakaus/impeccable","slug":"impeccable-discarding-orphaned-session","errorCode":null,"errorMessage":"[impeccable] Discarding orphaned session ","messagePattern":"\\[impeccable\\] Discarding orphaned session ","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"skill/scripts/live-browser.js","lineNumber":6209,"sourceCode":"    if (message) showToast(message, 5000);\n  }\n\n  // How many delayed re-reads a completion-driven source fallback gets when\n  // the fetched source still shows only the preflight scaffold, before the\n  // failure is surfaced via recoverEmptyCycling.\n  const COMPLETED_SOURCE_FALLBACK_RETRIES = 3;\n  const COMPLETED_SOURCE_FALLBACK_RETRY_MS = 1200;\n\n  /**\n   * Terminal recovery for a session whose source-side scaffolding no longer\n   * exists. The discard event is best-effort: with no agent polling it parks\n   * the durable session in discard_requested, which no resume path adopts;\n   * with an agent attached it triggers the normal discard finalization.\n   */\n  function discardOrphanedSession(reason) {\n    const sessionId = currentSessionId;\n    if (!sessionId) return;\n    console.warn('[impeccable] Discarding orphaned session ' + sessionId + ': ' + reason);\n    sendEvent({ type: 'discard', id: sessionId, orphaned: true }).catch(() => {});\n    markSessionHandled();\n    cleanup({ instantChrome: true });\n    showToast('The previous live session no longer matches the source file, so it was discarded. Pick an element to start fresh.', 6000);\n  }\n\n  function isJsxSourceFile(filePath) {\n    return /\\.[cm]?[jt]sx$/i.test(String(filePath || ''));\n  }\n\n  function sourceHasSessionWrapper(text, sessionId) {\n    const src = String(text || '');\n    return src.indexOf('data-impeccable-variants=\"' + sessionId + '\"') !== -1\n      || src.indexOf(\"data-impeccable-variants='\" + sessionId + \"'\") !== -1\n      || src.indexOf('impeccable-variants-start ' + sessionId) !== -1;\n  }\n\n  /**","sourceCodeStart":6191,"sourceCodeEnd":6227,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/skill/scripts/live-browser.js#L6191-L6227","documentation":"This is the terminal self-discard path for an orphaned live session: the session's source-side scaffolding (the data-impeccable-variants wrapper) no longer exists in the source file, so no reload, HMR push, or server restart can ever complete it. The script sends a discard event (marked orphaned), cleans up all chrome, and toasts that the session no longer matches the source. It is a deliberate recovery, not an unexpected crash.","triggerScenarios":"Reached from probeJsxWrapperForOrphan (JSX files) or the HTML source-read path when, after the COMPLETED_SOURCE_FALLBACK_RETRIES budget (3 retries x 1.2s), the source file still lacks the session wrapper or the file 404s — i.e. the file was edited, regenerated, renamed, or deleted out from under an active/resumed session.","commonSituations":"Agent rewrite or manual edit overwrote the source file mid-session; HMR regeneration dropped the wrapper; the user reverted the file with git; the file was renamed or deleted; resuming a saved session whose source has since changed.","solutions":["Pick an element again to start a fresh session — the old one was intentionally discarded and cannot be recovered.","If the discard was wrong, restore the file version that contains the impeccable-variants markers (e.g. git checkout the file) before retrying.","Avoid editing or regenerating the target source file while a live variant session is active.","Ensure the agent attached to the live session is polling so discard finalization completes server-side."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function sourceHasSessionWrapper(text, sessionId) {\n  const src = String(text || '');\n  return src.includes('data-impeccable-variants=\"' + sessionId + '\"')\n    || src.includes(\"data-impeccable-variants='\" + sessionId + \"'\")\n    || src.includes('impeccable-variants-start ' + sessionId);\n}\n// guard: only discard after the wrapper is confirmed absent\nif (!sourceHasSessionWrapper(sourceText, sessionId)) discardOrphanedSession('wrapper missing');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not edit, revert, or regenerate the source file while a live variant session is active.","Keep HTML comment markers (impeccable-variants-start/end) out of formatter/minifier stripping rules.","Finish or explicitly discard sessions before switching git branches.","Attach the agent to the session so discard finalization completes server-side."],"tags":["session","source-file","orphan","cleanup","browser"],"backgroundTag":"stale-session-state","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}