The measurement is the part worth keeping: adding an offset to a moved
subtree's stored regions drifts linearly and without bound, so the fraction
path is there for accuracy, not generality. `tests/drift.rs` on the Iris
branch pins it.
Built-in alignment and size moves onto #18 rather than waiting for it, with
ownership agreed -- properties on the `region_node` mechanism, a declared
length winning per axis, and a size rule that carries min/max/clamp so a
clamp is resolved where the box is decided instead of by a widget reading
its own pixels.
Rewrites the opening as state rather than a chronicle of the last few
commits, and gives the parked rule its own section: what the owner asked
for in her words, the half that is written and works with the code in
it, the four ways of asking that were measured and what each did, the
seed that shows it most clearly, and the design question underneath --
which is the same one holding OrthoSize. Also folds the declared-length
rule into the invariants, brings the vocabulary to leftover, says the
suite is eight seconds and must stay that way, and writes out the image
replay rather than pointing at a file in /tmp.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Only rel doubles: apply_rest turns rest into the whole box and px
coincides. Aligned and Scroll honour a hint the same way Span does, so
all three double it. Also corrects the note about a fractional hairline,
which fails because a fraction is a fraction of its own box rather than
through any rounding, and records that a span whose shares run out walks
its children backwards instead of overflowing forward.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The text reference render is not byte-identical after all: a declared
rel or rest length is applied by the span and then again inside SetSize,
so .width(rel(0.5)) draws its child at a quarter. Also replaces the
example that measured one-pixel lines with what the tests now say, since
a span short of room overlaps its fixed lengths rather than collapsing
them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The tabs difference does not reproduce at f61e893 against upstream/main
built in its own worktree, so nothing is waiting on a decision. Records
the instruction counts, frame times and memory taken today rather than
mid-branch, and what a one-pixel line and a one-pixel gap do under the
chain, which is the question the pixel difference was really about.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A fresh session had no way to learn the handoff existed: AGENTS.md named
only docs/PLAN.md, and the filename tied the document to one piece of work.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both gestures, since two widths in turn flatters a store and a drag does
not, and the memory beside the time: the question that decided the shape
of it was whether it is a fixed cost or one per text widget.
Bring LAYOUT.md's §1 and §2 to what shipped. A widget returns its size
rather than recording it, a slot carries a box rather than a
translation, and the per-axis answer is `OnResize` rather than
`is_size_independent` -- and the constraint the position chain replaced
was an agent's, which the text now says.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The random generator grew during the work, so the seed that names a
1061-widget tree in the pre-#16 rows names a 144-widget one now. Every
"still N times the old resize" here was measured across that change and
says nothing; a hand-written fixture that compiles on both revisions
says the old code is 2.2x cheaper and puts a paragraph outside the
output, for two reasons it records as deliberate.
Record what a resize frame is actually spent on -- 63% text, 0.9%
draw_inner -- and what removing the single-entry shaping and placement
caches measures at.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The random tree at depth 7 measured against the two revisions before it: the
GPU pass is a tenth of a millisecond everywhere, and every difference is the
CPU laying out. A repaint of one leaf costs 1313 draws and 6.5 ms where the
pre-#16 code cost one draw, because `redraw` escalates to the top size reader
before knowing whether the size changed at all. Drawing first and escalating
only on a different size takes that to one draw and takes a resize below the
pre-#16 number, but misplaces four widgets in the resize case, so it is the
owner's to call.
Also records the measure-by-drawing multiplier -- 1.3x the drawn widgets at
depth 4, 5.2x at depth 8 -- and that scrolling is now part of the random
trees.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
And the open question beside it: a slot that carries a box rather than a
translation, which would make a move and a stretch of a Scale subtree
one write each. To be measured with chain_cost before it is chosen.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>