# Handoff Where the work in flight stands. The durable layout design, the measurement method and the findings that outlived the working log are in `docs/LAYOUT.md`. ## The Iris layout repair is submitted **Iris PR #19** (`layout/one-ask` at `cadfba0`, 123 commits over upstream `main` at `ca2b4b2`) is open and waiting on Bryan. It **replaces #18**, which is closed and whose branch `split/18-position-chain` stays as the reviewed baseline the newer work was measured against. Bryan decided on 2026-09-19 that the experiment replaces it, because it is more performant where it matters. The checkout is `/home/bob/repos/iris-layout-experiment`, on branch `wip/hint-first`, which is the same commit as `layout/one-ask`. Both are pushed to `origin` (`iris-ai/iris`). What the branch does and what it leaves undone is in the PR description; the settled protocol is in `docs/LAYOUT.md` under "Frames, decided boxes and padding". Verification at `cadfba0`, all run in this checkout: | check | result | | --- | --- | | `cargo fmt --all --check`, clippy `-D warnings`, with and without `layout-diagnostics` | clean | | `cargo test --workspace` | 123 suite, 20 core, 11 generated, green | | `cargo test --release --test generated` | 11/11 | | shrinker, 400 seeds, depth 5, sixteen cases | agree, 60 s | | 1000 seeds at depth 6 | agree, 177 s | | 2000-seed depth-4 scan, sixteen cases | agree, 295 s (82,203 widgets) | | cold dump of 400 trees at depth 5, diffed against `f6242aa` | identical, 34,488 widget boxes | | counters, seeds 1 and 13 at depth 8 | unchanged from `f6242aa` (the table is in `docs/LAYOUT.md`) | | five renders, the `tabs` replay, a live resize against a cold render | all byte-identical to `a888717` | The renderer was Vulkan on the host's RX 7900 XT: `src/default/render.rs` asks for `Backends::PRIMARY` and `.expect()`s the adapter, so a PNG at all means it was not the software fallback. ## What is next, in order 1. **Bryan's review of #19.** Fixes to it are unreviewed code: repeat the `pre-submit-review` passes over whatever each round changes, and re-run the three fuzzers and the dump diff for anything that touches `Span`, `Painter` or `render_state`. 2. **The app's Iris pin**, once #19 lands. It is still on the old submodule commit, and the branch changes API the app uses: `SizeRule` beside a widget rather than a wrapper, alignment as a widget property, `rest` renamed to `leftover`, `OrthoSize` gone. 3. **Round-to-nearest**, CPU and shader together as one verified change. Bryan approved it on 2026-09-17 and neither half has landed; the derivation, the form to use and what to re-check are in `docs/LAYOUT.md` under "Rendering the grid (pending)". ## Smaller layout items, none urgent - An undrawn `leftover` child still contributes its gap, so a vanished child leaves a double gap. - Nested spans pass `leftover` weight up, so three leftover children in one inner span beside one in another get three quarters to one quarter. No other layout system does that; confirm it is wanted. - A span can overflow itself without bound, so boxes of negative length reach children and nothing states what a widget may assume about one. - `Fixed::div` by zero answers `MIN`/`MAX` while `ratio` answers `ZERO`; both are caller bugs under `debug_assert`, but the fallbacks differ. - The comment on the `local == UiRegion::FULL` shortcut in `widget_at` says composing through `FULL` "is not quite the identity in f32"; on the grid it is exact and the shortcut is performance only. - `docs/LAYOUT.md` §4, §5 and the density section name `Painter::place`, `SetSize`, `desired_width`, `apply_rest`, `Len::dp`, `Aligned` and `MaxSize`, none of which exist. Do not restore `OnResize::Translate` or `OrthoSize`. - `LazySpan`, then `SizeRule::{Min, Max, Clamp}`. A cap may not contain `leftover`; whether `Max` narrows the child's drawing box is a product decision. - `Scroll` taking a direction rather than one axis. Other product work is in `docs/PLAN.md` and the focused documents it links. Do not mix it into the Iris layout branch.