import re with open('static/js/rehearser.js', 'r') as f: content = f.read() # 1. Revert buildScriptPage change content = content.replace( "const isCached = rehState.synthCache.has(i) || (rehState.serverCachedLines && rehState.serverCachedLines.has(i));", "const isCached = rehState.synthCache.has(i);" ) # 2. Revert serverCachedLines in _lineAudioSyncDots old_sync_dots = """let _lineAudioSyncedFor = null; // unused now, kept for compat async function _lineAudioSyncDots() { if (!rehState.serverCachedLines) rehState.serverCachedLines = new Set(); const book = _lineAudioBookName(); _ensureNarrator();""" new_sync_dots = """let _lineAudioSyncedFor = null; // unused now, kept for compat async function _lineAudioSyncDots() { const book = _lineAudioBookName(); _ensureNarrator();""" content = content.replace(old_sync_dots, new_sync_dots) old_foreach = """ const { existing } = await r.json(); (existing || []).forEach(key => { const idx = keyToIdx.get(key); if (idx == null) return; rehState.staleLines.delete(idx); rehState.serverCachedLines.add(idx); _markSynthDot(idx, 'ok'); }); } catch (_) { /* dots just stay as-is; playback still checks the disk cache lazily either way */ }""" new_foreach = """ const { existing } = await r.json(); (existing || []).forEach(key => { const idx = keyToIdx.get(key); if (idx == null) return; rehState.staleLines.delete(idx); _markSynthDot(idx, 'ok'); }); } catch (_) { /* dots just stay as-is; playback still checks the disk cache lazily either way */ }""" content = content.replace(old_foreach, new_foreach) with open('static/js/rehearser.js', 'w') as f: f.write(content)