Files
ai-app/docs/HANDOFF.md
T

5.4 KiB

Handoff

Where the work in flight stands. The durable layout design and the measurement method are in docs/LAYOUT.md; what the review of #19 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 c55be21: add6774 fixes collapsed-share placement, retained mask ownership and a redraw-on-reparent defect, 84dad21 removes repeated work in the test harness, and 5642f20 through c55be21 are the vocabulary and API work below. The core design remains sound; round-to-nearest is still unchanged.

Two checkouts share one Git storage. /home/bob/repos/iris is the active layout/one-ask worktree; ai-app-2/iris stays on main at the app's 32f6ad8 pin, and is kept until the app's integration is ready.

Each round was checked with format, workspace clippy under -D warnings, the workspace tests with and without layout-diagnostics, the release fast oracle, and the three prescribed seed scans — 400 at depth 5, 1,000 at depth 6, 2,000 at depth 4. The cold dump covers 34,488 boxes: the fixes moved 650 of them, all from the collapsed-share correction, and nothing since has moved one.

The vocabulary and the container API are settled

5642f20 finished the rename decided on 2026-09-17, which frame's return as a length had left half-applied, and aeb60e5 finished the word frame itself. Three names, and only two of them are boxes:

  • region -- the box a parent asks a widget in. It draws there, and a text wraps at it. Was Painter::extent, ActiveData::part, DrawInfo::part, Placing::extent, LayoutHolds::extent.
  • placement -- the box its drawing ends up in, the size it reported, once it has answered. Equal to the region wherever it fills one. Was ActiveData::extent; placed_extent is now placement.
  • rel_base -- not a box: the length a fraction it declares or reports is a fraction of. Was frame, which said the wrong shape. Painter::frame_len() is Painter::rel_base(), LayoutHolds::frame_len is rel_base, and frame_and_extent is rel_base_and_region.

aeb60e5 also cut what a container has to say, since correctness and cost had been paid for and ergonomics had not:

  • Painter::widget_within(id, region) takes a box in the widget's own coordinates and derives the child's rel base from it, so Pad and Offset are one call each. Offset had been reading region_len, which pinned its drawing to a box length an offset does not depend on.
  • Painter::place_at takes the rel base, returns the answer, and draws the child where there is no answer to re-express. Span's second pass is one call, and its drawn_across bookkeeping is gone.
  • The rel base a container decides for a child is narrow_rel_base, and it takes impl Into<Option<[Option<Len>; 2]>>, so one that narrows nothing writes None. The resolved value stays the bare rel_base.
  • Part::All is a Part::WHOLE constant rather than a variant. It was exactly Of(UiSpan::FULL); measured at 0.07% of instructions retired against 0.04% run-to-run noise on a 60-seed depth-5 shrink.

Cold layout is byte-identical to 84dad21 across all of it, over 400 depth-5 trees.

What is next, in order

  1. Bryan's review of #19. Fixes are themselves unreviewed code: repeat pre-submit-review over each round's changes, and re-run the three fuzzers and dump diff for edits to Span, Painter, or render_state. The ordinary oracle does not replace absolute geometry and retained-primitive expectations.
  2. Integrate the app's Iris capabilities before changing its pin. 32f6ad8 has 45 commits not reachable from the review branch; shared UI ownership, richer masks, Android support, and app-side performance work must survive the integration. The app then absorbs the branch's vocabulary and container API, all of it already upstream: restleftover, SizeRule beside widgets, alignment properties, the removal of OrthoSize, the region/placement/rel_base names above, and widget_within/place_at.
  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

  • 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.
  • docs/LAYOUT.md §4, §5 and the density section name Painter::place, Painter::region(), 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.