# HANDOFF — 2026-09-21 (pricing docs UNCOMMITTED + TASK 38 Capture Window… implemented, UNCOMMITTED) ## Branch / Commit State `main` HEAD = **`523c17b` — docs(handoff): rewrite for pushed 0c55645** (last code commit is `0c55645`, ON-AIR armable signed-out — PUSHED). **Working tree DIRTY — TWO uncommitted work units:** **Unit A — pricing docs session (started 2026-09-21, still uncommitted):** ``` M Distribution.md M README.md M TASKS.md ← now also carries this session's TASK 38 row M TASKS/task-10-monetization.md M ai.md ← now also carries this session's Capture Window… bullet ``` `MARCOM.md` and `MONETIZATION.md` were also edited but are **gitignored (confidential)** — never committed. **Unit B — TASK 38 "Capture Window…" backdrop (this session, code + docs, uncommitted):** ``` M Controls/LeftPanel.xaml M Controls/LeftPanel.xaml.cs M Controls/PreviewPane.xaml M ViewModels/MainViewModel.Background.cs M ViewModels/MainViewModel.cs ?? Services/Win32WindowEnumerator.cs ?? ViewModels/MainViewModel.WindowBackdrop.cs ?? ytLive.Tests/WindowBackdropIntegrationTests.cs M ytLive.Tests/PillRadioTests.cs ← out-of-scope prerequisite fix (below) ?? Models/WindowInfo.cs ?? Services/IWindowEnumerator.cs ?? TASKS/task-38-window-backdrop.md ``` NOTE: `Models/WindowInfo.cs` and `Services/IWindowEnumerator.cs` show as `??` yet were already in the working tree before this session (referenced by ai.md) — they are new/untracked, so the seams grew out of existing code expecting them. ## ⚠️ Open action items / landmines - **Polar product `d105dfa1-497e-423b-8cd4-e0ee2e3abbc0` is still a `$99/yr` subscription** — must be re-created as **one-time** ($29 founder / $49 list) before launch. Flagged in `ai.md`, `TASKS/task-10-monetization.md`, `Distribution.md`. `LLAMA50` discount changed 12mo→`once`; `LLAMAFOUNDER` unchanged (100% off, 50 uses, `once`). - **PillRadioTests corruption fixed out-of-scope:** `ytLive.Tests/PillRadioTests.cs:105` had a COMMITTED stray token (`…PrimaryStartButtonLabel soil;` CS1003) that blocked the ENTIRE test project compile (no tests could run at all). Fixed by deleting the stray word — ONLY change to that file. It's committed upstream in `0c55645`; upstream history should get a fix commit, the working-tree file is clean of it now. Flagged so no one re-hunts it. - **Stale "behind the picker" fact**: ai.md §Screen backdrop capture previously claimed window capture (`window:`) is picker-only; corrected to note the in-app submenu + session-scoped transience (2026-09-21). ## What this session did (TASK 38 — "Capture Window…", creator ruling 2026-09-21) In-app window-picker submenu on the Live backdrop context menus (PreviewPane + layer-row). Picking a window pins it as the full-bleed layer-0 backdrop via `RedesignateBackgroundAsync("window:0x…")` — same capture path as game/desktop, `window:` already resolves in `ScreenCaptureSourceFactory`. Full rulings + shipped items in `TASKS/task-38-window-backdrop.md`. - New: `Win32WindowEnumerator` (EnumWindows, filtered like Win32FullScreenDetector), `ViewModels/MainViewModel.WindowBackdrop.cs` (`OpenWindows`, `RefreshWindowsCommand`, `CaptureWindowCommand`, `IsTransientCaptureKey`=`window:`+`picker:`, `IsAliveWindowPin`, `OnScreenCaptureFailed`). - Heals: `ReacquireScreenCaptures` strips transient keys before auto-detection (**session-scoped, HWND-recycle hazard**); `OnFullscreenMonitorChanged` respects a live window pin (**pin wins while alive**); `CaptureFailed` → auto re-acquire for transient keys (window death = no dead end). - Ctor order matters: `_windowEnumerator = WindowEnumeratorOverride ?? new Win32WindowEnumerator()` is assigned BEFORE `RefreshWindowsCommand`/`CaptureWindowCommand`/`RefreshOpenWindows()`. - LeftPanel row-menu bindings use Window-anchored `RelativeSource` (ContextMenu DataContext is the row Source, not the VM) — mirrors the existing PlacementTarget.Tag pattern. - **ONE Good Dog integration test** (`WindowBackdropIntegrationTests`): seam feeds the submenu; a persisted `window:` key heals away on reload; pinning an un-capturable window falls back to auto. NOTE: an earlier draft asserted the auto-fallback is non-empty — WRONG in the full suite, where ambient desktop state can legitimately yield `null` (static art). Final test accepts null as valid. - **Builds 0 warnings / 0 errors.** Full suite: **312/312 pass.** One wild-lasting detail: tests use the Windows dotnet host and MUST be rebuilt before vstest (stale-dll false failures). ## Pricing decision (2026-09-21) — record, do not re-derive One-time perpetual license: **$29 founder** (launch→first 90 days) → **$49 list** at GA. Buy once, own forever; `IsPremium` never lapses (renewal/lapse code path dead). Free tier = full app, watermark-only. Driver = accessibility. Full reasoning in `MONETIZATION.md` (§Pricing, "Why these numbers"). $49 anchor, **$29 floor — never below**. Docs cascaded (unit A above). ## Next step 1. User reviews/commits this work unit (code + `ai.md`/`TASKS.md`/`TASKS/task-38…`/`HANDOFF.md` in the SAME commit, per rules). **No push unless it's a milestone.** 2. Then the pricing docs unit (5 dirty files) per `TASKS/task-10-monetization.md`. 3. Then TASK 10 implementation (perpetual-key model — renewal/lapse removal). ## Critical working rules (unchanged, still binding) - **Good Dog = ONE integration test per change.** - **Scope lock:** declare the exact file list BEFORE editing; run `scripts/scope-check.sh` with the declared list before commit. No "while I'm here" edits. (Exception this session: the PillRadioTests syntax-error fix — required before ANY test could compile; declared at the time.) - **Run from WSL** always uses the Windows dotnet host (`/mnt/c/Program Files/dotnet/dotnet.exe`) with **quoted** paths; test filter runs via `dotnet vstest --filter …`. - **ai.md + code in the SAME commit**; rewrite HANDOFF.md at session end or interruption. ## Where the machine facts live - `%APPDATA%\ytLive\ytLive.db` = real layout DB (`layout.db` is a 0-byte legacy file). sqlite3 at `/root/android-sdk/platform-tools/sqlite3`. - ffmpeg/ffprobe: `/mnt/c/Program Files/Krita (x64)/bin/` with Windows paths. - `ai.md` §Local recording (TASK 18, ≈lines 605-640) = authoritative pill/state-model doc. - `ai.md` §Screen backdrop capture = authoritative backdrop/capture-key/heal doc (incl. the new TASK 38 bullet). - Business/marcom facts: `MONETIZATION.md` + `MARCOM.md` (both gitignored).