efe88b8a0b
The element-space raster builds on a TRANSPARENT base but BlitContentRaw's partial-alpha branch applied the opaque-dst source-over blend: color premultiplied by the sampled alpha, then alpha forced to 255. Pasting that raster saw a==255 and straight-copied darkened ink over the scene — a recording box that the raw-bitmap preview (correct alpha) never showed. Transparent margins and opaque content were unaffected, which is why every take looped on the page/CSS while the capture was transparent all along (15:51 dumps: alpha max 255, mean ~19, zero 57%). BlitContentRaw now takes transparentDst; the raster call passes true and writes straight color + straight alpha so the paste rows (BlendRowOpaque/Weighted) do the real source-over onto the opaque master. Master paths byte-identical. ONE integration test PasteCache_SemiTransparentLayer_RevealsBackdrop_NotOpaqueInk: 50%-blue over red reads (127,0,128) fixed vs (0,0,128) buggy — proven both ways (verified by stashing the fix: fails before, passes after). Clean build, 0 warnings; 22/23 compositor-class tests pass, the sole failure the documented pre-existing Composite_FullScene_MasterPixels pixel (1380,700). Alpha-compositing model: standard source-over with producer-cached surfaces, the OBS/libyuv paste model already cited in ai.md/MyMistakes (rawvideo recipe, row-blit BLEND_NONE / straight-alpha branches); full story in MyMistakes (RESOLVED entry). Per the good-dog rule: one integration test, memory updates (MyMistakes/ai.md/ HANDOFF) in the same commit.
76 lines
4.6 KiB
Markdown
76 lines
4.6 KiB
Markdown
# HANDOFF — 2026-09-12 (transparency: ROOT CAUSE FOUND + FIXED, awaiting the verify take)
|
|
|
|
## Branch / Commit State
|
|
|
|
`main` HEAD lands THIS WORK UNIT: the compositor alpha fix (see ✅ below) + its ONE
|
|
integration test + memory updates (`MyMistakes.md`, `ai.md`, `HANDOFF.md`). Ahead of
|
|
origin by ~22 commits. **NOT pushing** — user ruling: no push until web-overlay
|
|
transparency AND audio-silence are addressed. Nothing uncommitted at end of session.
|
|
|
|
## ✅ HONEST STATUS — THE TRANSPARENCY BUG IS IDENTIFIED
|
|
|
|
**Root cause found by reading the unread code path to the end (the handoff's live
|
|
suspect, now convicted):**
|
|
|
|
`SceneCompositor.BlitContentRaw` (SceneCompositor.cs, partial-alpha `else if (sa > 0)`
|
|
branch) applied the OPAQUE-dst source-over blend onto the paste-cache raster's
|
|
TRANSPARENT base: `dst = (src*sa + dst*inv)/255` with dst black → color premultiplied by
|
|
sa, then `dst[+3] = 255`. A 50%-alpha widget pixel became darkened color + FULL alpha; at
|
|
paste time `BlendRowOpaque` saw alpha 255 → straight copy → the scene behind was
|
|
overwritten by darkened ink. Transparent margins (alpha 0) and opaque content (alpha 255)
|
|
survived, which is why every take showed a box while the dumps (raw capture) and the
|
|
preview (raw WriteableBitmap) stayed correct. The CSS-wipe fixes (`b4bba4b`/`0f72c53`)
|
|
were red herrings — they treated the PAGE as the villain, but the capture was transparent
|
|
from the start (the 15:51 dumps already proved it).
|
|
|
|
**The fix (committed):** `BlitContentRaw` gained `transparentDst=false`; the raster call
|
|
passes `true` and writes straight color + straight alpha so the paste rows
|
|
(`BlendRowOpaque`/`BlendRowWeighted`) do the real source-over onto the opaque master.
|
|
The two blend rows were verified correct all along (HANDOFF accepted facts held); the
|
|
divergence was the sampler feeding them. Master paths are bit-identical (`transparentDst`
|
|
defaults false).
|
|
|
|
**Verification:** clean build 0 warnings (app + tests); `SceneCompositorTests` +
|
|
`SceneGraphTests` + `FramePumpTests` + `ChatOverlayLayerCacheTests` = 22 pass, the ONE
|
|
failure is the documented pre-existing `Composite_FullScene_MasterPixels` pixel (1380,700)
|
|
(reproduces with the fix stashed — see ai.md slice 9). The new
|
|
`PasteCache_SemiTransparentLayer_RevealsBackdrop_NotOpaqueInk` test FAILS on the old code
|
|
(exact signature: `pixel (16,16): expected rgb(127,0,128), got rgb(0,0,128)`) and PASSES
|
|
on the fix — non-vacuous, proven both ways.
|
|
|
|
## NEXT STEP — ONE take (verify, no further analysis)
|
|
|
|
The Good Dog Rule is satisfied (ONE integration test shipped with the fix). Record the
|
|
Live scene with the widget animating, pre-record ~35s so the 30s re-arm dump fires
|
|
mid-take, then read the verdict:
|
|
- Element rect shows the scene backdrop behind the widget art (no black box/void, no
|
|
darkened edge ring) → **transparency CLOSED, push gate #1 clears**.
|
|
- If anything persists, the fix's own test contract is the diagnostic: a translucent
|
|
pixel must read as scene-through-src, never inked — bring the take.
|
|
|
|
## Other threads (paused)
|
|
|
|
- **Audio silence** — `f3d578c` has per-5s `Audio live:` telemetry; next take with
|
|
desktop audio ACTIVE names the stage. Push gate #2.
|
|
- **Webcam missing** — "MJPG negotiation refused (being used by another process)". Queued.
|
|
- **Web capture speed** — ~10-14Hz effective, user satisfied. Revisit only on request.
|
|
- **Layer order** — dragging an element over another does not persist `SortOrder`; user
|
|
explicitly asked it not be buried. Queued after transparency.
|
|
- **Known backfills when queued work resumes:** `Composite_FullScene_MasterPixels` pixel
|
|
(1380,700) cyan-vs-magenta (pre-existing, recorded in ai.md slice 9); vertical-tier
|
|
`BilinearScale` fresh allocation per frame.
|
|
|
|
## Landmines
|
|
|
|
- testhost shares startup.log with the app — filter by time.
|
|
- `taskkill //F //IM ytLive.exe` before rebuilds; re-run if `MSB3021` copy-lock.
|
|
- Build/tests: `/mnt/c/Program Files/dotnet/dotnet.exe build …` / vstest. 0 warnings rule.
|
|
FULL-suite vstest can hang (WASAPI teardown, pre-existing) — per-class filters are the
|
|
norm (`--TestCaseFilter:"FullyQualifiedName~…"`).
|
|
- Probing: `/mnt/c/Program Files/Krita (x64)/bin/ffmpeg.exe` / `ffprobe.exe` — Windows
|
|
exes take Windows-style paths (do NOT re-download Linux ffmpeg — user aborted that).
|
|
- Evidence artifacts (keep): `%TEMP%\ytLive-web-8d7234ec-…-w1..5.png` (15:51),
|
|
recordings `ty-20260910-12\51|1534|1551-*.mp4`, decoded frames at
|
|
`/mnt/c/Users/gramp/AppData/Local/Temp/w151.raw`.
|
|
- The full transparency story lives in `MyMistakes.md` → "SPIN GUARD → RESOLVED" (now
|
|
including the 2026-09-12 RESOLVED entry). GREP IT FIRST. Do not re-derive a fourth time. |