diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 5ec4cc2..298d066 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -14,18 +14,23 @@ detached comparison checkout is `/home/bob/repos/iris-layout-baseline`. It is the reviewed baseline this work must preserve or improve. The continuation is `/home/bob/repos/iris-layout-experiment`, now on branch -**`wip/one-ask`** at **`3091fb8`**, one commit over `4328eac` (the head of +**`wip/one-ask`** at **`0ef87eb`**, two commits over `4328eac` (the head of `wip/transparent-frames`, which is unchanged). It replaces the step 3 plan -below with a smaller protocol change, and it passes every fast check: +below with a smaller protocol change, and it passes every check that has +finished: -| check at `3091fb8` | result | +| check at `0ef87eb` | result | | --- | --- | | `cargo fmt --all --check`, clippy `-D warnings`, with and without `layout-diagnostics` | clean | -| `cargo test --workspace` (debug) | 114 suite, 20 core, 11 generated, all green | -| the two decided-box pins from step 1 | **pass** (red at `4328eac`) | +| `cargo test --workspace` (debug) | 115 suite, 20 core, 11 generated, all green | +| the two decided-box pins from step 1, and the new seed 946 pin | **pass** (the first two were red at `4328eac`) | | `cargo test --release --test generated` | 11/11 | | shrinker, 400 seeds, depth 5, all fifteen cases | agree, 56 s | -| 1000 seeds at depth 6, and the 2000-seed depth-4 scan | see `docs/LAYOUT_LOG.md`; they were running when this was written | +| 2000-seed depth-4 scan, all fifteen cases | agreed at `3091fb8` (269 s); rerun at `0ef87eb` was running when this was written | +| 1000 seeds at depth 6 | found seed 946 at `3091fb8`, fixed and pinned in `0ef87eb`; rerun was running when this was written | + +Read `/tmp/oracle-1000-6b.log` and `/tmp/shrink-2000-4b.log` for the reruns +if they still exist; otherwise run them (step 1). The worker's uncommitted step 3/4 experiment is preserved as branch `wip/step3-experiment` (one commit over `4328eac`) and as @@ -156,6 +161,15 @@ back at the retained place of the box the parent's answer *chose*. Both halves are needed: seed 2 at depth 4 (a stack sized by its text) fails without the second. +A widget its parent asked more than once in one draw -- a share child, asked +in the room and then in its slot -- has two questions and one record, so it +cannot settle locally: `redraw` defers it to the parent the way it defers a +widget whose declared length changed (`ActiveData::re_asked`, set by +`widget_at` when the child is already in `children`). Seed 946 at depth 6 +found the case: a fixed-height column that is a share while its rect fits +and a fixed width once it does not, so emptying it changes the room answer +and not the slot answer. + A symbolic length a child pinned now composes through `Part::Of` where the part is the whole box less pixels, and pins the parent's own length otherwise (`in_parent`). Dropping it let a zero `Pad` reuse a drawing across a narrowed @@ -267,18 +281,18 @@ the probe's diff readable; do this as one mechanical commit. Suite, oracle. Work counters at `3091fb8`, seed 1 and 13, depth 8, widget draws / distinct widgets, beside `e44dea3` (#18) and `49cec82` (the branch head before this): -| seed 1 | e44dea3 | 49cec82 | 3091fb8 | +| seed 1 | e44dea3 | 49cec82 | 0ef87eb | | --- | --- | --- | --- | | cold | 369/261 | 516/288 | 331/288 | -| many | 157/95 | 187/119 | 78/78 | +| many | 157/95 | 187/119 | 110/92 | | size | 16/12 | 3/3 | 3/3 | | scroll | 2 | 1 | 1 | | resize | 13/13 | 24/76 | 40/15 | -| seed 13 | e44dea3 | 49cec82 | 3091fb8 | +| seed 13 | e44dea3 | 49cec82 | 0ef87eb | | --- | --- | --- | --- | | cold | 1330/707 | 2940/982 | 1179/982 | -| many | 524/159 | 1091/423 | 335/333 | +| many | 524/159 | 1091/423 | 424/364 | | resize | nothing | 2215/510 | nothing | `many` and `size` are better than #18 at seed 1 and `many` draws fewer times @@ -287,13 +301,17 @@ at seed 1 draws 40 times where #18 drew 13. Two mechanisms, both understood: - **A share child is asked twice per span draw** -- in the measuring room with the frame forwarded, then in its slot with the frame narrowed. Each - ask that reads pixels or pins a length draws. Give `Span` a measure-only - ask for the first pass: reuse the retained *answer* when its holds contain - the room, without validating or relocating the drawing, and let the - placing ask settle the drawing. The answer contract must then carry no - symbolic pin (a span's total does not depend on `far`; only its slots do), - which is the separation the worker's experiment made with - `answer_extent_len`. Measure `many` at seed 13 before and after. + ask that reads pixels or pins a length draws, and since `0ef87eb` every + local change inside a share child redraws its span as well. Give `Span` a + measure-only ask for the first pass: reuse the retained *answer* when its + holds contain the room, without validating or relocating the drawing, and + let the placing ask settle the drawing. The answer contract must then + carry no symbolic pin (a span's total does not depend on `far`; only its + slots do), which is the separation the worker's experiment made with + `answer_extent_len`. With that, a twice-asked child could keep both + answers and settle locally by re-asking both questions instead of + deferring. Measure `many` at seed 13 before and after; the seed 946 pin + must stay green throughout. - **A positive-direction span with no shares pins `far`** it does not need, so a resize redraws it. Read `extent_len` only where a slot depends on it (shares, or `Sign::Neg`), and express the measuring room's far end without diff --git a/docs/LAYOUT_LOG.md b/docs/LAYOUT_LOG.md index d65612c..fa6d16f 100644 --- a/docs/LAYOUT_LOG.md +++ b/docs/LAYOUT_LOG.md @@ -54,10 +54,26 @@ Branch `wip/one-ask` at `3091fb8` over `4328eac`. The change is described in a share child is asked twice per span draw, and `resize` at seed 1 draws 40 because positive-direction spans without shares pin `far`; both are step 4 there. -- The 1000-seed depth-6 oracle and the 2000-seed depth-4 scan were started - at `3091fb8` and had not finished when this was written; the next session - reads `/tmp/oracle-1000-6.log` and `/tmp/shrink-2000-4.log` if they still - exist, or reruns them. +- At `3091fb8` the 2000-seed depth-4 scan agreed over all fifteen cases + (82,203 widgets, 269 s) and the 1000-seed depth-6 oracle found **seed 946, + `shuffle-all-but-first`**, which shrinks to nine widgets: `Span{LEFT}[Rect, + Span{RIGHT}[Rect, Span{DOWN}[Wrapped, Rect, Wrapped].height(159), Rect]]`, + the column emptied to its first text. Reproduced with the records + printed: the column reports a share along the row while its rect has room + (both texts wrap at the whole row, 35 px each, under 159) and a fixed + width once asked in its third of the row (each text 88 px, no room, rect + undrawn, cross-axis answer a pixel width). So the row asked it twice and + built its slots on the first answer and its cross size on the second. + Emptying the column changes only the first; the local redraw re-asked the + second, found it unchanged, and told nobody. Cold has the column 874 px + wide. Fixed in `0ef87eb` by deferring any widget its parent asked twice + in one draw to that parent, pinned as + `unsettled::emptying_a_column_the_row_asked_twice_asks_the_row_again` + (checked red without the deferral, green with it). Cost: `many` at depth + 8 went from 78/78 to 110/92 draws/distinct at seed 1 and from 335/333 to + 424/364 at seed 13; still under #18's 157/95 and 524/159 draws. The + reruns of both long fuzzers at `0ef87eb` were running when this was + written (`/tmp/oracle-1000-6b.log`, `/tmp/shrink-2000-4b.log`). ## What the step 3 plan got wrong (planner, 2026-09-18, third session) @@ -251,24 +267,25 @@ at depth 8; draw counts are deterministic so these are single runs. `e44dea3` is #18's head, `34cafb6` the commit the branch starts from, `49cec82` its head. -| seed 1 | e44dea3 | 34cafb6 | 49cec82 | 3091fb8 | -| --- | --- | --- | --- | --- | -| cold | 369/261/10.6 | 463/274/13.3 | 516/288/12.0 | 331/288/12.3 | -| repaint | 1 | 1 | 1 | 1 | -| many | 157/95/0.33 | 263/108/0.59 | 187/119/0.52 | 78/78/0.13 | -| size | 16/12/0.018 | 3/3 | 3/3/0.010 | 3/3/0.008 | -| scroll | 2/0.002 | 1 | 1/0.004 | 1/0.001 | -| resize | 13/13/0.019 | 22/15/0.032 | 24/76/0.090 | 40/15/0.096 | +| seed 1 | e44dea3 | 34cafb6 | 49cec82 | 3091fb8 | 0ef87eb | +| --- | --- | --- | --- | --- | --- | +| cold | 369/261/10.6 | 463/274/13.3 | 516/288/12.0 | 331/288/12.3 | 331/288/12.0 | +| repaint | 1 | 1 | 1 | 1 | 1 | +| many | 157/95/0.33 | 263/108/0.59 | 187/119/0.52 | 78/78/0.13 | 110/92/0.23 | +| size | 16/12/0.018 | 3/3 | 3/3/0.010 | 3/3/0.008 | 3/3/0.008 | +| scroll | 2/0.002 | 1 | 1/0.004 | 1/0.001 | 1/0.001 | +| resize | 13/13/0.019 | 22/15/0.032 | 24/76/0.090 | 40/15/0.096 | 40/15/0.096 | -| seed 13 | e44dea3 | 49cec82 | 3091fb8 | -| --- | --- | --- | --- | -| cold | 1330/707/20.3 | 2940/982/28.3 | 1179/982/24.6 | -| many | 524/159/1.09 | 1091/423/2.39 | 335/333/0.62 | -| resize | nothing drawn | 2215/510/6.56 | nothing drawn | +| seed 13 | e44dea3 | 49cec82 | 3091fb8 | 0ef87eb | +| --- | --- | --- | --- | --- | +| cold | 1330/707/20.3 | 2940/982/28.3 | 1179/982/24.6 | 1179/982/24.6 | +| many | 524/159/1.09 | 1091/423/2.39 | 335/333/0.62 | 424/364/0.87 | +| resize | nothing drawn | 2215/510/6.56 | nothing drawn | nothing drawn | -The `3091fb8` column is single runs from the third session; its `cold` and +The last two columns are single runs from the third session; `cold` and `resize` at seed 1 are after the `Part::Of` pin composition, which added -18 and 19 draws respectively over the version without it. +18 and 19 draws respectively over the version without it, and `many` at +`0ef87eb` includes the deferral of twice-asked share children. Three findings, each applied on the branch: