diff --git a/HANDOFF.md b/HANDOFF.md index 8e9b271..7782556 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -7,34 +7,39 @@ ## Session state (last updated: 2026-08-13) -- **Branch:** `main`. The audio UX follow-up (`9f9ed34`), round 2 (`18abe42`), - and round 3 (`dc29adf`) are **committed and pushed**. -- **This session (TASK 4 ship step 6 — health stats in the bottom bar):** - 1. **Wiring:** `MainViewModel.OnFramePumpHealthUpdated` subscribes to - `FramePump.HealthUpdated` and marshals onto the UI thread (the encoder's - stderr loop raises on a background thread — same pattern as the audio - level handlers), copying the parsed bitrate/FPS/dropped/duration into - `CurrentHealth`, which the bottom bar's left stats group already binds - (bitrate/FPS/dropped/duration/health-message). - 2. **Session hygiene:** `ResetHealth(status)` zeroes dropped frames + the - elapsed duration (and clears `LastError`) on go-live and on End so stats - never linger from a previous stream; bitrate/FPS stay on the tier's - targets from `ApplyStreamQuality`. - 3. **Reality:** the bar lights up with REAL encoder values once TASK 5 fills - `_rtmpUrlProvider` with the reusable stream's ingest URL — until then the - pump skips the encoder (logged) and the bar shows the tier's targets. - No new tests needed: `FramePumpTests.HealthUpdated_ForwardsEncoderHealth` - already covers the pump→event seam; the VM handler is a thin marshal+copy. -- **Mic status contract (creator's rule, verified — do NOT "fix"):** the status dot is - **red until a mic resource is actually connected**. `MicStatus` starts `NotConnected` - (red); it goes green ONLY when the mixer's `MicConnected` fires, which comes strictly - from the mic source's `Started` event raised after `StartRecording()` succeeds. Zero - devices at startup → stays red and the mixer is never started; capture failure → yellow. - Green must never be raised earlier (e.g. on loopback start or on `Start()` being called). -- **Uncommitted:** this session — `ViewModels/MainViewModel.cs` (health wiring + - `ResetHealth`), `TASKS.md` (ship step 6 ✅), `ai.md`, `ViewModels/index.md`, `HANDOFF`. -- **Verified:** pending (build + full test run right before commit). +- **Branch:** `main`, in sync with `origin/main`. +- **This session (TASK 7 — UI polish batch, gramps's 6-point review):** + 1. **Scenes list cleaned:** the per-row edit/trash/visibility icons and the inline + rename TextBox are gone. Scenes are pure selection rows; `IsHidden` stays + persisted and still dims a hidden row to 45%. Removed dead surface: + `EditSceneCommand`/`RemoveSceneCommand`/`ToggleSceneVisibilityCommand` + + `BeginEditScene`/`ToggleSceneVisibility`/`RemoveScene` handlers + `Scene.IsEditing`. + 2. **Sources list upgraded:** each row now has edit + visibility eye + trash. New + `EditElementCommand` (`SceneElement.IsEditing` → inline rename TextBox, Enter/Esc/ + lost-focus commits) and `ToggleElementVisibilityCommand` (flips `SceneElement.IsVisible`); + the eye style now binds `IsVisible` and hidden rows dim to 45%. + 3. **Duplicate naming:** shared `NextSourceName(scene, baseName)` → `Image`, `Image2`, + `Image3`… (no space), next free number derived from actual names so deletions never + collide. Used by both `AddSource` and `AddReusedImage`. + 4. **Social bar:** `MaxWidth=200` + `CharacterEllipsis` removed from BOTH + `SocialBarRenderer.cs` and the preview DataTemplate — full validated handle renders. + 5. **Panels:** left 220 / right 300 fixed widths are deliberate — panels never re-layout + on resize; the preview absorbs it. No change. + 6. **Focus-loss capture lag:** recorded in `ai.md` as a known OS limit (DWM/WGC + throttling when unfocused + GPU readback contention + the `_framePending` / + `DispatcherPriority.Render` gates). NOT an in-app throttle; deferred by user decision. +- **Test infra change:** the two real-WPF-App tests (round-clip + new source-naming) now + share `RealAppHost` — a dedicated STA thread owning the single `App` — via the `RealApp` + serial collection. WPF allows exactly one `Application` per AppDomain; never add a test + that calls `new App()` directly again — marshal onto `RealAppHost` instead. +- **Uncommitted:** `MainWindow.xaml` + `MainWindow.xaml.cs` (rows), `ViewModels/MainViewModel.cs` + (commands + naming), `Models/SceneElement.cs` (+`IsEditing`), `Models/Scene.cs` (−`IsEditing`), + `Services/Compositor/SocialBarRenderer.cs` (no truncation), `ytLive.Tests/SourceNamingTests.cs` + (new), `ytLive.Tests/RealAppCollection.cs` (new), `ytLive.Tests/RoundClipInteractionTests.cs` + (now uses the shared host), `TASKS.md` (TASK 7 ✅), `ai.md`, `ViewModels/index.md`, `HANDOFF`. +- **Verified:** build 0 warnings / 0 errors; **170/170 tests pass** (169 + the naming test). - **Landmines:** + - Never add another test that constructs `new App()` — use `RealAppHost.Run(...)`. - Never set a local `Canvas.SetTop` on the social bar — a local value permanently overrides `{Binding SocialBarTop}` (the `ClearValue` lesson from 5.5). - `AudioMixer` meter `Push` is unconditional **by design now**: `OnMicSample`/ @@ -44,7 +49,7 @@ - `MicConnected` comes from the source `Started` event, raised right after `StartRecording()` succeeds — tests must `MarkStarted()` the fake source before asserting connection state. - - The mic dot is red until a resource connects (see contract above) — green + - The mic dot is red until a resource connects (see contract below) — green only after `Started`, yellow on `Failed`. - Zero mic devices at startup = red dot AND the mixer is never started, so loopback + the game bar can't run either (no capture at all) — acceptable. @@ -56,17 +61,22 @@ - `StopAsync` must stop the encoder (closes stdin) **before** awaiting the pump loop — closing stdin unblocks a write stuck on pipe backpressure; the reverse order deadlocks. - - Tests never instantiate `MainViewModel` directly except the round-clip - integration test (a real `MainWindow`), which never goes live — keep it that way. + - Tests never instantiate `MainViewModel` directly except via a real `MainWindow` + on the `RealAppHost` STA thread (round-clip + naming), which never go live. - Sandbox can't reach outbound HTTPS — `HttpSocialValidator` stub-handler tests only, never the real instance. -- **Next step:** commit + push this ship-step-6 work (one commit). Then the remaining - TASK 4 requirement is **ship step 7 — one-click go live + private-only enforcement** - (honor the dialog's chosen visibility / enforce `privacyStatus = "private"`; also - fixes the REC sign's private state — see round-3 note above). Also queued: task 21 - (logo + About hub), task 22 (voice filters). Nothing else queued — do not expand - the task queue on your own. Optional, not queued: rewriting the healed entry's - `ProfileUrl` to `https://mastodon.llamachile.tube/@gramps` (user must say the word). +- **Mic status contract (creator's rule, verified — do NOT "fix"):** the status dot is + **red until a mic resource is actually connected**. `MicStatus` starts `NotConnected` + (red); it goes green ONLY when the mixer's `MicConnected` fires, which comes strictly + from the mic source's `Started` event raised after `StartRecording()` succeeds. Zero + devices at startup → stays red and the mixer is never started; capture failure → yellow. +- **Next step:** commit + push this TASK 7 batch (one commit). Then the remaining TASK 4 + requirement is **ship step 7 — one-click go live + private-only enforcement** (honor the + dialog's chosen visibility / enforce `privacyStatus = "private"`; also fixes the REC sign's + private state — see round-3 note). Also queued: task 21 (logo + About hub), task 22 (voice + filters). Nothing else queued — do not expand the task queue on your own. Optional, not + queued: rewriting the healed entry's `ProfileUrl` to `https://mastodon.llamachile.tube/@gramps` + (user must say the word). - **Secret/DB/port facts live:** OAuth client id/secret in `Helpers/OAuthCredentials.cs`; OAuth session token in `Helpers/TokenStore.cs` (DPAPI → `%APPDATA%\ytLlive\ytLlive.auth`); diff --git a/MainWindow.xaml b/MainWindow.xaml index 5d09d35..d46a109 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -49,21 +49,21 @@ - + @@ -193,64 +193,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - + @@ -287,6 +231,11 @@ @@ -295,6 +244,8 @@ + + @@ -310,9 +261,51 @@ + Padding="4,2" TextTrimming="CharacterEllipsis"> + + + + - + + + +