2.5 KiB
Independent scenario workspace review — 2026-09-10
Codex-9e8r6t /root/palette_finish. Reviewed commit
3978bbe23c3d50563ad87fea5552de3d52f39d6b against its parent, the new tests,
App context/modal gates, existing scroll observer and actual cached
iced_widget-0.14.2/src/sensor.rs. No source edits, Cargo or native input.
Actionable finding: viewport observation loses owner identity
P2 — Fit overview can stop working after same-size scenario navigation.
Affected code: crates/oa-desktop/src/behavior/scenario.rs, State::enter,
and crates/oa-desktop/src/behavior/scenario/workspace.rs, canvas_pane.
Reproduction condition: mount scenario A and obtain its viewport measurement;
navigate to scenario B at the same canvas viewport size, without opening a
shelf or changing focus/header height; then choose Fit overview on a scene
larger than that viewport. enter resets presentation to defaults for B,
including viewport = None. The Sensor wraps the identity-resetting scroll
observer but has its own stable outer widget state and default unit key.
Iced's Sensor retains has_popped_in and last_size through diff; unchanged
size and key produce neither on_show nor on_resize. B therefore never receives
the current measurement. Its fit scale falls back to 1.0 until another action
changes the canvas dimensions. The same identity-lifetime issue can preserve a
historical caller viewport on Back after resizing in a callee.
The existing mounted A-to-B tests verify actual scroll reset/restoration and manual camera values, but do not assert B obtains a measured viewport at an unchanged allocation. Pure Presentation tests manually provide that measurement and therefore cannot expose this failure.
Requested fix: key the Sensor by (context.document, context.scenario) or
otherwise re-observe its current size at that identity boundary, while preserving
the existing child scroll restoration contract. Add a mounted same-size A-to-B
regression that proves B gets a measurement and Fit produces a scale below one
without a resize. The author acknowledged the finding and is implementing this
fix and regression under their lease. No executed fix result is claimed here.
No second actionable counterexample was established in this bounded review of stale pointer epochs, passive scroll/viewport guards, invalid Back normalization, raw pending forms, stable disclosure/focus slots or scale/hit-coordinate paths. This does not replace root's immutable full-suite run or native acceptance.