# Shared behavior canvas — independent root union review Codex-956atf `/root/canvas_union_review`, 2026-09-11. **No actionable correctness, input-ownership, architecture or source/history regression was found in this bounded source review of the integrated canvas and scenario-parent focus paths.** This is not a build, runtime, visual or release acceptance verdict. ## Scope and identity Root delegated this read-only review against the production union on `codex/behavior-authoring-20260910`, first identified by root as commit `6969c825a8340980b6a419524ade3bb687a6051f`, then frozen at `06ec9621297627a1f7d5c3bc65efb237d1c9923e`. The latter adds two test-only compiler adaptations described below. Commit identities are root-provided; this reviewer did not run Git. The scenario test freeze independently matched SHA256 `950CF4347A3EDEA615B1AC71D9A681C32B446B5109FCFD0F03F3AE2B147360BF`. Read the current AGENTS.md and PROJECT_GOAL.md, the [prior R1/R2/R3 review](release-behavior-canvas-r123-review-20260911.md), the isolated candidate's R1/R2/R3 source handoff, and the relevant actual root implementation and tests. The prior review's resolved counterexamples were checked for integration regressions rather than re-reported. Root owns Gitea coordination, compilation, native acceptance and publication. Only this report was written. The following independently observed raw working-file hashes identify the important union boundaries. Paths are relative to `crates/oa-desktop/src/`. | Path | SHA256 | | --- | --- | | `app.rs` | `AA2E4853B25BB7E185B1DE49EDA42028523C8EBF9599BFE6B7CB2A2B2A688090` | | `behavior.rs` | `5E7CECB54BFCA64E4462F7881F460900ABD925BA2CFE9451CE2B0C78AF4BC850` | | `behavior/scenario.rs` | `FB1DA03E8DF05A59253F7FDF34391E30ABD8AEA427B7D0A12B86B80FF3BF9ECA` | | `behavior/scenario/focus.rs` | `73A9EA10AD7312086081B8688396A21AB4251C9FAECC2DF6D984B702F3963533` | | `behavior/scenario/workspace.rs` | `284F5A7DA09BDC77D70C6788A091D57927150C796FFC10D786793CFF7DA4B7C6` | | `behavior/scenario/workspace/tests.rs` | `950CF4347A3EDEA615B1AC71D9A681C32B446B5109FCFD0F03F3AE2B147360BF` | | `behavior/canvas_workspace/focus.rs` | `CC58CB3838F546150D22FE4DD83A3FFD52504C279FEBAEB8D0B4A6A3B8A73950` | | `behavior/canvas_workspace/tests.rs` | `D84D022574A6F1D69F203D9383502227FB9FC23605C6FB48779CA9F09BEE546D` | | `behavior/topology/layout_tests.rs` | `A990947CB39B2FB15C21DFBC95EE16F92BF6BE749D3872C6904762B9BDE37089` | | `behavior/form_session.rs` | `F5027FB3A5A5599A182E7D1A10DBA56DD66EB1F23A4BA4C4A1744C9A6A5B6E61` | ## Production integration All source locations in this section are under `crates/oa-desktop/src/`. `app.rs:1041` nests the scenario parent owner root outside the canvas owner root, with both outside the actual hosted/reference overlays. Their custom owner types are distinct. Each operation ignores the other's marker, receives its own current marker before visiting focusable children, and independently checks ownership in Collect and Apply. This preserves the parent form guard while allowing the canvas operation to cover the actual nested overlay traversal. A pending scenario form makes `Scope::input_owner` return None (`behavior/canvas_workspace.rs:84`); opening its source child removes `form_mount` (`behavior/scenario.rs:509`); Review removes the parent owner (`app.rs:1495`). No competing current canvas/parent focus owner was found in these paths. `app.rs:1119` retains the exact current canvas Scope admission and narrow presentation whitelist. Only accepted presentation actions normalize the semantic epoch, and resulting control focus uses the post-action lifetime at `app.rs:1177`. The outer parent wrapper neither changes these epochs nor emits another focus operation. The resolved held-pan/toolbar and delayed canvas-task cases therefore retain their production guards after integration. Domain authoring still uses exact scenario context at `app.rs:1619`. Scenario Name uses the session-and-mount-derived dynamic ID (`behavior/scenario/workspace.rs:283`), while the scroll reset wrapper remains keyed only to editing session (`:615`). The sensor uses the mount key and sends that mount in FormShown (`:565`). The handler accepts same-owner geometry epoch changes but checks document, owner, revision, current owner and pending mount (`app.rs:1527`). Back, Use and Escape rearm the parent through `remount_form` (`behavior/scenario.rs:324`, `:696`, `:745`). None of these presentation paths replaces the raw invocation or source draft. The zero-delta axis preservation in `behavior/scenario/focus.rs` remains present. The Details pane now uses the production passive observer with `process = false` (`behavior/scenario/workspace.rs:595`). Its actual translation enters scenario Page scroll state, and a caller restore receives and consumes the matching token through `behavior.rs:114` and `behavior/scenario.rs:460`. `restore_caller` marks only Page pending (`behavior/scenario.rs:425`), consistent with the viewport using camera pan instead of a Scrollable. The reviewed source contains no new semantic command or source mutation in these observer/focus paths. The boxed workflow convention is retained (`workflow.rs:22`, `:45`), including `review_event.as_ref()` in `app/reference_authoring.rs:218`. Reference chooser availability excludes pending behavior forms (`app/reference_authoring.rs:72`), so its separate canvas guard does not create an uncovered simultaneous parent-form/chooser owner in the reviewed production path. ## Mounted evaluator and nontrivial assertions Independently inspected the installed Iced sources under `.local/toolchain/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/`: - `iced_winit-0.14.0/src/lib.rs:1214` drains App updates, rebuilds the resulting UI, then executes actions; `:1300` collects immediately ready task actions for the whole message batch and retains pending streams; `:1742` executes chained widget passes synchronously. - `iced_runtime-0.14.0/src/user_interface.rs:539` operates both the real root and nested overlays. - `iced_widget-0.14.2/src/scrollable.rs:540` reports the scroll translation before traversing unshifted child layout, matching the parent's translated bounds observer and reveal calculation. `sensor.rs:198` rearms on key change and emits on the subsequent redraw, including unchanged bounds. `iced_core-0.14.0/src/widget/id.rs` supports the dynamic `Id::from(String)` used by the union. The shared Mounted helper uses those actual UserInterface and Cache APIs, drains a complete input message batch before tasks, builds the final App view for ready actions, and executes Chain passes against that same UI (`behavior/canvas_workspace/tests.rs:140`, `:184`). Output messages form the next update cycle; pending streams are retained until completion. Unexpected native actions panic and unavailable renderer initialization fails. This is the relevant single-window widget/App ordering, not a replica of subscriptions, OS focus, native dialogs or arbitrary asynchronous scheduling. The reconciled parent tests preserve useful falsifiers: - `scenario/workspace/tests.rs:412` first focuses another real field, establishes actual parent overflow, performs the accepted task, and requires the exact Name to be the sole focus and fully visible. Mismatched mounts, revisions, owners and modal admission are separately rejected. - `:794` obtains the real sensor task and first consumes initial focus before entering the actual child. Back, Use and Escape must retain session/raw identity, create a different mount, emit a new sensor task, and focus the parent again. A repeated FormShown must produce no task. - `:864` retains an actual widget Action before replacement, child, Review and context transitions; it observes the resulting tree and requires the saved Collect to remain inert. `:935` similarly retains Apply across Review. This intentionally stronger retained-Apply invariant does not claim native Chain passes interleave. - `:958` is explicitly a small synthetic missing-target test; it is not presented as a production-root modal test. The preceding production-root cases supply that coverage. - `:1654` requests 700 pixels on the real Action form and requires the measured offset to exceed 64, preserves it while editing, then performs Cancel/Start with no intervening closed view. It checks zero offset before a redraw could rescue it through a new Name-focus task. Action and Observation share the same relevant field structure (`scenario/workspace.rs:280`, `:315`, `:476`), so replacement is not simply a switch to an empty form. Camera, raw invocation, recovery, source snapshot and history assertions remain. - `:1773` tests same-bounds owner/document remeasurement with the same Mounted cache. `:1820` builds legitimate Details rows, requires the actual offset to be exactly 80, navigates through preselection and caller return, then requires the offset/camera restoration, consumed receipt, and subsequent pan movement. Source and revision comparisons surround navigation; existing rename history is acknowledged instead of asserting an empty history. The shared chooser/Review case continues to use actual nested search and Review fields (`behavior/topology/layout_tests.rs:568`). The two compiler adaptations in `06ec962` are consistent with installed APIs: explicit `Headless::screenshot` selects the trait's physical-size/scale overload (`behavior/canvas_workspace/tests.rs:268`), and the Review fixture calls the existing boxed event constructor (`behavior/topology/layout_tests.rs:726`). Neither changes evaluator ordering or production behavior. ## Acceptance limits No compiler, test, renderer, native GUI, Git/index, network, Linux/WSL or VPN action was performed by this reviewer. Root reported the initial two test API errors and the committed adaptations; the corrected compiler run was still underway when this report was prepared. There is no executed pass claim here, and earlier reports establish different bytes. Root still needs the appropriate exact-union build/test and native acceptance evidence. In particular, operation geometry and prepared pixel assertions do not establish native focus/accessibility, clipping of transformed scene text, all modal geometry or minimum-window usability. The separately owned B4 renderer work and broader phase 1/issue 2/PROJECT_GOAL acceptance are not certified by this bounded integration review. No new blocking source finding is left for this reviewer to hand back.