Files
ARCADIA-Studio/harness/experiments/text-workspace-native3-20260913/reviews/native2-escape-undo-review.md
T
sorokin.oleg.edu 2df7f580aa Make the Text workspace compact and preserve editing context
Replace the oversized header and reference rail with stable editor slots and a retained supporting drawer. Bind diagnostic, result and menu actions to their original publication and visit; preserve effective selections on navigation and dismiss Actions, Find and the drawer one surface per Escape.

Retain exact Windows source captures, eight final gates (871 desktop passes), independent reviews, native selection/rename/recovery trials and the original failures. All 526 tested inputs and staged evidence were byte-checked before commit. Combined preview integration and packaging remain with issue 27; Linux remains paused.
2026-09-12 22:00:36 -07:00

53 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Native trial 2: Escape and text Undo review
Read-only source and evidence review by Codex-9e8r6t /root/diagnostic_input, 2026-09-13. Parent owns the live GUI, source integration and execution. This note is the only new artifact; no source edits, build, test, Git or GUI operation was performed for this review. Source references below are relative to C:/ar-text-9e8r6t at the hashes recorded below. Trial evidence is under main `.local/text-workspace-native-20260912/trial-text-2`.
## Escape: one legacy action, not duplicate dispatch
Screenshots 050 and 051 were independently inspected. 050 shows the menu dismissed with Find and References still open. 051 shows both Find and the drawer closed. Its filename says “keeps-drawer”; that label is incorrect and must not override the pixels.
The mechanism is direct: `app.rs:1996` computes whether to restore source focus, then unconditionally sets `source_navigation.open = false` and calls `text_workspace.show_drawer(None)` before guarded focus restoration. The captured bridge (`behavior/creation.rs:15,23`) emits only for Captured Escape. The ordinary subscription (`app.rs:1128–1142`) explicitly ignores Captured Escape. The bridge is disabled while the Text popup is open (`app.rs:1117`). There is no evidence of two App Escape messages from one key. The actual-subscription test at `app/source_symbols/tests.rs:1916` already asserts one message after popup dismissal and then explicitly expects both surfaces closed; the modal matrix at line 1099 also encodes the simultaneous dismissal.
Frozen CBC `main/crates/oa-desktop/src/app.rs:1911` performed the same simultaneous dismissal, additionally clearing old results. This is inherited behavior, not a new subscription race. Current interaction contract line 53 requires only menu-first dismissal, which trial 2 passes. Earlier private `design.md:50` says “Escape closes only the focused transient surface”; that stronger scoped-dismissal intent was omitted from the handler/test expectations. Parent now accepts a one-surface-per-Escape correction after the native trial closes. This is a bounded usability defect, with no observed source/model data loss; retained query data already survives Hide.
### Small correction and evaluator
Keep the existing popup and modal dispatch layers. In the ordinary Text Escape path, dismiss Find if it is open; otherwise hide the supporting drawer. Use the existing focus-only restoration for Find, preserving its actual selected bytes and scroll. Do not introduce another subscription or focused-widget engine. The accepted priority is explicitly menu → Find → drawer, including the case where clicking Actions had unfocused the Find input.
Extend the actual subscription regression: start with current References data, grouping and nonzero saved scroll, open Find, then Actions. Popup Escape yields its tokened dismissal and no bridge message. The next actual captured/ignored Escape yields exactly one App message, closes Find only, retains drawer visit/groups/results/scroll, and leaves the live word/line selection intact after guarded focus. The next Escape closes only the drawer and retains its data. Check accepted source/model/history unchanged; pending matching query completion may store data without jumping/reopening. Update the two legacy simultaneous-dismissal expectations rather than merely adding a new test that contradicts them. Native replay must inspect each resulting surface separately.
Higher-priority risks: do not move the Text branch before menu handling (`app.rs:1232`), architecture cancellation (1287), model-menu dismissal (1324), hosted/workflow/file/delete/pending dialogs (1392), or rename cancellation (1454). Existing modal Escape tests must still leave underlying Find/drawer intact and must not queue editor focus. Generic source interaction invalidation precedes ordinary dispatch; retain that cancellation and queue focus only after the chosen current surface closes. Preserve `source_navigation_available` guards (`app/source_symbols.rs:91`) and the raw-input/ticket guards on asynchronous focus. Do not inadvertently extend this Text priority to behavior-source back/cancel or active connection cancellation in the same ordinary handler.
## Text Undo: separate existing history limitation
`source_workspace.rs:83` stores `past/future: Vec<String>` plus one current cursor, with no per-history cursor, selection or scroll. `app.rs:2982` applies the edit and sends the **post-edit** cursor into `Workspace::edit` (233), which overwrites `buffer.cursor`. `Workspace::undo` (302) swaps text/history and advances generation but leaves that cursor unchanged. `app.rs:3156` then calls `show_source_file(true)`; its default path (`app.rs:700–734`) reconstructs Content with text, losing internal scroll, and queues the retained post-edit coordinate.
If that coordinate is invalid in the restored shorter text, the existing exact-cursor guard refuses the reveal, leaving the fresh editor at its default top/caret. If it remains valid, restoration can use that post-edit coordinate instead of the earlier pre-edit selection. These primary-source mechanisms explain the parent's reported scroll-to-top and occasional prior post-edit caret. Workspace bytes are unchanged from frozen CBC and CBC has the same SourceUndo reconstruction route. A targeted note search found no earlier explicit tracked Undo-scroll defect: describe this as a newly observed native limitation of pre-existing text-only history, not as already accepted exact cursor/viewport Undo behavior.
Screenshot 011 was inspected: it shows the original alias, the viewport at the file start, and “All changes saved” after the typing probe's Undo. The parent reports analogous baseline restorations during the other selection probes. This is limited evidence of visible text restoration and clean-state feedback, **not** proof of exact Undo caret/selection/scroll restoration or all unsaved buffers. Saved-disk oracle results inspect disk only; they cannot establish a live unsaved editor's cursor or viewport. Model/rename Undo evidence is a separate action and must not be used as text-Undo evidence.
Keep exact text-Undo cursor/selection/viewport semantics as a separate follow-up: decide the edit grouping and before/after selection/viewport history policy, then evaluate real replacement → Undo → Redo with Unicode, multiline CRLF, caret movement after edit, and exact source/selection/scroll assertions. Navigation design line 43 explicitly keeps existing text/model history untouched. The current Escape correction should not redesign histories.
## Exact reviewed hashes
Trial launch manifest binds source archive `83ff861fc27b7aead159fde12e6fd881ba6c3c02b29e7bf10bbc12c60b7e6067`; its native scope was still pending at launch. Hashes below bind this review, not later fixes.
| Artifact | SHA-256 |
| --- | --- |
| crates/oa-desktop/src/app.rs | 75ef46ef2789b32c5837ee33dfdc303eaba013ba75767138e4a19ba5113bc6ba |
| crates/oa-desktop/src/app/source_symbols.rs | d81914a553114d85452d973a1edb175843d27154b3f9b9fc4cbc5049d423abe4 |
| crates/oa-desktop/src/app/source_symbols/tests.rs | 00cbacdd0af98858b5e74608720bd8251719c9926569a65a0ad777a40f1744c9 |
| crates/oa-desktop/src/behavior/creation.rs | 438a245ead397060767c790c51a8f21cd5021342627999deb4695cf3bd22091a |
| crates/oa-desktop/src/source_workspace.rs | 388c71f63829c0c76526a1700ebf5f240c86c467a65aae4fca4cd6c6a88c468b |
| harness/text-workspace-interaction-contract-20260912.md | 87d83bcedc808bf78bb3f9d0bb4b09884f627c010fbc339c86e11d00f696646b |
| harness/release-text-navigation-design-20260911.md | adaaf60fa0711677997f62c49ec899b8d412a0a0896897b2f1bb53d0ecdbeb75 |
| main private design.md | 73c6aa75980ce0ceeb132ef8a89f73a906a2ed6c4a7cc1f2ff5745ab0d0b66fa |
| frozen CBC main app.rs | d2e13b4527eec6c0920668d312d647806c762ed0a2f3ad9595a1243d9993fc14 |
| trial2 launch-manifest.json | f4bc04c2f6669f7e2cb28d12cc65efe4c89917396c3d871a189960dea7dee1ee |
| trial2 screenshots/050-escape-closes-only-actions.json | 3bb686f78988b6d7a321fa4c7c7f62f7ffe159023fb38146b8fb6baa73d924bf |
| trial2 screenshots/050-escape-closes-only-actions-0.jpg | d414906bcb1e55e881128a388c223e9f139b5c5097083bb51f35cad133632fdc |
| trial2 screenshots/051-second-escape-closes-find-keeps-drawer.json | 942ccb4b8cb87de4a2b1d02fe5daa98ccf8db26723c2d55ab946570b59c5e10e |
| trial2 screenshots/051-second-escape-closes-find-keeps-drawer-0.jpg | 988dc77f7844cbae0bf3156e27065a20f5198e7a081ecb7b031d95f15f04b29a |
| trial2 screenshots/011-word-find-close-undo-baseline.json | cfdf9fb5fe821e269e2288acc9d3e69bce7d2601b0dc1f528044755eff390658 |
| trial2 screenshots/011-word-find-close-undo-baseline-0.jpg | ddb8488cfefad22260bf9aded45ca46a7c77cdf2e35ec413c1e66d605f01ece5 |