Files
ai-app/docs/HANDOFF.md
T
iris-ai 3ecd676bcf Land the layout repair's findings and retire the working log
`docs/LAYOUT_LOG.md` existed until the one-ask protocol landed. It has, as
Iris PR #19 replacing #18, so what has to outlive the log moves into
`docs/LAYOUT.md`: the hint rule and the one ask a span makes, the reported
shares that are left and the two-answers design that would remove them, what
the fuzzers reach and what they cannot, the hypotheses not to repeat, and the
counter and dump commands with the numbers they print now. The handoff becomes
what it is for -- where the work stands, which is waiting on a review.
2026-09-19 02:57:17 -04:00

4.0 KiB

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.