# HANDOFF — Session State ## Branch / Commit State **`main`**, **working tree CLEAN.** TASK 18 (record-only pipeline + top-bar pills/light/Start-End button UX + Sign In label/spacing) **plus** the memory-map/derived-solution fix **and** the README hero image were committed and pushed as **`a9eb360`** (2026-08-29). `origin/main` and head both at **`a9eb360`**. No feature branches pre-1.0: all work lands on `main` per work unit. ## Memory-map corrections (2026-08-29 — "don't re-derive" fix) - **Incident:** the image-shrink recipe (for `docs/ytLlive-preview.jpg`) was never recorded when first done, so it was re-derived from scratch. Fixed by: - **`AGENTS.md`** → Working rules: new **🔬 Derived-solution rule** (record a one-off solution in `MyMistakes.md` the same session; grep it first on any "did this before?" wall). - **`MyMistakes.md`** → contract expanded: per-task failure log **+ RECIPES REGISTRY** (permanent, NOT truncated); recorded the verified image-shrink recipe. - **`schema.md`** → file inventory now rows `MyMistakes.md` as the recipes registry. - **`ai.md`** → Derivative-work section notes the derived-solution rule (registry reachable from map home). - **`README.md`** + `docs/ytLlive-preview.jpg` → README hero image replaced (screenshot downscaled to 1400×794, 188KB JPEG). ## TASK 18 — Local recording (shipped `a9eb360`, 2026-08-29) **Shipped (committed + pushed):** - `EncoderOptions` + `FfmpegArgs` + `FfmpegEncoder`: independent `StreamEnabled`/`RecordEnabled`/ `RecordPath`; per-output blocks (`-f flv` stream, `-f mp4` record); encoder throws unless ≥1 output. - `MainViewModel`: REC + ON-AIR pill toggles, status lights, dynamic `PrimaryButtonText` (Start Streaming / Start Recording), `ShowPrimaryStartButton`/`ShowLogInButton`/`ShowEndStreamButton`, `CanStartSession`, `AccountStatusLightToolTip`; `IsEditMode` += `!IsRecording`. - `StartSession()` routes: ON-AIR → GoLive dialog then stream (± record); only-REC → `BeginRecordOnly()` (no YouTube dialog). `StopStream()` no longer signs the creator out (explicit logout only) and runs **rename-on-stop** to `ty---.mp4`. - `Services/RecordingFile` (pure): auto-name `ty-…-0000.mp4` → rename-on-stop with hh2mm2 length. - `LayoutStore.Load/SaveRecordFolder` + `ChooseRecordFolderCommand` (`OpenFolderDialog`), default `%APPDATA%\ytLlive\recordings\`. - `MainWindow.xaml`: REC/ON-AIR pill `ToggleButton`s + status lights, dynamic button, status-light tooltip, About overlay border 520→650 / MaxHeight 560→700 / padding 24→28, About grid background `#171928`. - Tests: `FfmpegEncoderTests` record-only + dual-output arg tests; `RecordingFileTests` (naming rules). **Not done / parked:** manual rename dialog for the user (planned as a modal, needs a trigger since the toast service has no actions) — parked; running-app verification of rename + dual output. ## Key facts / landmines - **Pre-existing test failures (do not chase):** `AudioPipelineTests.Mix_HonorsProviderGains…` + `RoundClipInteractionTests.Round_Clip_Corner_Is_Grabbable…` — fail on `main` with this change unapplied. All other tests pass (incl. the 7 new recording tests). - **App running locks `ytLive.exe`** → build fails MSB3027 until the creator exits the app. - **Startup diagnostics:** `%APPDATA%\ytLlive\startup.log` (`Helpers/AppLog.cs`). - **Real-MainWindow tests MUST set `LayoutPathOverride`** — DB pollution wiped real data once. - **Good Dog Rule:** ONE integration test per change; no feature branches pre-1.0. - **Scope Lock:** declared list below; run `scripts/scope-check.sh` before committing. - **Every feature change ships memory updates in the SAME commit** — `TASKS.md` status + this file. - **Pre-commit gate:** run `./scripts/verify.sh ` — clean build (0 warnings) + full tests + scope check. Do NOT trust an incremental build's "0 warnings". - No `CODING.md`; conventions live in `AGENTS.md` + `ai.md`. ## Commit scope (declared) `Services/Encoder/EncoderOptions.cs Services/Encoder/FfmpegArgs.cs Services/Encoder/FfmpegEncoder.cs Services/Encoder/FramePump.cs Services/RecordingFile.cs Services/LayoutStore.cs ViewModels/MainViewModel.cs MainWindow.xaml ytLive.Tests/FfmpegEncoderTests.cs ytLive.Tests/FramePumpTests.cs ytLive.Tests/RecordingFileTests.cs AGENTS.md TASKS.md ai.md HANDOFF.md MyMistakes.md schema.md README.md docs/ytLlive-preview.jpg docs/ytLlive-preview.png(deleted)` ## Next steps 1. **Running-app verification** of TASK 18 (the one real gap): confirm rename-on-stop produces `ty-…-.mp4` and dual stream+record output actually works live. Requires the creator to run the app. 2. ~~Manual rename modal~~ **DONE** — `RenameRecordingDialog` (themed modal, pre-filled auto-stem, OK/Enter / Cancel/Esc, invalid-char + empty = keep-auto validation) shown at finalize in `FinalizeRecordingAsync`; reuses `YtTextBox`/`YtButton` styles. 3. Continue queue: TASK 21 media source, TASK 22 audio sync offset.