86 lines
15 KiB
Markdown
86 lines
15 KiB
Markdown
# Scenario parent-focus correction — independent source review
|
||
|
||
Codex-956atf `/root/focus_review`, 2026-09-11. **No unresolved material source finding in the bounded I1/I2 correction. Runtime acceptance remains pending.** This reviews the working patch over HEAD `8d55d2d2eb05aed826b96a917cf776e1d8c3b690`, frozen with author `scenario_focus_fix`, including the final test-only strengthening below. The [pre-reboot integration review](release-chooser-contextual-integration-review-20260911.md) remains unchanged history. See the [implementation handoff](release-scenario-focus-fix-20260911.md).
|
||
|
||
Read AGENTS, current Gitea issue 1 coordination, empty open PR inventory, BehaviorAuthoring20260911 and ContextualSourceDrafts20260911 Wiki pages. Review ownership was posted at [issue 1/comment 302](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/1#issuecomment-302). Only this new report was written. No production edits, Cargo, rustc, rustfmt, tests, renderer creation, native UI, install or commit occurred. `git diff --check` passed for tracked working changes; it is not compilation or runtime evidence.
|
||
|
||
## Findings and resolution
|
||
|
||
**I1, previous P2 — correction supported by source.** `scenario.rs:317`, `:490`, `:669` and `:710` now request a fresh parent mount on successful Escape/Back/Use return. This changes only `form_mount` and `form_focus_pending`; `form_session` remains stable. Source staging and its existing admission/validation are retained. In `workspace.rs:362` the Name ID includes the current stamp; at `:642` the parent-only sensor is keyed by mount, while `editor_panel` remains keyed by editing session. The child still replaces the parent branch. An ordinary parent whose initial focus has already been consumed can therefore publish a fresh FormShown after the child returns. Raw semantic identities are not rotated to obtain focus.
|
||
|
||
**I2, previous P2 — correction supported by source.** `App::view` (`app.rs:1029`) wraps the final reference/hosted content with the scenario owner marker. `scenario_focus_owner` (`:1387`) computes the live document/scenario/revision/session/mount stamp and excludes busy, hosted, workflow, architecture, model-menu, file-prompt, deletion and pending-confirmation ownership. The marker is published from the current view on every operation traversal, rather than retained widget state. FormShown checks the context and consumes the exact mount before constructing the guarded task (`:1410`). Geometry epoch is deliberately absent from the stamp, so a same-mount viewport notification does not invalidate first focus.
|
||
|
||
`focus.rs:84–119` collects without changing any focusable or scrollable. A mismatched owner or missing exact Name target ends with `Outcome::None`. Only a valid target yields Apply, initially invalid; Apply rechecks the current root owner before changing focus or scroll (`:129–145`). Thus a saved S1 action operated after replacement, child opening, same-session remount, document/owner/revision change or modal ownership change cannot act on S2 or clear another field. The scoped Name ID also prevents the former global-ID collision.
|
||
|
||
**R1, P2 test weakness — corrected during review, execution pending.** The initial reveal test scrolled to 1000 and asserted only a final offset at most 64. Without proving actual overflow, that sequence could pass with a broken reveal. Author changed the production viewport to 1100×700, requires measured pre-focus offset greater than 64, and measures the Name's effective bounds inside the actual form viewport afterward (`workspace/tests.rs:217`). Existing raw/history assertions remain. No claim is made that this stronger fixture has passed; missing overflow will now fail explicitly. Author also added a direct chained-Apply owner-change falsifier (`:602`) after review feedback.
|
||
|
||
## Prepared regression scope
|
||
|
||
Five `scenario_form_focus_*` tests are present in `workspace/tests.rs`; four use the production headless renderer and actual `App::view`. Backend creation uses `expect`, with no absent-renderer/GPU skip. Tests remain under the existing debug-test module gate.
|
||
|
||
- The current-focus test retains stale-dispatch, repeated-dispatch, busy/hosted, epoch-only-change, raw snapshot, accepted-Project pointer and history assertions; it now executes the operation chain on the mounted production view and checks real reveal geometry.
|
||
- The return test (`:507`) first runs and consumes ordinary initial focus, mounts and focuses the actual source Name, then uses Back, valid Use and Escape independently. It checks stable session, changed mount, retained raw name/invocation/owner/slot/source-origin fields, focused parent, unchanged accepted Project/source bundle/history, and an unchanged returned recovery snapshot after focus. Use intentionally stages its source; the focus step must preserve that resulting snapshot.
|
||
- The saved-action matrix (`:553`) extracts S1's actual Widget action before eight live-state changes: replacement session, open source child, real Review candidate modal, document token, document revision, owner, same-session source-return mount, and hosted visibility. It operates on the rebuilt current `App::view`, preserving the focused child/Review or other actual input, source bundle, recovery state and Undo/Redo availability. This exercises delayed execution, not merely rejection of stale FormShown messages.
|
||
- The chained-Apply test (`:602`) successfully collects on the current parent, saves its Chain result, mounts/focuses a real Review candidate, and applies the saved operation there. It requires unchanged focus, recovery/source and history.
|
||
- Missing exact target (`:626`) deliberately uses a small generic marker/input tree with a valid stamp and an unrelated focused input. This is a narrow missing-target test, not claimed to mount the entire App.
|
||
|
||
`focus_action` extracts the first Widget action without waiting for task-stream completion while that action retains the channel. The execution helper follows `Outcome::Chain`. This matches the relevant synchronous chain behavior in the locally read Iced 0.14 runtime; no event-loop execution is claimed.
|
||
|
||
## Scroll, chooser and integration boundaries
|
||
|
||
Compared `behavior/scenario/focus.rs` with `forms/reference_chooser/trigger/focus.rs`. Both translate bounds by accumulated ancestor offsets, restore traversal state when leaving ancestors, calculate reveal from inner to outer scrollables, clamp shifts to content capacity, and apply shifts by traversal index. Local Iced `Scrollable::operate` reports its translation before traversing content, matching that calculation. Scenario Apply focuses the exact stamped Name; chooser focus has separate form scope/relative navigation/modal policy. Their root marker types are distinct. No concrete sign, ancestor-scope or retained-child conflict was found in this readback; native pixels and broader nested-scroll behavior remain execution work.
|
||
|
||
The production test helper calls `App::view`'s widget operation traversal. It does not invoke Iced UserInterface's additional overlay traversal. `reference_chooser::Popup::operate` (`widget.rs:252`) traverses its content, while its separate search input belongs to the overlay operation (`:484`). This report does **not** claim generic content traversal reaches that separate input. Existing child-open focus tasks and other focus systems were not redesigned or exhaustively audited.
|
||
|
||
Root owns scoped formatting, compilation, all five focus gates, related workspace/chooser/contextual-source tests, broader checks, matching GUI and native acceptance. Canvas integration must preserve the outer live owner marker, stamped Name, parent-only mount sensor and session/mount distinction. Root/author should link this review from their shared Wiki evidence; source review alone does not close the release or replace the frozen pre-reboot report.
|
||
|
||
## Reviewed byte fingerprints
|
||
|
||
SHA-256, actual pre-format freeze. Paths are relative to `crates/oa-desktop/src`. Formatting or further changes require fresh gate provenance.
|
||
|
||
| File | SHA-256 |
|
||
| --- | --- |
|
||
| `app.rs` | `4B700DBC6F8C0E8258B0F409C0B8F28266838F66ADAEABBEACE6B37E6DCAF736` |
|
||
| `behavior/scenario.rs` | `6E26E0EDD44D11D473B67E9DFE634185D77AE080E26776E9F55230D587ABA083` |
|
||
| `behavior/scenario/workspace.rs` | `D58CD2EA3F4603801BBD268906141076C5F70A83FB87A102B19A8806B083DEAE` |
|
||
| `behavior/scenario/focus.rs` | `48E1F227527E66CF0B56D75B23E05A1F4F89C3D0681760BE471D3E31362F2FBA` |
|
||
| `behavior/scenario/workspace/tests.rs` | `CBA10D3A5C2EC0DF9E5FA67EA2B2570412DACE45BBD1D351431CC1579970C56D` |
|
||
| `forms/reference_chooser/trigger/focus.rs` | `D489FA00F445BC603B3326CAD8721E2B608456ECF543954538904BF188C6C5FA` |
|
||
| `forms/reference_chooser/widget.rs` | `D66CC17AF7A48BB8598BE683F084BB08FA7AF7304F9636F0A1BEA94C5CF6C727` |
|
||
|
||
## Independent follow-up — 2026-09-11, 15:34 UTC
|
||
|
||
Codex-956atf `/root/focus_review`. **No material new issue found in root's explicit session-reset wrapper and zero-reveal-axis correction.** This follows actual failures discovered after the preceding review; that historical source review did not establish installed-Iced key replacement or detect its fractional-capacity corner case. The preceding text and fingerprints are preserved unchanged (pre-append report SHA256 `36F77578FA73998736EDE16098B91A697678E3696806F37E7178785FBA0B5BD9`).
|
||
|
||
Read current Gitea issue 1 through comment359, empty open PRs, ScenarioFocus20260911 Wiki, the [chooser diagnosis](release-chooser-full-gate-diagnosis-20260911.md), current diff and installed Iced sources. Root assigned frozen working corrections over `8895dd2e0f87c0f16085bf4b478b8c0fbed38685`; root committed those corrections during review as `80f25882143d977ca4984691740c3a7ffd45aedd` (`fix(forms): reset replacement sessions and preserve visible scroll`). Reviewed bytes stayed equal to the saved gate manifest. This reviewer only appended this report; no production edits, compilation, test/native execution, Git mutation, network diagnostics or WSL/Linux work. Linux checking/builds remain deferred by the user's instruction.
|
||
|
||
### Session reset and I1/I2 preservation
|
||
|
||
`behavior/form_session.rs:37` stores an editing-session Id in its own typed widget state. If that Id changes, it updates the retained identity and constructs fresh child Trees. With the same Id, ordinary child diff retains compatible widget state. In `scenario/workspace.rs:757` this wraps only the `scenario-form` scrollable and its fields; the footer and sibling canvas remain outside. Size, layout, operation, events, draw, mouse and overlay forwarding retain that child's behavior. The current child has Fill width/height, matching the removed one-child keyed column's layout contract.
|
||
|
||
The concrete pre-fix sequence is still the original regression: scroll form to700 and canvas to(137,850), edit raw Name and rebuild the same session, then Cancel→Start without a closed render. The saved full log independently reads retained form700 versus expected0. Installed `iced_widget::keyed::Column::diff` delegates to `iced_core::widget::tree::diff_children_custom_with_search`; with equal child counts, that helper diffs the existing child instead of constructing a replacement despite the changed key. The explicit wrapper removes that dependency. `workspace/tests.rs` is unchanged from8895: it still requires same-session700, replacement0, unchanged canvas(137,850), fresh recovery session, exact raw Name, same accepted-Project pointer and no Undo.
|
||
|
||
The focus session/mount distinction remains intact: `workspace.rs:642–646` passes the session to the editor and keys the outer parent sensor by mount. Source Back/Use/Escape still changes the presentation mount and pending intent without rotating the editing session or raw semantic identities. `app.rs` and `scenario.rs` have no delta from8895. Stamped Name targeting, live outer owner marker, Collect's missing-target rejection and Apply's owner recheck remain unchanged. The wrapper forwards operations to its child without adding a competing owner marker or hiding a scroll ancestor.
|
||
|
||
### Zero-axis correction
|
||
|
||
`scenario/focus.rs:249–261` now returns exactly zero delta independently for each axis whose reveal request is zero. Nonzero axes retain the existing bounded reveal calculation, inner-to-outer traversal and guarded Apply. This is the same narrow correction as the reviewed chooser path, with no relaxed geometry assertion or ownership check.
|
||
|
||
Installed Iced rounds the translation reported to operations, while capacity remains fractional. For an already-visible target with rounded offset101 and capacity100.6, the old zero-reveal expression yields−0.4; the new branch yields0. Previously that artificial delta could change the underlying offset and its next drawn pixel. If one axis needs revealing and the other does not, only the needed axis receives a delta. An entirely visible target adds no scroll shift. This source reasoning supports the correction; no new numeric or runtime experiment was run by this reviewer.
|
||
|
||
### Independently read execution evidence and frozen inputs
|
||
|
||
Read the saved logs under `.local/chooser-correction-gate-20260911/`: chooser **14 passed/0 failed/0 ignored**,64.11s; scenario workspace **18 passed/0 failed/0 ignored**,4.89s. The18 include the unchanged replacement-session regression and all five I1/I2 tests. These are root's executions, independently inspected here; they are not additional test runs. The earlier complete gate remains716/4,377.91s in its preserved log. This follow-up makes no full-rerun, native GUI or Linux acceptance claim.
|
||
|
||
Independently hashed the saved binary as `05811E18E4FF3495EECFD585947234906F27F7709B7E583F0362477EF1A943C3` and512-input manifest as `985C06A3B9926C9096F97D59DDE57CE3494F2FE06008BB9F46FBD5578126B4BB`. All seven checked current inputs (the four root correction paths below, workspace tests, App and scenario state) match that manifest. This is a scoped input comparison, not an independent reconstruction of all512 entries. The three chooser-owned corrections remain covered by their separate diagnosis/review and root's gate.
|
||
|
||
| Corrected/retained input below `crates/oa-desktop/src` | SHA256 |
|
||
| --- | --- |
|
||
| `behavior/form_session.rs` | `F5027FB3A5A5599A182E7D1A10DBA56DD66EB1F23A4BA4C4A1744C9A6A5B6E61` |
|
||
| `behavior.rs` | `94AE865C35BA6E5BA3EB77A0F77B795933A86801AE68E68E395A5E1E5E0EE6ED` |
|
||
| `behavior/scenario/workspace.rs` | `D338C612058FB9AE82A6ED016A334042898D4CBFC2A8524BA22F7718AA91B03E` |
|
||
| `behavior/scenario/focus.rs` | `73A9EA10AD7312086081B8688396A21AB4251C9FAECC2DF6D984B702F3963533` |
|
||
| Unchanged `behavior/scenario/workspace/tests.rs` | `457150FDA4B92EAC416A82819DFBA147C7F2F1400F71F092B7A8CD085ABAECFD` |
|
||
|
||
Root retains full-suite/native acceptance and the later canvas/process union. Reusing this helper there must preserve each editor's actual session/invocation identity; this review does not establish acceptance of that isolated candidate. The earlier limitation concerning the chooser's separate overlay search input remains unchanged.
|