diff --git a/HANDOFF.md b/HANDOFF.md index 09911db..afd865c 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -2,22 +2,25 @@ ## Branch / Commit State -**`main`**, dirty working tree being committed as one unit (web source rendering fix — user-confirmed -working). **NOT pushed — user rule: never push without explicit instruction (2026-08-24).** No feature -branches pre-1.0: all work lands on `main` per work unit. +**`main`**, working tree clean. Web-source bounding work is **DONE, verified, committed, and +PUSHED (2026-08-28)** — the first push in a while; the web feature is complete and on origin. +No feature branches pre-1.0: all work lands on `main` per work unit. -## The web-source rendering work (2026-08-28) — CURRENT MODEL: canvas-size viewport + ALPHA-BBOX crop +## The web-source rendering work (2026-08-28) — DONE: canvas-size viewport + ALPHA-BBOX crop -**History of failures (see MyMistakes.md for the full log):** box-size rendering clipped full-bleed -widgets to their upper-left chunk (fixed — page renders at the master canvas 1920×1080, stable, the -one render the creator confirmed solid). Then four crop attempts failed in different ways: (1) the -`JSON.stringify` return double-encoded under `ExecuteScriptAsync`, silently disabling the crop; -(2) `scrollWidth/scrollHeight` at canvas size returns the whole viewport for full-canvas wrapper -bodies → no trim (ghost boundary); (3) union-of-DOM-elements measured an unsettled layout on -NavigationCompleted and BROKE the image (creator's "don't break the rendering" boundary crossed). -(4) Reverting to f39ebd9's scroll-crop was another dead end (#2 again). +**VERDICT (creator, 2026-08-28):** bounding is PERFECT. Verified with a second widget resource that +has no glow effect. The earlier "remaining defect / dead-space gap" was the WIDGET'S OWN GLOW +effect pushing out its perceived borders — NOT a code bug. The alpha-bbox was already hugging the +glow halo; with a plain widget the dashed selection border sits exactly on the widget edge. -**The CURRENT MODEL (this commit):** +**History of failures (log wiped from MyMistakes.md per task-complete rule; see git history):** +box-size rendering clipped full-bleed widgets to their upper-left chunk; `JSON.stringify` return +double-encoded under `ExecuteScriptAsync` (crop silently disabled); `scrollWidth/scrollHeight` at +canvas size = whole viewport for full-canvas wrappers (no trim); DOM-element-union measured an +unsettled layout on NavigationCompleted (BROKE the image); sizing the container to the crop +(`ab29ec8`) made things worse (reverted). + +**The model that shipped:** - `Services/WebView2Manager.cs` — page renders at 1920×1080 (stable, never tracked); `overflow:hidden` + transparent-bg injection. `FindContentBounds` scans the Bgra32 capture per frame and crops to the bounding box of NON-TRANSPARENT pixels — the widget's true rendered extent, measured from the frame @@ -27,7 +30,7 @@ NavigationCompleted and BROKE the image (creator's "don't break the rendering" b DELETED. - `MainWindow.xaml` — web `` Stretch set to Fill via the IsWebSource DataTrigger (unchanged). - Invariant: **render at canvas size; crop to the alpha extent; Fill to the box.** -- Unit tests: 3 new for `FindContentBounds` (tight box, no-alpha no-crop, full-alpha no-crop). +- Unit tests: 7/7 (3 `FindContentBounds`, 4 control-size.) **Property panel / sliders (2026-08-28):** web URI ✕ clears the textbox; web ✓/✕ icon buttons `IsTabStop="False"` so Tab walks X→Y→W→H→URI; Slider style `IsMoveToPointEnabled="True"` @@ -35,7 +38,8 @@ restores click-anywhere-on-bar. All three confirmed fixed by the creator. Build: 0 warnings; tests 7/7 (WebView2Manager). Rejected for the record: box-sized viewport (upper-left truncation), fixed 1920×1080 + `Uniform` (letterbox dead space), CSS margin/100% reset (enlarged gap), -viewport==box (reflow/truncation/scrollbars), DOM-union crop (broke the image). +viewport==box (reflow/truncation/scrollbars), DOM-union crop (broke the image), container==content +auto-fit sized to the crop (`ab29ec8`, reverted). ## Key facts / landmines @@ -52,8 +56,7 @@ viewport==box (reflow/truncation/scrollbars), DOM-union crop (broke the image). - No `CODING.md`; conventions live in `AGENTS.md` + `ai.md`. ## Next steps -1. AWAIT creator's verdict on the ALPHA-BBOX crop — reload a widget URL at several box sizes; the - selection frame must snap flush to the widget with no dead space, image must stay identical for - full-bleed widgets. If an animated widget causes visible jitter, add crop hysteresis as a follow-up. -2. Follow-up only if the creator asks: graceful handling of navigation errors / invalid URIs (TASK 17 ×9). +1. Done (2026-08-28): web-source bounding verified PERFECT and pushed. If an animated widget causes + visible crop jitter later, add hysteresis as a follow-up — not queued. +2. Graceful handling of navigation errors / invalid URIs (TASK 17 ×9) — only if the creator asks. 3. Continue queue: TASK 18 local recording, TASK 21 media source, TASK 22 audio sync offset. \ No newline at end of file diff --git a/MyMistakes.md b/MyMistakes.md index 4f0588c..6c6b78a 100644 --- a/MyMistakes.md +++ b/MyMistakes.md @@ -2,46 +2,4 @@ > One task at a time. 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. - -## Task (active — committed `582d1f4`, NOT pushed, awaiting creator verification) -Stream widget bounding box: hug the widget on all four sides, pinned to canvas (0,0). - -## Iterations that failed -1. **e917c41 — fixed 1920×1080 viewport + `Stretch="Uniform"` + startup registration.** - Failed: `Uniform` letterboxed the 16:9 canvas into arbitrary‑sized boxes → asymmetric dead - padding read as a "gap". Lesson: Fill the box with the cropped frame, never Uniform. -2. **9d4103c — per‑document CSS reset (`html/body` width/height 100%) + (0,0) anchor.** - Failed ("enlarged the gap"): forcing dimensions overrode the widget's own layout and expanded - the dead space. Lesson: inject only `overflow:hidden` + transparent background — never set sizes. -3. **8d793af — viewport == element‑box size + `Stretch="Fill"`.** - Failed (janky / truncating / scrollbars): hosting at the box size clips full‑bleed widgets to - their upper‑left chunk, and tracking the box reflows the page on drag. Lesson: render at a - fixed canvas size, never track the box. -4. **f39ebd9 — crop capture to `scrollWidth/scrollHeight` bounds + (0,0) + Fill.** - Partially passed (panel fixes 1a/1b/4 confirmed) but the box stayed loose; the apparent - "tight right/bottom" was just the small‑viewport clip edge. **ROOT CAUSE: the crop never ran.** - The script returned `JSON.stringify(...)` (a string); `ExecuteScriptAsync` JSON‑encodes every - result, so the JSON was double‑encoded → `JsonDocument.Parse` got a string node → - `GetProperty` threw → try/catch swallowed → bounds unset → no crop. Lesson: return a real JS - object, never a stringified one. Also: scroll extents ≠ widget rect (they include page margins). -5. **70fe2b8 — fixed canvas‑size viewport (1920×1080) + crop + Fill.** - Image render/resize became solid (creator confirmed) but the box still gapped right/bottom and - wasn't 0,0. Same silent JSON bug — the crop still never executed — and the measure was scroll - extents regardless. Lesson: verify declared mechanics actually execute; assume nothing ran. - -## Current iteration (web bounding box — UNCOMMITTED, verification pending) -ALPHA-BBOX CROP: `FindContentBounds` scans the captured Bgra32 frame and returns the bounding box -of non-transparent pixels (the background is injected transparent, so alpha = the widget's extent). -Capture is cropped to that rect and `Stretch="Fill"` maps it flush under the box. No DOM query, no -layout timing — the crop rect IS the rendered widget by construction, so it can NEVER truncate -visible content. Worst case (widget fills the canvas) = full frame = the confirmed-good render. -Canvas-size viewport + Fill untouched. `QueryContentBoundsAsync` + the JS script are DELETED. - -## Iteration that just failed (`a5b9952` — wrapper-excluded DOM-union crop + image alignment) -Broke the image rendering — creator could not evaluate the box because the image was gone/ruined. -Why: the visible-element-union rect is measured ONCE on NavigationCompleted; widget layout isn't -settled then (async fonts/images, load animations, iframes), so the crop rect comes out tiny/wrong -and the Fill-stretched frame renders a broken/zoomed sliver. This was against the creator's explicit -"don't break the rendering" instruction. Lesson: measure actual RENDERED PIXELS (alpha), never -transient DOM state; and never ship a crop blind. \ No newline at end of file +> A new task does NOT seed this file until its first failure. \ No newline at end of file diff --git a/TASKS.md b/TASKS.md index a43ef13..921e8fc 100644 --- a/TASKS.md +++ b/TASKS.md @@ -917,16 +917,21 @@ capturing the primary display (which causes the infinity mirror effect). 8. ✅ Preview shows live web content (not just a blank rectangle) 9. ☐ Handle navigation errors, invalid URIs, timeout gracefully -**Rendering model (2026-08-28, canvas-size viewport + ALPHA-BBOX crop):** +**Rendering model (2026-08-28, canvas-size viewport + ALPHA-BBOX crop — DONE, creator-verified):** the page renders at the MASTER CANVAS size (1920×1080), stable, never tracked (no reflow/truncation; scrollbars suppressed via `overflow:hidden`). `FindContentBounds` scans the Bgra32 capture and crops to the bounding box of non-transparent pixels — the widget's true rendered extent, measured from the frame itself (NO DOM query, immune to layout timing; can never truncate content; full-canvas widgets fall through to the full frame = prior verified-good image). `Stretch="Fill"` maps the cropped frame flush under the selection box → box hugs the widget on all four sides. `QueryContentBoundsAsync` + -the JS content-bounds script are DELETED. ⚠️ Lesson bank: never return `JSON.stringify` from -`ExecuteScriptAsync` (double-encodes); never measure DOM stuff on NavigationCompleted (unsettled -layout broke the image — `a5b9952`); measure rendered pixels instead. +the JS content-bounds script are DELETED. **RESULT: bounding verified PERFECT by the creator with +two widgets.** Root-cause note on the earlier "remaining defect/gap": that was a WIDGET GLOW EFFECT +(the widget's own CSS glow pushes out its perceived borders), not a code bug — the alpha-bbox was +already hugging the glow halo. Lesson: test with a second, plain widget before changing code. +⚠️ Lesson bank: never return `JSON.stringify` from `ExecuteScriptAsync` (double-encodes); never +measure DOM stuff on NavigationCompleted (unsettled layout broke the image — `a5b9952`); avoid +sizing the container to the crop (`ab29ec8` reverted — made it worse); a widget glow effect can +fake a gap — verify with a plain widget first; measure rendered pixels instead. **Properties panel (2026-08-28):** web URI ✓/✕ icon buttons are `IsTabStop="False"` so Tab flows X→Y→W→H→URI; the ✕ button now clears the URI textbox (was reverting to the pre-accept snapshot).