Record what making the frame a window length corrected
Step 2 of the layout plan is done in the experiment checkout, at 1512d84 and 23523ee. The handoff carries the commits and what is left; LAYOUT.md carries the settled rule, which is now one coordinate unit with the frame a length of it and both pins beside each other; the log carries what implementing the plan corrected in it, including the four that would have shipped as wrong layout and the two rig gaps that hid them.
This commit is contained in:
1 parent
da1807664a
commit
36ce66554b
3 files changed
+196
-146
No files matched your search
@@ -7,6 +7,100 @@ must outlive it (settled design, the measurement method) is already in
|
||||
`docs/LAYOUT.md`, and the current plan is in `docs/HANDOFF.md`. Commit ids
|
||||
are in `/home/bob/repos/iris-layout-experiment` unless said otherwise.
|
||||
|
||||
## What making the frame a length found (worker, 2026-09-19)
|
||||
|
||||
Step 2 of the handoff, implemented over `0ef87eb` in
|
||||
`/home/bob/repos/iris-layout-experiment`. Six of these are corrections to the
|
||||
plan, not to the code that implemented it, so they are worth keeping even
|
||||
after the step lands.
|
||||
|
||||
- **A narrowed frame is a window length, not a fraction of the parent's
|
||||
frame.** The plan said both at once: `Pad` narrowing by `rel 1 - 32px` (a
|
||||
fraction) and `Span` narrowing by `slot.len()` (a window length). The first
|
||||
implementation resolved every `narrow` against the parent frame, which took
|
||||
padding off twice for anything inside a padded row -- a `leftover(1)` slot
|
||||
of a 900 px row inside `pad(16)` gave its child a frame of 418 where the
|
||||
slot is 434. A slot *cannot* be written as a fraction of the row's frame:
|
||||
that is a division of two lengths, the same argument that forced region
|
||||
node entries to be translations. So `narrow` is a window length, `Pad` reads
|
||||
its own frame with the new `Painter::frame_len` and takes the pixels off,
|
||||
and nothing resolves a narrow a second time. Pinned by
|
||||
`layout::a_share_inside_padding_fills_the_slot_it_was_given`.
|
||||
- **The root resolved its own rule twice**, because `root_layout` passed the
|
||||
declaration as both the narrow and the declaration: a root of `rel(0.5)` in
|
||||
a 900 px window came out 225 wide. Pinned by
|
||||
`layout::a_root_with_a_fraction_rule_is_that_fraction_of_the_window`.
|
||||
- **Which box arm `in_parent` takes is decided by the box, not the frame.**
|
||||
The first implementation treated any decided frame -- a narrow, a share, a
|
||||
declaration -- as a box this widget chose, so a `Pad` (which narrows) lost
|
||||
its child's box pin, and a rule changed over two zero pads relocated the
|
||||
column under them instead of dividing it again (seed 59, depth 5,
|
||||
`resize-size`). Only a declaration places the box inside the part it was
|
||||
given; a narrowed frame leaves the box exactly the part. Pinned by
|
||||
`unsettled::changing_a_rule_over_two_pads_divides_the_column_again`.
|
||||
- **Frame validity is a pin, not a range.** A range of window pixels cannot
|
||||
say "this answer is a fraction of *that* frame": two frames are different
|
||||
lengths at the same window size. `LayoutHolds` therefore carries
|
||||
`frame_len` beside `extent_len`, set where a widget reads its frame
|
||||
(`frame_len`, which `Pad` does) and where a rule that is a fraction of the
|
||||
frame is answered with it, and composed up where a length of this frame is
|
||||
what reached the child. It replaced a `holds_for_frame` helper that
|
||||
compared expressions and asked `Holds::ANY` whether anything depended on
|
||||
them, which missed the rule-answered case entirely. **No test in the repo
|
||||
distinguishes the rule-answered half**: 400 seeds over sixteen cases at
|
||||
depth 5 agree with it and without it, and hand-built trees for the shape
|
||||
the seed-30 records showed (a stale `1 rel` answer beside a stack's sizing
|
||||
child) do not reproduce it either, because a frame that changes almost
|
||||
always changes a box as well and the box pins catch it. Kept anyway,
|
||||
because "these two invalidations always coincide" is the kind of unstated
|
||||
assumption the three earlier plans died of; it is one line at each of two
|
||||
sites if it is ever shown to be dead.
|
||||
- **`Scroll` resolved its content length against its own box.** With one unit
|
||||
its child's answer is a window length, so it becomes pixels against the
|
||||
window; the two differ wherever a scroll's box is not its frame. Fixing it
|
||||
then broke `resize`, because resolving a length against the window is a
|
||||
*read of the window* and nothing recorded it: a viewport 40 px tall inside
|
||||
a branch's box does not change when the window does, so an end-snapped
|
||||
scroll kept the offset it had (seed 942, depth 6). `Painter::to_px` takes
|
||||
the read where the resolution happens and pins the window only where the
|
||||
length has a fraction in it; `window_px_len`, which returned the number
|
||||
and recorded nothing, is gone. Pinned as
|
||||
`unsettled::resizing_under_a_short_scroll_snaps_its_window_tall_content_again`.
|
||||
- **A local redraw resolves its own frame** from its record's narrow and
|
||||
declaration (`ask_again`, shared with `place_in`) rather than reusing the
|
||||
retained frame. That deleted `asked_px` and the assert that the two agree:
|
||||
they legitimately disagree when an ancestor's frame changed and the
|
||||
ancestor was reused because nothing under it pinned the frame, and the
|
||||
freshly resolved one is the right one.
|
||||
- **The clipping debug assert compared the reported size with the frame**
|
||||
rather than with the box it is a claim about.
|
||||
|
||||
Two rig changes came out of it, both kept:
|
||||
|
||||
- The shrinker prints the *shrunk* tree's divergence rather than the grown
|
||||
tree's, and the divergence now lists, for the failing widget and every
|
||||
ancestor, warm and cold `frame`, `ask`, `box` and `size`. Reading that
|
||||
table is what found the box-arm defect; reconstructing a 20-widget plan by
|
||||
hand would not have.
|
||||
- A `size-resize` case: a size change and *then* a resize. Every other case
|
||||
changes something and compares at once or resizes first, so an answer kept
|
||||
as a fraction of the wrong length agreed at the window it was made at and
|
||||
parted from cold at every other one.
|
||||
|
||||
Checks at the end of the step (`23523ee`): `cargo fmt --all --check`, clippy
|
||||
with and without `layout-diagnostics`, 122 suite tests, 20 core, 11
|
||||
generated, the 400-seed depth-5 shrinker over all sixteen cases, the
|
||||
1000-seed depth-6 oracle, and the 2000-seed depth-4 scan over all sixteen
|
||||
cases.
|
||||
|
||||
One thing is unexplained and worth knowing about: seed 30 at depth 5
|
||||
(`shuffle-all-but-first`) failed once, with a span keeping an answer of
|
||||
`1 rel` for an axis whose frame had become `78 px`, and then stopped failing
|
||||
before the pin was added -- reverting each part of the change since that run
|
||||
did not bring it back. Either an edit fixed it that I could not identify, or
|
||||
the rig is not as deterministic as it looks. If a seed ever fails once and
|
||||
not again, suspect the second.
|
||||
|
||||
## What the one-ask protocol found (planner, 2026-09-18, third session)
|
||||
|
||||
Branch `wip/one-ask` at `3091fb8` over `4328eac`. The change is described in
|
||||
@@ -404,6 +498,12 @@ is the padded share and fits. The clipped render records the current bug.
|
||||
was checked this way and is new under the pin experiment).
|
||||
- Depth finds things and so does breadth; widen one axis at a time and
|
||||
record which.
|
||||
- The cases are what a change is *then* compared at, and until 2026-09-19
|
||||
every one of them compared at the window the change was made in. A
|
||||
`size-resize` case was added because a length kept as a fraction of the
|
||||
wrong box agrees with cold at that window and parts from it at every other
|
||||
one. There is still no case that changes a tree twice with a resize
|
||||
between, and no case that resizes twice.
|
||||
|
||||
## Smaller open items (carried from the old handoff)
|
||||
|
||||
|
||||
Reference in new issue
Block a user