Eight findings in iris `c2b8bf8`, the largest a widget's own size hint overriding a length rule that hint cannot express -- which no widget here but `Image` can reach, so the dump is unchanged and the case builds its own widget. The lesson for the next round is in the handoff beside the seventh and eighth sweeps' own: where a round fixed a class of defect one instance at a time, the check belongs in the shared helper, which closes the class and tests the instances that round said were already fine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
193 lines
11 KiB
Markdown
193 lines
11 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 `c2b8bf8`,
|
|
and past the reviewed `cadfba0` it is eleven 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.
|
|
|
|
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
|
|
-- 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.
|
|
- `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.
|