User launch (2026-09-01 19:07) NRE'd in MainViewModel ctor:
1. SceneGraph (TASK 31) was 'null!'-declared, assigned mid-ctor, but Scenes is touched
~120 lines earlier — field-initialized now.
2. LeftPanel extraction (c9fd1bd) moved StaticResource users (EyeButton/EyeIconStyle)
into a UserControl while the styles stayed window-scope — invisible at parse time;
moved to Themes/Controls.xaml (app scope, the existing rule). Full audit: these were
the only two offenders (grep of Controls/*.xaml StaticResource keys vs app dictionary).
3. RoundClipInteractionTests — the second 'known failure' the map never explained: it
was two stale-test layers (window.FindName across the new UserControl namescope +
VisualTreeHelper.HitTest, which returned the IsHitTestVisible=False WebViewHostPanel
overlay for EVERY point; UIElement.InputHitTest — the real input pipeline — shows the
corner IS grabbable in both Traditional and Round). Test fixed, no product bug.
Verified: clean rebuild 0 warnings; app boots (log shows full MainWindow loaded; user
clicked + closed, zero new exceptions; real DB Webcam row = the genuine C920, untouched);
RoundClip + 6 RealApp classes pass natively per-class.
Docs: ai.md known-failure note → 246/247 (audio only); TASK 31 verification paragraph
corrected ('cannot run headless' overstated — per-class Windows-host vstest runs them);
MyMistakes: InputHitTest-vs-VTH recipe + namescope/app-style + shared-log facts.
Spin-guard citations: WPF Visual Tree Overview (InputHitTest vs VisualTreeHelper hit
semantics) + XAML namescope docs, learn.microsoft.com.
7.0 KiB
MyMistakes.md
Two jobs, distinguished by heading:
- Per-task failure log — updated before every commit touching that task: current iteration + why the last one failed. On task complete, committed AND pushed → truncate to this stub. A new task does NOT seed this file until its first failure.
- Recipes registry (DERIVED-SOLUTION RULE, see
AGENTS.md🔬) — the durable home for one-off derived solutions, recipes, and how-tos. The moment you work out a reusable solution, write it here in the same session. GREP THIS FILE FIRST when you hit a "I've done this before but have to figure it out again" wall. Recipe entries stay permanently (they are NOT truncated on task completion) — only the failure log truncates.
🔬 Recipes registry
Shrink / re-encode an image for the README (screenshots → small hero image)
Worked out 2026-08-29 (the recipe was NEVER recorded the first time it was done, so it had to be re-derived from scratch — that's the incident this entry exists to end).
Approach: a throwaway Windows-dotnet console app uses WPF's imaging stack
(System.Windows.Media.Imaging) — same framework the app runs on, zero NuGet
packages, high-quality downscale via TransformedBitmap. Screenshots compress
far smaller as JPEG than PNG (PNG 1400px = ~1.2MB; JPEG q82 1400px = ~188KB).
Recipe (run via the Windows dotnet host from WSL):
- Create
imgresize.csprojtargetingnet8.0-windowswith<UseWPF>true</UseWPF>(SDK controller). Put it in a Windows-visible temp path, e.g.C:\Users\gramp\AppData\Local\Temp\imgresize— NOT/tmp(Windows dotnet can't reach a Linux-only path reliably). Program.cs: loadBitmapImage(CacheOption=OnLoad→Freeze()), downscale withTransformedBitmap(src, new ScaleTransform(scale, scale))to max width (1400 for the README hero), encode withJpegBitmapEncoder { QualityLevel = 82 }, save.- Run:
"/mnt/c/Program Files/dotnet/dotnet.exe" run -c Release --project .
-- "C:\Users\gramp\Downloads\Screenshot 2026-08-29 075626.png"
"C:\Users\gramp\Documents\Code\projects\ytLive\docs\ytLlive-preview.jpg" 1400
- Point
README.mdat the.jpg(not.png).
Result: 3.2MB screenshot → 1400×794 → 188KB ytLlive-preview.jpg in docs/.
Splitting a large file into partials — NEVER awk … > SRC while awking SRC
(2026-08-31, Commit D) Tried to split SocialsDialogViewModel.cs in one line:
{ awk '…' SRC; echo ""; awk '…2…' SRC; } > SRC. The first write truncated
SRC to 1 line, so the second awk read the already-truncated file → the whole
source was lost (1 line left). Recovered with git checkout -- SRC, then redid
it, but the same bug could have meant making it up from scratch.
Rule: when a cut needs N blocks from one source into N files, never write a
block back onto the source that the awks still read. Instead:
- Read the source once at the start into temp files (
mktemp -d, one file per block), with a$Dvariable you carry forward. - Verify block sizes (
wc -l) and brace balance (python3 -ccounting{/}) before touching any real file. - Then assemble each new file from
cat D/block …— never truncating the source until every read is done.
git status can't save you here if you don't notice until the file is gone —
git checkout -- <path> from the last commit is the recovery. Cheap insurance:
restore-then-retry, do it atomically from temp files the first time.
Verifying an ffmpeg decode contract from WSL (no real CLR needed)
(2026-08-31, TASK 21) When a change depends on ffmpeg producing output with an exact frame-size contract (rawvideo W×H×4 BGRA), you can prove the command + frame accounting here without any .NET process:
- Fetch a static Linux ffmpeg into
/tmp/opencode(no sudo needed):curl -sLO https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && tar -xf … - Generate a tiny known clip:
ffmpeg -f lavfi -i "testsrc2=duration=1:size=640x360:rate=30" -pix_fmt yuv420p clip.mp4 - Decode with exactly the app's args:
-f rawvideo -pix_fmt bgra -vf scale=640:360 -an - Assert
total_bytes % (W*H*4) == 0(python3) → exact integer frames, no pad.
Why not a dotnet-spawned ffmpeg here: the only CLR on this box
(/home/gramps/bin/dotnet) is a Windows-bound shim — Process.Start resolves
paths to \\wsl.localhost\Debian\… and throws "not a valid application for this
OS" when handed a Linux ELF ffmpeg. So never plan to have dotnet exec a Linux
ffmpeg here; verify the contract with shell/python instead, and leave the
CLR→real-ffmpeg run to the native Windows suite.
WPF hit-test truth in tests: UIElement.InputHitTest, NOT VisualTreeHelper.HitTest
(2026-09-01, the RoundClip "known failure" post-mortem — a failure the map carried as "not a regression" for weeks without ever recording WHY.)
The trap: VisualTreeHelper.HitTest(window, pt) returned the window's
WebViewHostPanel overlay (IsHitTestVisible="False", Opacity=0, ZERO children) for
EVERY point in the window — so a "corner is grabbable" assertion could never pass, and
it looked like a real interaction bug. The actual input pipeline (UIElement.InputHitTest,
what Mouse routing uses) correctly returned the element's Grid at elem-center/corner-in/
corner-exact and fell through to CanvasGrid just past the corner. The product was fine;
the TEST was probing an API that doesn't model input semantics.
Rule: any test asserting "where does a click land" uses window.InputHitTest(pt) +
IsDescendantOf — never VisualTreeHelper.HitTest.
Diagnosis recipe (how the lie was caught in ~3 probe cycles, no guessing): add a TEMP
probe [Fact] in the RealApp collection that hit-tests a spread of points
(elem-center / corner-in / corner-exact / corner-out / bg-center) and Assert.Fails with a
composed dump: per-point VTH hit + InputHitTest hit + ancestor chain (GetParent walk
with #Name) + panel properties (IsHitTestVisible/Opacity/children/actual size) +
TranslatePoint origins. Run the class alone, read the message, delete the probe.
Two sibling facts learned the same session (record-once):
- A UserControl owns its own XAML namescope — after extracting a region out of a window,
window.FindName("InnerPart")returns null; resolve the UserControl by its window-level name, thenpane.FindName("InnerPart"). And window-scope STYLES are invisible to a UserControl'sStaticResourceat parse time — move such styles toThemes/Controls.xaml(the app-scope rule exists for this). - Per-class
dotnet.exe vstestfrom WSL DOES execute the RealApp/MainWindowtests fine (they passed natively 2026-09-01) — only the FULL suite hangs (WASAPI startup). And the test process shares%APPDATA%\ytLlive\startup.logwith the real app: lines likecamera 'test-camera' failedare test noise, not DB state — to check pollution, query the DB directly (python3 sqlite3,SELECT DeviceId FROM Webcam), not the log.