Two rounds past the ninth sweep: `b295c8b` reads a share under a parent that divides nothing as a minimum, which is what Bryan said it means and what a span already did, sharing one comparison with it; `2dba90b` grows images in the generated trees, which is the only widget here whose hint is a length in pixels and so the only one that reaches the case. The dump baseline is 34,571 boxes now that the trees carry images, and a seed no longer names the tree it used to -- the log says what that costs and where those defects live instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
205 lines
12 KiB
Markdown
205 lines
12 KiB
Markdown
# Handoff
|
|
|
|
Where the work in flight stands. The settled layout design, the vocabulary
|
|
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 `2dba90b`,
|
|
and past the reviewed `cadfba0` it is twelve rounds, each described in
|
|
`docs/LAYOUT_LOG.md`:
|
|
|
|
- **The repair**, `add6774` and `84dad21` -- collapsed-share placement,
|
|
retained mask ownership, a redraw-on-reparent defect, and repeated work in
|
|
the test harness.
|
|
- **The vocabulary and the container API**, `5642f20` through `58ce74d`.
|
|
- **Naming**, `55df32a` through `40b89c1`.
|
|
- **A sweep over the logic those names exposed**, `8d2b7a5` and `6c84b6f`.
|
|
- **A clarity sweep**, `3da1c71` through `1ebd4d3` -- naming the pairs layout
|
|
returns, `Span::slot`, a diagnostic that printed the rel base while calling
|
|
it the box, and `in_parent` matching a place's own cases.
|
|
- **A quality sweep**, `aea0387` through `69ba915` -- a kept contract judged
|
|
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 `1096c31` -- a contract kept where the new window left
|
|
it out, a surface configured under its own texture, a counter naming the
|
|
wrong contract, things nothing reads, and a question asked through a value
|
|
rather than a reference.
|
|
- **A sweep over the shader boundary and the position widgets**, `b7b8d09` --
|
|
two constants the shader and the CPU both count in written twice, and a
|
|
`Scroll` positioning content the framework positions, which cost a redraw
|
|
at the default alignment.
|
|
- **A sweep over the rigs, `Fixed`, and `b7b8d09` itself**, `f8aa0c5` -- the
|
|
other half of that same `Scroll` test, which could never decide it; a grid
|
|
conversion and its helper that only their own test called; `Len`
|
|
arithmetic written a component at a time; a question asked through a value
|
|
one line from its `&self` sibling; and `run-headless.sh --resize` leaving
|
|
a replayed gesture scaled against the mode the output used to have.
|
|
- **A sweep over the tests and the seventh sweep's own fix**, `77ed7a2` --
|
|
four shrunk fixtures naming one widget under three names and counting
|
|
each in the list of boxes the case compares, seven copies of a helper
|
|
sitting at the top of the same file, the GPU rigs' adapter probe written
|
|
twice, a mask resolved three times, a field nothing reads, a shrinker
|
|
claim its own assertion does not make, and three stale numbers.
|
|
- **A sweep over the widget vocabulary and the eighth sweep's own fix**,
|
|
`c2b8bf8` -- a widget's own size hint overriding a length rule the hint
|
|
cannot express, marking a widget for redraw having no name at twenty-one
|
|
call sites, the helper the eighth sweep shared being unable to see the
|
|
defect it had just fixed, two bare arrays where the framework names the
|
|
pair, forty-five lines nothing references, and one word for two things.
|
|
- **A leftover as a minimum, and images in the trees**, `b295c8b` and
|
|
`2dba90b` -- a share under a parent that divides nothing losing the
|
|
overflow its pixels asked for, said as the place the parent gives and
|
|
sharing one comparison with the span; and `Image` grown in the generated
|
|
trees, which is the only widget here whose hint is a length in pixels.
|
|
|
|
The settled design of the vocabulary rounds is in `docs/LAYOUT.md` under
|
|
"Three names, and the one argument that says them". Bryan settled the API
|
|
over 2026-09-17 to 19; it is current, not frozen.
|
|
|
|
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, and `ai-app-2/iris` stays on `app-pin` at the
|
|
app's `32f6ad8` pin until the integration below is ready.
|
|
|
|
### The branch layout, and the trap that used to be here
|
|
|
|
`main` is PR #19's base and tracks `upstream/main` (`iris/iris`), so the
|
|
obvious commands are the right ones:
|
|
|
|
git merge-base main layout/one-ask # ca2b4b2, the PR's base
|
|
git diff main...layout/one-ask # exactly what #19 changes
|
|
|
|
It was not always so. Until 2026-09-20 `main` tracked `origin/main` -- the
|
|
*fork's* line, which carries the app's 45 commits, is not an ancestor of
|
|
upstream's main, and sat four merged pull requests behind it (#10 parley
|
|
text, #12 pointer routing, #16 draw/size merge, #17 headless rig). Diffing
|
|
against it showed all four as this branch's work, which is how the parley
|
|
migration's undo path kept being reported as #19's; the sixth sweep lost
|
|
half a session to it before Bryan caught it, and the fourth and fifth
|
|
sweeps deleted `Painter::text_data` partly on the same false reading.
|
|
|
|
Bryan asked for the setup fixed rather than documented. What changed:
|
|
|
|
- The app's line is now the branch **`app-pin`** (`32f6ad8`), pushed to
|
|
`origin`. That is the name to use for it; it is no longer called `main`.
|
|
- `main` points at and tracks `upstream/main`.
|
|
- `.gitmodules` pins the `iris` submodule to `branch = app-pin`, so
|
|
`git submodule update --remote` follows the app's line and cannot drag
|
|
the pin onto upstream.
|
|
- `git iris-base` and `git iris-diff` are still configured and still
|
|
correct; they now agree with plain `main`.
|
|
|
|
`origin/main` on the fork was force-pushed to match, and `origin/HEAD`
|
|
follows it, so a fresh clone of the fork with no `upstream` remote gets the
|
|
right base from the plain commands too -- verified by cloning one. The
|
|
fork is managed entirely by agents and nobody works from it directly, so
|
|
rearranging its branches is always safe where it improves the workflow
|
|
(Bryan, 2026-09-20); that licence does not extend to the `iris/`
|
|
repositories, which are what pull requests target.
|
|
|
|
The submodule's recorded commit is unchanged at `32f6ad8` and stays
|
|
reachable through `app-pin`, so nothing about the app's pin moved -- only
|
|
the name it is reachable by.
|
|
|
|
### How to check a round
|
|
|
|
**Always**, because they cost nothing: format, workspace clippy under
|
|
`-D warnings` with and without `layout-diagnostics`, the workspace tests, and
|
|
the **cold dump**. `layout_dump` over 400 depth-5 trees is **34,488** boxes
|
|
-- **34,571 since `2dba90b` grew images in the trees**; counted again on
|
|
2026-09-20, the fourth through eighth sweeps having all repeated 34,492, which
|
|
is a `wc -l` of the whole run rather than of its box lines -- 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. Count the lines
|
|
that are a box (`grep -cE '^[0-9]+ [0-9]+ '`), not the output. The repair moved 650 of those
|
|
boxes, all from the collapsed-share correction; every commit since has been
|
|
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
|
|
quarter of an hour and they exist to find logic that is wrong on some tree
|
|
shape, so a rename has nothing for them to find (Bryan, 2026-09-19). Never
|
|
start one and then edit the tree: cargo rebuilds mid-flight and exits 1 from
|
|
a compile error, which reads exactly like a fuzzer failure.
|
|
|
|
## 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 apply the gate above to
|
|
whatever each one touched. The ordinary oracle does not replace absolute
|
|
geometry and retained-primitive expectations. The seventh sweep is the
|
|
evidence: reading `b7b8d09`, the sixth sweep's own fix, found that it had
|
|
removed one dead operand from a test and left the one beside it.
|
|
The eighth adds a second lesson, about the tests themselves: a fixture a
|
|
fuzzer shrank is a regression test, so a round that rewrites one has to
|
|
prove the tree is the same rather than that the case still passes, since
|
|
a fixture that quietly changed still passes and covers nothing. The ninth
|
|
adds a third: where a round fixed a class of defect one instance at a
|
|
time, put the check in the shared helper, which both closes the class and
|
|
tests the instances that round said were already fine.
|
|
2. **A review of everything written before the review gate existed.**
|
|
`pre-submit-review` and the rule that nothing is submitted unreviewed
|
|
arrived on 2026-09-13, well after the Rust port and most of Iris were
|
|
written, so all of that code went in unreviewed and none of the sweeps
|
|
above covered more than the layout branch. It wants a pass of its own
|
|
(Bryan, 2026-09-20). The surface-texture defect in `02048ea` is the
|
|
argument: nothing about that arm was hard, and it was written wrong
|
|
anyway, which is what a first reader catches and a later sweep of some
|
|
other subject does not. Three things it already has waiting, left out of
|
|
#19 because they are outside its diff: `Align::tuple` and both
|
|
`partial_align`s have no callers, `Vec2::align`/`partial_align` are
|
|
`UiVec2`'s with a conversion in front, and `impl_op!` carries four
|
|
grammars of which `core/src/util/vec2.rs` uses two, one line apart.
|
|
`Align` now has `Index<Axis>`, so the `if let Some` each
|
|
`partial_align` writes twice collapses when that sweep reaches them.
|
|
3. **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. What has to survive is those capabilities,
|
|
not the calls the app makes today: the app is to be largely rewritten
|
|
against the new API rather than ported call by call, so nothing in Iris
|
|
is kept alive for the app's sake (Bryan, 2026-09-20).
|
|
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
|
|
derivation, the form to use and what to re-check are in `docs/LAYOUT.md`
|
|
under "Rendering the grid (pending)".
|
|
|
|
Wanted but not started, recorded in `iris/TODO`: transforms on a move entry,
|
|
so a whole subtree scales or rotates with one buffer write and no redraw.
|
|
Compose-style stretch at the end of a scroll area is the use that prompted
|
|
it. A move entry only translates today, and composing through one scales the
|
|
`rel` part while `px` passes through untouched, so fixed-size content and
|
|
glyphs do not follow a shortened entry.
|
|
|
|
## 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.
|
|
- A `leftover` under a parent that does not divide is a minimum size --
|
|
`max(box, px + rel*box)` (Bryan, 2026-09-20), which is a `SizeRule::Min` of
|
|
`rel(1.0)` and shares `Painter::longer_than` with the span. Done in
|
|
`b295c8b` for a widget its parent asks; `root_layout` still reads the old
|
|
way, for which see `docs/LAYOUT_LOG.md`.
|
|
- `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. `Min` is `Painter::longer_than` again -- a `leftover` where
|
|
nothing divides it is already a `Min` of `rel(1.0)` -- so it belongs on
|
|
that path rather than beside it.
|
|
- `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.
|