Files
LlamaCasty/HANDOFF.md
T
gramps 4e0915a36e feat(backdrop): Capture Window… in-app window pin (TASK 38, Good Dog ONE test)
Click-to-pin an open window as the full-bleed Live backdrop, via the existing
window:<hwnd> capture path (same render layer as game/desktop). Session-scoped:
window:/picker: keys heal to auto on reload (HWND-recycle hazard); pin wins
while the window enumerates, then auto-fallbacks (game → desktop → static); a
dead window's capture session heals to auto, no dead ends.

Fix: ScreenCaptureSourceFactory.Resolve hex-parsed "window:0x<Hwnd>" WITHOUT
stripping the 0x prefix — NumberStyles.HexNumber rejects it, so every pin
resolved null ("No capture target for this key") and the heal silently rolled
back. Same flaw in IsAliveWindowPin (pin-wins guard was dead). Both fixed.

Commit also carries an out-of-scope prerequisite: PillRadioTests.cs:105 had a
committed stray token ("...PrimaryStartButtonLabel soil;", CS1003) blocking the
whole test-project compile — token removed.

Plus the previous session's uncommitted pricing docs (one-time $29/$49) that
share TASKS.md/ai.md/HANDOFF.md.
2026-09-22 07:00:47 -07:00

6.5 KiB

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:<hwnd>) 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 <dll> --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).