diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 80a1409..c70ec38 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -69,7 +69,13 @@ its box is its own declared length or the whole of what its parent had. Minimal repro: `(inner.width(rel(0.5)), rect()).span(Dir::RIGHT)` at 400 wide, asking where `inner` landed. -**Parked, and wanted: a `rest` with nothing left over should not draw.** The +**`rest` is now `leftover`** (`691e3eb`): `Len::leftover(2)`, `Len::LEFTOVER`, +`Size::LEFTOVER`, the field, and `apply_leftover`. The owner renamed it on +2026-09-15 because "rest" reads as "the remainder of the list" as often as "the +remaining space". ai-app's own calls to `rest(..)` will need the same rename +when its submodule pin moves. + +**Parked, and wanted: a `leftover` with nothing left over should not draw.** The owner asked for it on 2026-09-15 -- "if it's 0 wide for rest then it shouldn't draw in the first place", with `rel` and `px` continuing to overflow forward as they do now, and only a length that is *nothing but* `rest` skipped. Written @@ -82,10 +88,25 @@ cold on different answers: the same span holds the same region in both, and `ActiveData::px` says it drew against 63 px warm and 900 cold, so the leftover question is answered in two different boxes. `Painter::undraw` -- drop a child drawn only to measure it, so it is not one of this widget's children this -frame -- is the other half and worked. `Branch` in `iris::random` already makes -a pixel-dependent choice about which child to draw and the fuzzer is happy with -it, so the shape is supported; what is not settled is which box a span should -ask in. +frame -- is the other half and worked. + +Four ways of asking were measured on 2026-09-15 and none of them holds: + +| what the span asks | what happens | +| --- | --- | +| its own box (`px_len`), `Span` keeping `OnResize::Scale` | seeds 8, 10 and 13 diverge: a scaled drawing keeps a leftover answer taken in another box | +| its own box, `Span` saying `Redraw` on its own axis when it holds a `leftover` child | ordinary tests pass, the 100-seed sweep still fails at seed 10, and the `many` load goes from 12.59B to 23.57B instructions | +| the box it was offered, threaded through `draw_inner` so it is the parent's current offer rather than last frame's | four generated cases diverge, worse than asking its own box | +| the box it was offered, with a general rule that a drawing which read its box in pixels cannot be scaled along that axis | two generated cases diverge | + +**The shape of the problem is the one already parked for +`OrthoSize::{Fill, Children}`**: a span's drawing becoming a function of its +own pixel length, when its box can be decided from what it reports. `Branch` +in `iris::random` makes a pixel-dependent choice about *which child to draw* +and the fuzzer is happy with it, so a pixel-dependent draw is not itself the +problem -- what is missing is a way for such an answer to settle when the box +that decided it moves. That is the piece of design to do before this rule, +and it would take `OrthoSize` off the shelf with it. **The `tabs` divergence does not reproduce, so nothing waits on the owner.** Re-measured 2026-09-15 at `f61e893` against `upstream/main` built in its own