Refresh scenario viewport measurement when its identity changes

This commit is contained in:
2026-09-11 01:21:24 -07:00
parent 3978bbe23c
commit d114a271c5
4 changed files with 138 additions and 5 deletions
+12 -1
View File
@@ -43,4 +43,15 @@ After root integrated the upstream explicit-enum F1 seed repair as `81668f9`, th
Root received an immutable **631-test** executable in `.local/scenario-workspace-20260910/tests-81668f9/arcadia-studio-tests.exe`, 104,007,680 bytes, SHA256 `FF5999466032E4FBDD615969E349720EC6B29A5945F7E3A57CCF976D8A2736E7`. The sibling `libunwind.dll` is 190,976 bytes, SHA256 `F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4`. `manifest.json` records the source HEAD and 252 working-tree input hashes (including clearly marked present but undeclared creation modules), SHA256 `D06C72EBBE9B39A7CE2CCCFF888D2DE7892DFD07EA166FC308155642D37708EE`. Root owns the full run of this immutable artifact while this worker builds the GUI and performs fmt/strict Clippy under the coordinated source freeze.
Scoped rustfmt and diff checks pass. No current GUI binary or native acceptance is claimed at this checkpoint. Root's earlier immutable artifact had 615 passes and three failures; all three failing cases now pass the focused current gates above.
The GUI build passed in **4m17s** (`gui-build.log` and `gui-build-status.json`). Before final handoff, palette_finish's independent review found a real missing case: `State::enter` clears measured viewport on owner/document changes, while an unkeyed Iced Sensor retains its last size and does not re-emit when the new workspace is the same size. Root staged this build only as a known-defect native candidate, not scenario acceptance.
The correction keys the actual canvas Sensor by `(document, scenario)`. A new mounted regression opens a different owner with exactly the same pane dimensions, then replaces the document while retaining the owner UUID and dimensions; both must re-observe the viewport and make Fit work immediately. Existing scrollable/observer identity and camera restoration remain unchanged. The corrected complete scenario filter passed **53/53**, 579 filtered (**632 total**), in 30.90s after a 2m17s compile. It includes eleven workspace tests. Evidence: `scenario-sensor-tests.log` and matching status JSON.
Scoped rustfmt and diff checks pass. After this gate, root explicitly transferred shared App/behavior/checkpoints integration and the sole Cargo writer lease to the creation worker. Exact shared boundaries were handed over; this worker has stopped Rust edits. Root owns the sensor correction commit and final combined GUI/fmt/strict Clippy after the creation focused gate. The corrected/combined GUI and native acceptance remain pending. Root's earlier immutable artifact had 615 passes and three failures; all three failing cases now pass the focused current gates above. The full 631-test run belongs to root and must not be duplicated.
## Native handoff and remaining limits
- At 1100×700 and 1440×900, open a scenario, insert at a visible root/ALT position, scroll a long message/value form and reach the pinned Create/Cancel actions. Verify canvas rows remain usable while the form is open; Focus and shelves must retain raw input and canvas position.
- Use Fit after switching to another scenario with unchanged window/pane size, and after opening another document. It must act immediately, with no resize workaround. Manual scale must survive form disclosure and resize; returning to a caller must recover its tool, scale, shelf, focus and actual scroll offsets.
- Create remains one existing validated command batch; Save/Undo/Redo/reopen and exact source/ordered-occurrence identity remain the semantic acceptance oracle. This layout slice introduces no new domain/schema/REST contract, local owner/source creation, reuse semantics or lifecycle inference.
- Test rendering uses actual Iced layout/Scrollable operations with a null renderer and explicit header-height cases; root must verify real font wrapping, hit targets and readability. The first GUI candidate intentionally predates the Sensor correction and cannot establish corrected Fit acceptance.
@@ -0,0 +1,42 @@
# 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.