Files
LlamaCasty/TASKS/task-05-layout-persistence.md
T
gramps 87509bcf99 docs: restructure TASKS.md into a catalog — one file per task in TASKS/
TASKS.md is now the index (status table, open items, research pointer).
33 files: 32 task files + 1 research facts file. The full take-saga
narrative and all design decisions are preserved verbatim; the catalog
makes the queue readable without opening every task body. Schema and
AGENTS.md updated to reflect the new layout.
2026-09-05 16:31:46 -07:00

4.5 KiB

TASK 5 — Layout Persistence (SQLite)

Catalog: TASKS.md — status and requirements live here.

Goal: Scenes, sources, and asset bytes survive restarts; assets are always available.

Status: ✅ Done

  1. ✅ SQLite database (Microsoft.Data.Sqlite) at %APPDATA%\ytLlive\ytLlive.db; schema versioned via PRAGMA user_version (currently v8)
  2. ✅ Assets live in the DB (BLOB keyed by SHA-256 content hash), never file paths — deleting the original file never breaks a scene
  3. ✅ File-model save/open — the active layout file is tracked (default is the AppData DB); Save Layout As… / Open Layout… switch the active file; auto-save writes to whatever is active
  4. ✅ Auto-save (invisible) — ~1.5s debounce on scene/source add/remove/reorder/rename/hide + any source transform change; flush on window close
  5. ✅ Startup — load the active file; seed the five canonical scenes only when the DB is empty; (+) re-adds a missing canonical scene and is hidden once all five are present; adding beyond the five is rejected
  6. ✅ Schema v1 → v9 — webcam columns (v2), singleton Webcam + per-scene WebcamSceneConfig (v3), RectWidth/RectHeight round-to-rect restore (v4), Source.IsBackdrop + Source.CaptureKey (v5), Scene.HasBackdrop — backdrop Live-only by policy (v6, one-time backfill + EnforceBackdropPolicy on every load), Scene.HasSocialBar (v7, dropped per-scene toggle — column back-compat, unread), Socials.BarEnabled (v8); the SocialEntry.Software fediverse-software column is a column-presence migration (commented v8→v9, no version bump — user_version stays 8); v9 = single-row Music. Load-time rule: sources load with IsBackground derived from Type (OR'd with the persisted column so legacy DisplayCapture backdrops keep their flag) — rows saved before the Type setter derived the flag heal on load
  7. ✅ WindowHandle stays in-memory (per-session); save = transactional rewrite; orphaned assets pruned. v9 lands in the TASK 8 audio milestone (single-row Music — TrackPath/IsEnabled)

Design decisions

  1. SQLite database (Microsoft.Data.Sqlite) at %APPDATA%\ytLlive\ytLlive.db; schema versioned via PRAGMA user_version.
  2. Assets live in the DB, not on disk — Asset table stores image bytes (BLOB) keyed by a SHA-256 content hash (unique). Identical image content collapses to one row regardless of file name — the 1:M resource memory model, enforced by the database. No file paths; deleting the original file never breaks a scene.
  3. File-model save/open — the active layout file is tracked (default is the AppData DB). Save Layout As… / Open Layout… switch the active file; auto-save writes to whatever is active.
  4. Auto-save (invisible) — ~1.5s debounce on scene add/remove/reorder/rename/hide, source add/remove/reorder, and any source transform change; flush on window close.
  5. Schema — Scene (Id, Name, IsHidden, IsChatScene, HasBackdrop, HasSocialBar, SortOrder), Asset (Id, Hash, Data, PixelWidth, PixelHeight), Source (Id, SceneId FK cascade, AssetId FK, Type, Name, IsEnabled, X/Y/Width/Height/Opacity, MonitorIndex, DeviceId, ClipShape, IsMirrored, SortOrder), Socials (Id, BarPosition, BarJustify — back-compat, unread, BarEnabled added via ALTER), SocialEntry (Id, SocialsId FK cascade, Service, Handle, ProfileUrl, SortOrder) — user_version 8 (v1 → v2 = ALTER TABLE adds the two webcam columns; v3 = singleton Webcam + per-scene WebcamSceneConfig; v4 = WebcamSceneConfig.RectWidth/RectHeight for the round-to-rect restore; v5 = Source.IsBackdrop
    • Source.CaptureKey for the live-capture backdrop; v6 = Scene.HasBackdrop — the backdrop is Live-only by policy (one-time backfill turns Starting/BRB/Chat/Ending off and drops their backdrop sources; EnforceBackdropPolicy re-normalizes every load); v7 = Scene.HasSocialBar (per-scene toggle dropped — column back-compat, unread); v8 = Socials.BarEnabled). The SocialEntry.Software fediverse-software column is a column-presence migration (commented v8→v9, no version bump). WindowHandle stays in-memory (per-session). Save = transactional rewrite; orphaned assets pruned.
  6. Startup — load the active file; seed the five canonical scenes (Starting/Live/BRB/Chat/Ending, SceneCatalog) only when the DB is empty. The (+) button re-adds a missing canonical scene and is hidden once all five are present; adding beyond the five is rejected — work with less, never more.