Record Iris review fixes, validation, and consolidated checkout

This commit is contained in:
iris-ai committed 2026-09-19 13:53:12 -04:00
1 parent 67584cedda
commit f3c9ab8106
3 files changed
+102 -52

No files matched your search

+35 -40
View File
@@ -6,52 +6,47 @@ in `docs/LAYOUT_LOG.md`.
## The Iris layout repair is submitted ## The Iris layout repair is submitted
**Iris PR #19** (`layout/one-ask` at `cadfba0`, 123 commits over upstream **Iris PR #19** (`layout/one-ask`) replaces closed #18. The current tip is
`main` at `ca2b4b2`) is open and waiting on Bryan. It **replaces #18**, which `84dad21`: `add6774` fixes collapsed-share placement, retained mask ownership,
is closed and whose branch `split/18-position-chain` stays as the reviewed and a redraw-on-reparent defect; `84dad21` removes repeated work in the test
baseline the newer work was measured against. Bryan decided on 2026-09-19 harness. `docs/LAYOUT_LOG.md` records the review and its regression coverage.
that the experiment replaces it, because it is more performant where it The core design remains sound; naming and round-to-nearest are unchanged.
matters.
The checkout is `/home/bob/repos/iris-layout-experiment`, on branch There is one Iris Git repository, stored with this checkout's submodule:
`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: - `/home/bob/repos/iris` is the active `layout/one-ask` worktree.
- `/home/bob/repos/ai-app-2/iris` stays on `main` at the app's `32f6ad8` pin.
It shares Git storage with the active worktree, rather than being a second
development repository. Keep it until the app's integration is ready.
- The standalone `iris-layout-experiment` clone is retired. Superseded fork
branches are removed; unique experiment tips and the #18 measurement
baseline are preserved under `archive/2026-09-19/` tags. A complete bundle
is also under `~/.local/state/iris/archive/`.
| check | result | Verification of the fixes: format and workspace clippy with `-D warnings`,
| --- | --- | workspace tests with and without `layout-diagnostics` (128 suite tests,
| `cargo fmt --all --check`, clippy `-D warnings`, with and without `layout-diagnostics` | clean | 20 core tests, 21 with diagnostics, and 11 generated tests), and the release fast oracle pass.
| `cargo test --workspace` | 123 suite, 20 core, 11 generated, green | The 400-seed depth-5 shrinker, 1,000-seed depth-6 run, and 2,000-seed
| `cargo test --release --test generated` | 11/11 | breadth scan all pass. The cold dump covers 34,488 boxes; 650 change because
| shrinker, 400 seeds, depth 5, sixteen cases | agree, 60 s | of the collapsed-share correction. With only that correction withheld,
| 1000 seeds at depth 6 | agree, 177 s | the remaining fixes reproduce the baseline dump exactly.
| 2000-seed depth-4 scan, sixteen cases | agree, 295 s (82,203 widgets) | The headless `tabs` example and the exact collapsed-share repro were rendered
| cold dump of 400 trees at depth 5, diffed against `f6242aa` | identical, 34,488 widget boxes | and inspected; the latter places the blue tail at x=220..400. The machine's
| counters, seeds 1 and 13 at depth 8 | unchanged from `f6242aa` (the table is in `docs/LAYOUT.md`) | Vulkan device is the RX 7900 XT through RADV native context.
| 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 ## What is next, in order
1. **The two defects the review of #19 found**, written up with their 1. **Bryan's review of #19.** Fixes are themselves unreviewed code: repeat
repros and fixes in `docs/LAYOUT_LOG.md`: a span misplaces the slot after `pre-submit-review` over each round's changes, and re-run the three
a collapsed `leftover` child, and a reused child keeps the mask its fuzzers and dump diff for edits to `Span`, `Painter`, or `render_state`.
parent replaced. Both are live at `cadfba0` and neither has a test. The ordinary oracle does not replace absolute geometry and
2. **Bryan's review of #19.** Fixes to it are unreviewed code: repeat the retained-primitive expectations.
`pre-submit-review` passes over whatever each round changes, and re-run 2. **Integrate the app's Iris capabilities before changing its pin.**
the three fuzzers and the dump diff for anything that touches `Span`, `32f6ad8` has 45 commits not reachable from the review branch; shared UI
`Painter` or `render_state`. ownership, richer masks, Android support, and app-side performance work
3. **The app's Iris pin**, once #19 lands. It is still on the old submodule must survive the integration. Then migrate `SizeRule` beside widgets,
commit, and the branch changes API the app uses: `SizeRule` beside a alignment properties, `rest` to `leftover`, and removal of `OrthoSize`.
widget rather than a wrapper, alignment as a widget property, `rest` 3. **Round-to-nearest**, CPU and shader together as one verified change.
renamed to `leftover`, `OrthoSize` gone.
4. **Round-to-nearest**, CPU and shader together as one verified change.
Bryan approved it on 2026-09-17 and neither half has landed; the 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` derivation, the form to use and what to re-check are in `docs/LAYOUT.md`
under "Rendering the grid (pending)". under "Rendering the grid (pending)".
+10 -3
View File
@@ -302,6 +302,11 @@ physical pixels, unchanged.
## Masks ## Masks
This section and "UI ownership and frame access" describe the app's pinned
Iris implementation. The upstream #19 review branch still has single
rectangular masks and separate `UiData`/`UiRenderState`; adopting it requires
integrating the app-side capabilities as well as migrating layout calls.
A `Mask` references a rectangle primitive and its parent mask. Nested masks A `Mask` references a rectangle primitive and its parent mask. Nested masks
multiply coverage. Plain `.masked()` creates an undrawn rectangle at the multiply coverage. Plain `.masked()` creates an undrawn rectangle at the
widget's region; `.masked_by(shape)` draws the shape behind the content and widget's region; `.masked_by(shape)` draws the shape behind the content and
@@ -489,8 +494,8 @@ of its parent's frame and a local redraw walked back up the parent chain in
defensively on every use. defensively on every use.
- A retained drawing is reusable only when its `Holds` contains the new box - A retained drawing is reusable only when its `Holds` contains the new box
on both axes, its parent and region-node choice match, it is on the layer it on both axes, its parent and region-node choice match, it is on the layer it
was drawn on, and the widget is clean. A valid ordinary subtree moves by was drawn on, its inherited mask matches, and the widget is clean. A valid
recursive remap; a region node moves by one entry. A container that draws a ordinary subtree moves by recursive remap; a region node moves by one entry. A container that draws a
child to learn its size uses `Painter::child_layer_at`, the layer the child child to learn its size uses `Painter::child_layer_at`, the layer the child
will actually occupy. will actually occupy.
- An answer's validity and its final drawing's validity are independent. A - An answer's validity and its final drawing's validity are independent. A
@@ -506,7 +511,9 @@ of its parent's frame and a local redraw walked back up the parent chain in
draw it. Dirty size dependencies settle deepest-first. draw it. Dirty size dependencies settle deepest-first.
- A widget that creates a mask clips to and reports its box. Its own mask and - A widget that creates a mask clips to and reports its box. Its own mask and
its inherited mask are distinct retained state: the former says which mask its inherited mask are distinct retained state: the former says which mask
a move rewrites, while a local redraw receives the latter. a move rewrites, while a local redraw receives the latter. The owner retains
one mask reference and reuses its slot across redraws, independently of
primitive references; dropping the mask or undrawing the owner releases it.
- A span's leftover/no-leftover boundary is a strict structural decision, not - A span's leftover/no-leftover boundary is a strict structural decision, not
a tolerance. Derive the boundary through the inverse of the expression that a tolerance. Derive the boundary through the inverse of the expression that
places children. A cap may not contain `leftover`, because feeding the places children. A cap may not contain `leftover`, because feeding the
+57 -9
View File
@@ -6,12 +6,60 @@ nothing here is rediscovered. Each entry says who found it and when.
it (settled design, the measurement method) belongs in `docs/LAYOUT.md`, and it (settled design, the measurement method) belongs in `docs/LAYOUT.md`, and
the current plan is in `docs/HANDOFF.md`. the current plan is in `docs/HANDOFF.md`.
## What the review of #19 found (2026-09-19) ## Follow-up implementation review (2026-09-19)
Read at `cadfba0` in the `iris/` submodule of this checkout, which is the The ask/place split, window-unit frames, exact validity preimages, and
same commit as `layout/one-ask`. `cargo fmt --all --check`, clippy bottom-up dirty settling implement the settled design. Keep this approach.
`-D warnings` and the 123-test suite are clean there, so both defects below It does not guarantee one body call per widget: an unhinted descendant that
are live behaviour rather than anything the tests say. reports leftover weight still needs a room ask and a slot ask. The explicit
measurement redesign remains deferred until an app screen justifies it.
The fixes below are on `layout/one-ask` in `/home/bob/repos/iris`:
- A collapsed share advances both span cursors. The regression covers one
and two collapsed children in all four directions.
- A masking widget owns a mask reference and reclaims its existing slot on
redraw. Primitives retain their own references. Removing the mask,
undrawing its owner, freeing the widget, and replacing the root release
ownership; a changed inherited mask rejects drawing reuse. Tests check
actual primitive mask indices, movement with and without a region node,
child draw counts, clip removal/addition, and empty-mask slot reuse.
- **A further handover defect:** `draw_inner` saved the old parent only
after a redraw replaced `ActiveData`. The old parent therefore kept the
child in its list and could undraw the subtree after its new parent drew
it. Capture the old parent before replacing the record. A branch-switch
regression reproduces disappearing content when its new parent owns a
region node, and also checks the ordinary reuse path.
The mask and handover tests fail on the reviewed code and pass with the
fixes. The mask fix preserves child reuse rather than redrawing descendants
on every mask repaint. No naming sweep or rounding-policy change is included.
Validation: workspace tests with and without diagnostics, the release fast
oracle, and all three prescribed seed scans pass. Comparing 34,488 cold
boxes against `cadfba0` finds 650 changes; withholding just the collapsed-slot
fix reproduces the baseline exactly. This is an expected geometry correction,
not a cost-only change whose dump should remain identical. The tabs example
and an exact 400 px collapsed-share fixture were rendered and inspected.
Two test-harness savings leave the random stream and coverage unchanged:
`generated` constructs one plan per seed for its sixteen scenarios, and the
warm/cold comparison constructs its diagnostic ancestry lookup only after
finding a mismatch. No overall speedup is claimed; no deep profile was run.
**Integration is larger than an API rename.** The app's pinned `32f6ad8`
has 45 commits not reachable from this review branch. In particular, the
app's nested/shape masks and shared `Ui` ownership are absent here: #19's
mask is still a single rectangle and `set_mask` rejects nested masks. Keep
the app pin until those existing capabilities have been integrated. The
"Masks" and "UI ownership" sections of `LAYOUT.md` describe the app-side
implementation, not everything already present on the upstream review branch.
## Original review of #19 at `cadfba0` (2026-09-19)
The original review read `cadfba0`, then the tip of `layout/one-ask`.
`cargo fmt --all --check`, clippy `-D warnings` and the 123-test suite were
clean there. These are the original failures, fixed by the follow-up above.
### A span misplaces the slot after a collapsed `leftover` child ### A span misplaces the slot after a collapsed `leftover` child
@@ -80,11 +128,11 @@ per-widget mask slot kept across redraws, the way `UiRenderState::move_slot`
already keeps a move entry, so the index is stable and `reposition` goes on already keeps a move entry, so the index is stable and `reposition` goes on
updating the one the descendants name. updating the one the descendants name.
### Neither path has a test ### Regression coverage
The suite passes with and without both fixes. A span case belongs in Both paths now have regressions in `tests/cases/layout.rs` and
`tests/cases/layout.rs` and a mask-reuse case in `tests/cases/retained.rs` `tests/cases/retained.rs`; the follow-up above records the additional cases.
when they land. The descriptions above preserve the original failure at `cadfba0`.
### Clarity, in the order worth doing ### Clarity, in the order worth doing