From 718923c217190032258ce75cca9f56136ae50d4c Mon Sep 17 00:00:00 2001 From: iris-ai <4+iris-ai@noreply.localhost> Date: Sun, 20 Sep 2026 01:03:05 -0400 Subject: [PATCH] Record the fifth sweep and point the handoff at 7502176 The renderer, the text store, the input default and the harness, which the four earlier rounds did not read, plus a second look at `redraw`. --- docs/HANDOFF.md | 10 +++++-- docs/LAYOUT_LOG.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 8202196..c53929e 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -6,8 +6,8 @@ found is in `docs/LAYOUT_LOG.md`. ## The Iris layout repair is submitted -**Iris PR #19** (`layout/one-ask`) replaces closed #18. The tip is `69ba915`, -and past the reviewed `cadfba0` it is six rounds, each described in +**Iris PR #19** (`layout/one-ask`) replaces closed #18. The tip is `7502176`, +and past the reviewed `cadfba0` it is seven rounds, each described in `docs/LAYOUT_LOG.md`: - **The repair**, `add6774` and `84dad21` -- collapsed-share placement, @@ -23,6 +23,10 @@ and past the reviewed `cadfba0` it is six rounds, each described in against the placed box rather than the box asked about, two things nothing read, three reuse rejections the diagnostics could not see, and a fuzz case that ran only in the long scan. +- **A sweep over the renderer, the text store and the retained path**, + `d8d5122` through `7502176` -- a contract kept where the new window left + it out, a surface configured under its own texture, a counter naming the + wrong contract, and three things nothing reads. The settled design of the last three is in `docs/LAYOUT.md` under "Three names, and the one argument that says them". Bryan settled the API over @@ -42,7 +46,7 @@ the **cold dump**. `layout_dump` over 400 depth-5 trees is 34,492 boxes, and it is the only thing that catches two same-typed values being swapped, which is the failure mode of a rename or a move. The repair moved 650 of those boxes, all from the collapsed-share correction; every commit since has been -byte-identical to `84dad21`, the clarity sweep included. +byte-identical to `84dad21`. **Only when the change can alter what layout computes**: the three seed scans -- 400 at depth 5, 1,000 at depth 6, 2,000 at depth 4. They cost about a diff --git a/docs/LAYOUT_LOG.md b/docs/LAYOUT_LOG.md index 93b279c..beb8801 100644 --- a/docs/LAYOUT_LOG.md +++ b/docs/LAYOUT_LOG.md @@ -6,6 +6,78 @@ nothing here is rediscovered. Each entry says who found it and when. it (settled design, the measurement method) belongs in `docs/LAYOUT.md`, and the current plan is in `docs/HANDOFF.md`. +## Fifth sweep: the retained path, the renderer and the diagnostics (2026-09-20) + +Over the parts the four earlier rounds did not read -- the renderer, the +text store, the input default, the harness -- and once more over `redraw`. +Four findings, `d8d5122` through `7502176`. The cold dump is byte-identical +to `781199a` and all three seed scans pass (400 at depth 5 in 69.45s, 1,000 +at depth 6 in 214.69s, 2,000 at depth 4 in 419.50s). + +**A contract was kept where it no longer held** (`d8d5122`). The sibling of +`713e3e7`, in the same function. `redraw` keeps the narrower of the old and +the fresh contract so widening and narrowing back do not churn the parent. +The drawing's half asks `was_holds.contains(window, rel_base, region)` first; +the answer's half did not. A widget whose answer contract widened in a frame +that also resized the window therefore kept a range the new window is +outside, and the parent's next ask refused it and redrew the whole subtree -- +throwing away the drawing that widget had just made. Cost, not geometry: the +size kept is the size just reported. It needs both a resize the root does not +absorb and a mark on a deeper widget in the same frame, which is what +`a_contract_this_window_is_outside_is_not_kept` builds; it draws the leaf +twice at `781199a` and once with the guard in. + +**Configuring a surface under its own texture** (`02048ea`). wgpu 30 says at +both `Surface::configure` and `Surface::get_current_texture` that configuring +while a texture the surface handed out is still alive panics. The +`Suboptimal` arm of `UiRenderer::draw` configured with the texture it was +about to draw with in hand, so the first suboptimal frame -- a resize or a +display change on some drivers -- takes the app down rather than rebuilding +the swapchain. The texture is good for that frame, so it is drawn with and +presented and the rebuild happens after `present` consumes it. Not +reproducible on demand here; the claim rests on wgpu's own documented panic. + +**A counter named the wrong contract** (`9b4cc32`). `AxisHolds` is four +contracts and `diag::outside` counted three: a refusal because this window +is outside the range the drawing was made for bumped "reuse outside: a rel +base". A window range is pixels and a rel base pin is a window-unit length an +unchanged window can still change, so the rig answered "why did that +redraw?" with the wrong one for every resize. Same class as `8088a1f`. + +**Three things nothing reads** (`7502176`). `Axis::pair` and +`RegionAlign::NEAR` arrived on this branch with no caller and never got one; +`Holds::contains` took `&self` where its five siblings on the same `Copy` +pair take `self`. The comment beside a span's cross-axis accumulator said a +scalable child "makes Children scalable too" -- `Children` names nothing in +this repository, and what it makes scalable is the span. + +### Tripped a rule and left as it stands + +- `Painter::text_data` has no caller either, and is the only way a widget in + `draw` can reach `TextData` at all (`painter.rsc` is private). It replaces + `main`'s `text_resources`, which the app does not call today but which the + pending integration may want. Deleting a framework's one escape hatch to + the text store while the app is still on the old pin is not a sweep's call. +- `TextData`'s spare store clones the whole string into `Placed` on every + re-break. Bounded at 128 entries, but the clone is per re-break and + proportional to the text; a transcript-sized text would pay it on every + width change. Left because a cheaper key changes what "two texts of the + same words share an answer" means, which is a design question. +- `TextEdit`'s undo history pushes a whole copy of the text per changed + keystroke and is never bounded, and `apply_event` clones the text on every + event including the arrow keys. Both are on `main` verbatim and unchanged + by this branch, so they belong to a change of their own. +- `ActivationState::update` writes four arms where the `Start`/`On` and + `End`/`Off` pairs are identical, and `is_off` is `!is_on`. Also verbatim + from `main`. +- `TextView::draw`'s empty-with-hint branch matches on `self.hint` again + after `is_some()` guarded it, so its `None` arm is unreachable. The guard + cannot become an `if let` because `self.render(painter)` needs `&mut self` + between the two. Left rather than cloning the handle to satisfy the shape. +- `CurrentSurfaceTexture::Lost` is answered by reconfiguring, where wgpu says + to recreate the surface. It will not panic, and recreating needs the + window; worth doing with the next renderer change rather than this one. + ## Quality sweep of the whole branch (2026-09-20) A fourth sweep, over the layout core, the arithmetic, the atlas, the sensor