Files
LlamaCasty/HANDOFF.md
T
gramps 670fe3a10a TASK 31: SceneGraph component + baked-crust compositor optimization
- Add ElementKind (Static/Dynamic) to SceneElement base; Source/WebcamSceneConfig classify
- Services/SceneGraph.cs: owns the Scenes collection (ViewModel's Scenes delegates to it),
  the element mutation surface (Add/Insert/Remove/Move, each invalidating the bake), and the
  queries that were scattered LINQ (GetBackground/GetWebcam/GetChatBoxes/GetSplitPoint/IsStatic)
- SceneCompositor: split-aware BakeStaticBase + CompositeLayers + Render(.., staticBase, split);
  builds/caches the static base below the split point in source-rect space
- FramePump: optional SceneGraph -> optimized bake+composite path; falls back to full render
- MainViewModel: routes element mutations through the graph; invalidates the bake on static
  layout/opacity/visibility/useDefaultBackground changes and after background heal/Ensure
- Integration test SceneGraphTests.BakedStaticBase_WithDynamicLayer_CompositesCorrectly

Derivative survey (mandated): tried before writing — OBS does per-source opacity/visibility
caching and static-scene baking; this mirrors OBS's 'cached static source' optimization.
3 documented defensive deviations from the spec (ChatOverlayLayer stays decoupled;
background helpers stay VM-static for direct testability; full facade peel deferred post-1.0)
in TASKS.md + ai.md. Scope check passed; clean build 0 warnings.
2026-08-31 17:53:34 -07:00

134 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HANDOFF — Session State
## Branch / Commit State
**`main`**. TASK 31 (SceneGraph + baked-crust compositor) implemented, tests green,
docs updated — **uncommitted**, ready to commit as one work unit (pending push at
the user's checkpoint).
**Pushed** (reached `origin/main` == `85893ea`, incl. tags): Phase 1 commit `0` +
refactor commits `1..11` + **Phase 2 commits `12..18`** + the `Controls/index.md`
docs commit `cb54637` + **Phase 3 splits A–E** (tags `refactor-commit-A..E`) +
**Commit F (Recording, `refactor-commit-F`)** + **Commit G (ChatOverlayLayer,
`refactor-commit-G`)**. Everything before TASK 31 is pushed; nothing local-only.
**Commit log (all pushed):**
| Commit | Hash | Tag | Payload |
|--------|------|-----|---------|
| docs | `cb54637` | — | `Controls/index.md` |
| A | `6944db8` | `refactor-commit-A` | split `MainViewModel.cs` core → **495** |
| B | `31362d1` | `refactor-commit-B` | split `MainViewModel.Streaming.cs` → **330** |
| C | `fab2e09` | `refactor-commit-C` | split `MainViewModel.Background.cs` → **418** |
| D | `d3271a0` | `refactor-commit-D` | trim `SocialsDialogViewModel.cs` → **334** |
| E | `dcb3637` | `refactor-commit-E` | split `LayoutStore.cs` → 6 partials |
| F | `3107f92` | `refactor-commit-F` | extract recording concern → `MainViewModel.Recording.cs` |
| G | `85893ea` | `refactor-commit-G` | **first true decomposition** → `Services/ChatOverlayLayer.cs` |
## What's In Flight
**TASK 31 (SceneGraph + baked-crust compositor) implemented — uncommitted, tests green.**
Files touched (see `git status`): `Models/SceneElement.cs`, `Models/Source.cs`,
`Models/WebcamSceneConfig.cs`, `Services/SceneGraph.cs` (new), `Services/Compositor/SceneCompositor.cs`,
`Services/Encoder/FramePump.cs`, `ViewModels/MainViewModel.cs`, `MainViewModel.Scenes.cs`,
`MainViewModel.Sources.cs`, `MainViewModel.Webcam.cs`, `MainViewModel.Background.cs`,
`ytLive.Tests/SceneGraphTests.cs` (new), `ai.md`, `TASKS.md`, `HANDOFF.md`.
Verification: SceneCompositorTests 4, StretchMathTests 4, BackgroundTests 16,
SceneCatalogTests 18, LayoutStorePersistenceTests 12, FramePumpTests 9,
SceneGraphTests 1 — all green. RealAppHost GUI tests hang headless (pre-existing).
Next: run `scripts/verify.sh`/`scope-check.sh`, commit, await user's push go-ahead.
**The directive (2026-08-31, user):** rewrite the project, breaking files into
**functional components to compliment AI retrieval/processing** — NOT line-count
chasing. Line count is a guideline for context management, not a design goal.
**What was done:**
- **Phase 3 (A–E):** every production `.cs` ≤ 500, grouped by concern. These are
*partial shuffles* — same class, same shared state. Marginal for retrieval.
- **Commit F:** recording-output concern → `MainViewModel.Recording.cs` (partial).
- **Commit G — the real win:** `Services/ChatOverlayLayer.cs` is a genuine
owner-state component (buffer + renderer + timers + preview + live `RenderFrame`);
`MainViewModel.Chat.cs` 194 → 44 (thin binding facade). First true decomposition.
**Expert diagnostic (recorded in `ai.md` → Key patterns):** the remaining partials
(Audio, Webcam, Background, Scenes, Socials…) are **binding glue over already-
extracted services** (`AudioMixer`, `CameraManager`, `ScreenCaptureManager`,
`ChatBoxRenderer`, `SocialValidator`). They have no cohesive owner-state blob to
peel — forcing extraction adds coupling. **Chat was the one clean peel.**
**Next (recommended):** TASK 31 landed the *core* of the scene-graph architecture
(the `SceneGraph` owner-object owning the collection + mutation surface, and the
baked-crust compositor optimization) without the full binding-surface peel. The
remaining step is the ViewModel-as-thin-facade migration (moving the many
`Scenes`/`StagedScene`/`LiveScene` binding call sites onto the graph) — deferred
as post-1.0 in `TASKS.md` because it is exactly the "unsupervised blind peel"
regression risk. Do it at a real Windows session where the GUI tests can run.
**Pending bus:** `ViewModels/index.md` Phase 3 tracker has rows A–E (closed);
Phase 3 marked COMPLETE. Watch-list (under limit, no action): `Controls/PreviewPane.xaml.cs`
(464), `ViewModels/MainViewModel.Audio.cs` (408).
## Landmines
- **Pre-existing test failures (do not chase):**
`AudioPipelineTests.Mix_HonorsProviderGains_AndGameMute_KillsTheLoopback` +
`RoundClipInteractionTests.Round_Clip_Corner_Is_Grabbable_And_Shape_Is_Circle`.
- **Tests occasionally abort early (236/237)** — known flake, accepted by `verify.sh`.
- **App running locks `ytLive.exe`** → build fails MSB3027. Kill PID before building.
- **WinForm crash from `Window_PreviewMouseLeftButtonDown`** — handled in-side the
preview/left panel; don't add handlers that deref `OriginalSource` unguarded.
- **Controls cannot see `Window.Resources`** (converter rule, Commit 13): any
StaticResource the window once supplied must live at app level in
`Themes/Controls.xaml`. The 7 converters were promoted there.
- **Some control XAML needs its own `xmlns:models` / `xmlns:Helpers`** — a moved
block lost its namespace when it left MainWindow's root (LeftPanel hit this,
MC2000 "key null"). Always add the model/helper xmlns on each control root.
- **Name-looked-up host stubs must stay in the window:** `WebViewHostPanel`
(ctor `InitWebView2(WebViewHostPanel)`) and `ToastArea`
(`NotificationService.InArea("ToastArea")`) are resolved by name from the
window — keep them as window-root children, don't bury them in a control.
OverlayHost deliberately left them in place (Commit 18) for this reason.
- **Pre-commit gate:** `scripts/verify.sh` (0-warning build + full tests) and
`scripts/scope-check.sh "file1" …` — scope-check REQUIRES explicit file args.
- Build from WSL with the Windows dotnet host only (see `AGENTS.md`).
## Todo state
- MainViewModel refactor: **Phase 1 complete (11/11 partials)**, pushed.
- MainWindow.xaml refactor: **Phase 2 complete (6/6 controls)**, pushed at `1f4624c`.
- 500-line compliance: **Phase 3 complete (A–E, all ≤500)**, pushed.
- **True decomposition: Commit G — `Services/ChatOverlayLayer.cs` shipped + pushed** (first owner-state component; pattern recorded in `ai.md`).
- **TASK 31 — SceneGraph + baked-crust compositor: implemented, tests green, uncommitted** (core optimization + collection/mutation ownership + integration test; see `TASKS.md` for the 3 documented defensive deviations). The full ViewModel-as-thin-facade peel (moving the entire binding surface) is intentionally deferred post-1.0 — flagged in `TASKS.md`.
- TASK 3: 27/30 (preview compositor 16, text source 17, alerts 20 still open).
- TASK 4: ✅ shipped. TASK 9: items 1–3 shipped; 4–7 open. TASK 10: steps 1–7; Velopack pending.
- TASK 18: shipped, creator verification pending. TASK 19/23, 20, 21-A: shipped.
- TASK 22 (audio sync offset): not started — required for v1.
## Session summary (2026-08-31)
- Ran the **500-line Phase 3 split to completion** (A–E), then the continuation.
- **Re-structuring principle (user correction, 2026-08-31):** split by
**functionality**, so an AI can process one concern per file; the 500-line
count is a **ceiling**, NOT the target. Do not pad or reshape code to a number.
- **Correction of a false premise:** my plan to "extract FFmpegEncoder /
StreamHealthMonitor / FramePump" was a no-op — those already exist as
`Services/Encoder/*`. The honest seams were (F) the recording concern and
(G) the chat overlay.
- **Commit G = first TRUE decomposition:** `ChatOverlayLayer` owns chat state +
behavior; `MainViewModel.Chat.cs` 194 → 44 thin facade. This is the pattern
that actually compliments AI retrieval (one self-contained unit per feature),
unlike the partial shuffles of A–E, which only marginalize context because
every partial still shares the god-object's state.
- **Accident caught & recovered (Commit D):** a `> ViewModels/SocialsDialogViewModel.cs`
write that truncated the file it was reading left it at 1 line; restored via
`git checkout --`, re-ran from temp files. **Lesson** in `MyMistakes.md`: never
`awk … > SRC` while awking SRC; stage cuts into temp files, then assemble.
- Everything through G is **pushed to `origin/main` (`85893ea`)** with tags A–G.
- **TASK 31 implemented (uncommitted, tests green):** added `ElementKind` (Static/Dynamic);
created `Services/SceneGraph.cs` owning the collection + mutation surface + bake cache;
made `SceneCompositor` split-aware (`BakeStaticBase`/`CompositeLayers`/`Render(staticBase,split)`);
wired `FramePump` to the optimized path; invalidated the bake on static mutations; added
`SceneGraphTests.BakedStaticBase_WithDynamicLayer_CompositesCorrectly`. 3 documented defensive
deviations from the spec (ChatOverlayLayer stays decoupled; background helpers stay VM-static for
direct testability; full facade peel deferred post-1.0). See `TASKS.md` → TASK 31.