Record the drift a partial repaint causes, and the rigs that reduced it

The oracle and the shrinker had separate generators and separate copies of
every scenario, so a failure one found could not be handed to the other: a
seed cannot be made smaller. Iris `98d4e98` splits growing a tree into
describing one and building it, and puts the cases in one place both rigs run.
Any failing seed now reduces with one command, which is written down here.

What it found first: marking one widget for redraw moves a span inside a
scroll 24px against a cold tree of the same state -- a whole child's height,
not a rounding. Five widgets, bisected to `95fb4f9`, where `Masked` began
reporting its box rather than its inner's size. Written out and ignored in
`tests/cases/unsettled.rs` until it is fixed.

Two claims in the verification list were withdrawn against a re-run rather
than an argument. The shrinker's "all five cases at 300 seeds of depth 5" does
not carry to a rig that runs fifteen cases over different trees and fails at
400. The 1000-seed depth-6 line does not hold at `5ed9e87` either, which fails
it on seed 40 after a resize -- so that run was never the clean baseline it
was quoted as.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-16 15:59:33 -04:00
1 parent 10e46522b4
commit bb5b79f2f6
1 file changed
+64 -9
+64 -9
View File
@@ -8,7 +8,7 @@ log.
Canonical Iris `main` is **`ca2b4b2`** (#17, the headless rig). **#18 Canonical Iris `main` is **`ca2b4b2`** (#17, the headless rig). **#18
`split/18-position-chain`** is open in `/home/bob/repos/iris-pr18`; its local `split/18-position-chain`** is open in `/home/bob/repos/iris-pr18`; its local
head is **`4febabf`**, seventy-one commits. Built-in alignment is complete there; head is **`98d4e98`**, seventy-two commits. Built-in alignment is complete there;
see "Built-in alignment" below for the retained-layout details. No PR reviews see "Built-in alignment" below for the retained-layout details. No PR reviews
were present when checked on 2026-09-15. were present when checked on 2026-09-15.
@@ -89,6 +89,53 @@ rewrite:
`core/src/ui/holds.rs`, the retained tests, and the generated cold-layout oracle `core/src/ui/holds.rs`, the retained tests, and the generated cold-layout oracle
pin those rules. Seeds 10 and 86 are now in the ordinary generated set. pin those rules. Seeds 10 and 86 are now in the ordinary generated set.
## A warm frame moves a scrolled span, and the rigs that found it
**The defect.** Marking one widget for redraw moves a span inside a scroll by
24px against a cold tree of the same state. Five widgets, in
`tests/cases/unsettled.rs` as
`redrawing_one_widget_does_not_move_what_scrolls_around_it`, **ignored until
it is fixed** so the suite stays honest rather than red:
Scroll(Y) { Span(DOWN) { Scroll(X){ text } as a region node, rect 87x24 } }
`git bisect` names **`95fb4f9`**, which made `Masked` report `Size::LEFTOVER`
rather than its inner's size. `Scroll` clips through a `Masked`, so what the
outer scroll is told its content measures now depends on whether the inner
subtree was redrawn this frame. The reasoning in that commit is sound -- a
widget that clipped its contents cannot honestly ask for more than its box --
so the fix is not to revert it but to stop the outer scroll's content
measurement from going through the clipped report. Not attempted yet.
24px is exactly the sized child's height, so this is a whole child's worth of
layout rather than a rounding.
**The rigs.** `98d4e98` splits `iris::random::grow` into `plan(seed, depth,
&edits)` and `build(rsc, &plan)`. A seed cannot be made smaller, which is why
a failure the oracle found could never be handed to the shrinker; a `Plan`
can, and `tests/scenario/` holds the fifteen cases both rigs now run over the
same trees. So any failing seed reduces directly:
SHRINK_SEED=18 SHRINK_DEPTH=6 SHRINK_CASE=repaint-some \
cargo test --release --test shrink -- --ignored --nocapture
That took seed 18's 277 widgets to 5. The oracle prints the command to reduce
whatever it failed on. Seeds still mean the trees they meant: the 1000-seed
depth-6 run gives the same three failures with the same boxes before and after
the split, which is the check to repeat if the generator is touched again.
**Unreduced leads**, from the shrinker at 400 seeds of depth 5 -- a level it
had never run, since it used to grow its own trees and know five cases:
**seeds 2 and 288 on `region-node`**, and **174 and 175 on `repaint-some`**.
The `repaint-some` pair is probably the defect above. The `region-node` pair
is not obviously the same thing and is the next one to reduce.
**Depth is what finds these.** Nothing fails at 100 seeds of depth 4, which is
all the oracle has ever routinely run. Seeds 18, 190 and 326 fail at depth 6
of 1000. Before fixed point, `5ed9e87` fails that same run on seed 40 after a
resize and on nothing else, so the partial-repaint family is new since then
and the resize one is older than all of it.
## Verification at `394d514` ## Verification at `394d514`
`4febabf` on top of it -- `Fixed` wrapping rather than saturating -- passed `4febabf` on top of it -- `Fixed` wrapping rather than saturating -- passed
@@ -102,11 +149,12 @@ against `394d514`. The measurements are under "Performance".
- `cargo test --workspace --all-features`: 105 passed, 10 ignored - `cargo test --workspace --all-features`: 105 passed, 10 ignored
- The release generated cold-layout oracle passed 100 seeds in 9.4 s, and a - The release generated cold-layout oracle passed 100 seeds in 9.4 s, and a
shrinker case at 300 seeds in 3.5 s: both run a thread per core but one. shrinker case at 300 seeds in 3.5 s: both run a thread per core but one.
- The release shrinker passed **all five** cases -- `resize`, `repaint`, - The release shrinker passed **all five** cases it had then -- `resize`,
`resize-repaint`, `reorder`, `size-change` -- at 300 seeds of depth 5: `repaint`, `resize-repaint`, `reorder`, `size-change` -- at 300 seeds of
26,001 widgets per case, largest tree 331. It passed 1000 seeds of depth 6 depth 5. **That claim does not carry to `98d4e98`**, which runs fifteen
(159,024 widgets per case, largest tree 587) at `5ed9e87`, before fixed cases over the oracle's trees rather than five over its own, and fails at
point; re-run that before quoting it again. 400 seeds of depth 5. Neither does the 1000-seed depth-6 line that used to
sit here: re-run, `5ed9e87` fails it too, on seed 40 after a resize.
- `tabs`, `view`, `minimal`, `text` and `random` render byte-identical at - `tabs`, `view`, `minimal`, `text` and `random` render byte-identical at
1920x1200 across the whole fixed-point sequence, and across this session's 1920x1200 across the whole fixed-point sequence, and across this session's
renames and arithmetic changes on top of it. renames and arithmetic changes on top of it.
@@ -621,9 +669,16 @@ cargo test --release --test generated -- --ignored a_long_run_of_seeds_agrees
`tests/generated.rs` compares a warm incremental tree with a cold tree of the `tests/generated.rs` compares a warm incremental tree with a cold tree of the
same state. `IRIS_GENERATED_SEED`, `IRIS_GENERATED_SEEDS`, and same state. `IRIS_GENERATED_SEED`, `IRIS_GENERATED_SEEDS`, and
`IRIS_GENERATED_DEPTH` select failures. `tests/shrink.rs` reduces a failing `IRIS_GENERATED_DEPTH` select what it covers. `tests/shrink.rs` reduces a
tree; use it to turn a seed into a readable regression rather than leaving the failing tree, over the same fifteen cases and the same trees since `98d4e98`,
seed as the only record. so a seed the oracle fails on goes straight to it -- the failure prints the
command. `SHRINK_SEED`, `SHRINK_SEEDS`, `SHRINK_DEPTH`, and `SHRINK_CASE`
(a case name, or `all`) select what it tries. Turn what it finds into a test
of its own rather than leaving a seed as the record.
The fifteen cases live in `tests/scenario/mod.rs`, which both targets include
by `#[path]`. Adding one there gives it to both rigs at once; a case that only
one of them knows is how the two drifted apart in the first place.
**The float head is checked out at `/home/bob/repos/iris-float-cmp`**, at **The float head is checked out at `/home/bob/repos/iris-float-cmp`**, at
`5ed9e87` with `394d514`'s `Edits::fixed_branches` cherry-applied to `5ed9e87` with `394d514`'s `Edits::fixed_branches` cherry-applied to