Part of the #403/#404 Phase A push. The working-copy layer needs the data-loss guards before the legacy storage is deleted.
- One central
markEdited(reason) wired by document-level delegation (Element.closest), not direct element listeners — the caption-mode round trip replaces #hypertranscript, silently killing direct listeners. Cover: transcript/caption/title/summary/topics input, caption-control and persisted-option change, the strike-through toolbar (mutates styles without input), and semantic events for caption regeneration/programmatic edits. Suppression scope around open/restore apply. Dirty state becomes synchronous, not inferred from OPFS timestamps.
- Per-tab lifecycle state:
identityGeneration (bumps on open/import/new-project commit), editGeneration (bumps per edit), dirty, saveInFlight, autosaveInFlight. Capture generations before gather; on completion, apply only if identity still matches; mark clean only if the edit generation also matches; serialize autosaves (one follow-up write, never parallel); finally clears in-flight flags.
- Transactional open/import (prepare → apply → commit): stage the incoming project fully before touching DOM or work state; apply under suppression with explicit success/throw; only on success switch identity/session and clear the OLD working copy. Never clear old work before replacement commits. Download marking must check that no edits landed during zip generation.
- Single-file crash snapshot: collapse the recovery snapshot to one
snapshot.json (everything except media; media copied once, immutable) — eliminating multi-file torn-snapshot states without staging/revision machinery. Empty captions are unambiguous by construction. Boot restore awaits recovery apply before enabling editing; a failed restore clears the boot hint instead of retrying forever.
Part of the #403/#404 Phase A push. The working-copy layer needs the data-loss guards before the legacy storage is deleted.
markEdited(reason)wired by document-level delegation (Element.closest), not direct element listeners — the caption-mode round trip replaces#hypertranscript, silently killing direct listeners. Cover: transcript/caption/title/summary/topics input, caption-control and persisted-optionchange, the strike-through toolbar (mutates styles withoutinput), and semantic events for caption regeneration/programmatic edits. Suppression scope around open/restore apply. Dirty state becomes synchronous, not inferred from OPFS timestamps.identityGeneration(bumps on open/import/new-project commit),editGeneration(bumps per edit),dirty,saveInFlight,autosaveInFlight. Capture generations before gather; on completion, apply only if identity still matches; mark clean only if the edit generation also matches; serialize autosaves (one follow-up write, never parallel);finallyclears in-flight flags.snapshot.json(everything except media; media copied once, immutable) — eliminating multi-file torn-snapshot states without staging/revision machinery. Empty captions are unambiguous by construction. Boot restore awaits recovery apply before enabling editing; a failed restore clears the boot hint instead of retrying forever.