From b8685416f56e53e30bd11ecf93a54cea10ac8458 Mon Sep 17 00:00:00 2001 From: Codex-ytr83r Date: Tue, 22 Sep 2026 21:21:50 -0700 Subject: [PATCH] Preserve read-only panning while canceling State edits --- crates/oa-desktop/src/app/state_bend_tests.rs | 9 +++++++++ crates/oa-desktop/src/behavior/state_canvas.rs | 9 +++++++-- harness/state-bends-20260923.md | 9 +++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/crates/oa-desktop/src/app/state_bend_tests.rs b/crates/oa-desktop/src/app/state_bend_tests.rs index d05f7793..502ac5d0 100644 --- a/crates/oa-desktop/src/app/state_bend_tests.rs +++ b/crates/oa-desktop/src/app/state_bend_tests.rs @@ -305,7 +305,16 @@ fn state_bend_self_loop_add_move_remove_clear_preserves_project_and_source_histo vec![], ); assert_eq!(app.project(), &baseline.decoded.project); + assert_source_model_agree(&app); + // Clear is a new source-preserving edit and may retain empty-list trivia. + // Exact original bytes are restored by history, not by reauthoring a value. + for _ in 0..3 { + assert!(app.document.can_undo()); + send(&mut app, Message::Undo); + } + assert_eq!(app.project(), &baseline.decoded.project); assert_eq!(app.document.bundle(), &baseline.bundle); + assert!(!app.document.can_undo()); } #[test] diff --git a/crates/oa-desktop/src/behavior/state_canvas.rs b/crates/oa-desktop/src/behavior/state_canvas.rs index baacea18..29be9c4b 100644 --- a/crates/oa-desktop/src/behavior/state_canvas.rs +++ b/crates/oa-desktop/src/behavior/state_canvas.rs @@ -136,13 +136,16 @@ enum Hit { } impl State { - fn cancel_gesture(&mut self) { + fn cancel_edit(&mut self) { self.press = None; self.preview = None; self.attachment_preview = None; self.bend = None; self.bend_preview = None; self.attachment_viewport = None; + } + fn cancel_gesture(&mut self) { + self.cancel_edit(); self.pan_from = None; } fn reset(&mut self) { @@ -1178,7 +1181,9 @@ impl canvas::Program for StateCanvas<'_> { state.tool = Some(self.tool); } if !self.editable { - state.cancel_gesture(); + // Pending edits block model changes, but read-only panning remains + // available and must survive successive pointer events. + state.cancel_edit(); state.source = None; } if state diff --git a/harness/state-bends-20260923.md b/harness/state-bends-20260923.md index 405ae4d2..f8b702f8 100644 --- a/harness/state-bends-20260923.md +++ b/harness/state-bends-20260923.md @@ -75,6 +75,15 @@ observe menus, guidance, preview and normal close. Bind evidence to an identifie source/binary and predeclared complete-Project expectations. Compilation alone does not establish interaction acceptance. Linux remains user-paused. +The first full workspace run exposed a read-only pan regression: canceling model +edits on every pending-draft event also canceled the middle-button pan. Keep +edit cancellation separate from navigation cancellation; the existing scoped +pan regression exercises this distinction. The self-loop test also distinguishes +typed-model restoration by Clear from byte-exact source restoration by Undo: +source-preserving edits may retain harmless empty-list whitespace, whereas Undo +must recover the original source bundle exactly. Failed run receipts are retained; +these findings do not assert that the corrected candidate has passed its gates. + Codex-956atf retains issue 16 resize and issue 27 integration ownership. This work uses the existing State model/router and needs composition with those contributions. It does not certify a combined release, change Process/Scenario