//! T M10.10 — Frontend-side optimistic-apply infrastructure.
//!
//! Two pieces of logic live here, deliberately small and testable in
//! isolation:
//!
//! 1. **`classify_key`** — the text-input predicate. Given a keystroke,
//!    decides whether to take the optimistic path (insert / delete-back /
//!    delete-forward) or fall through to the v0.1 `FrontendEvent::Key`
//!    round-trip. Pure function; no state.
//!
//! 2. **`apply_incoming_crdt_op`** — the echo-dedup filter for incoming
//!    `InstanceMessage::CrdtOp` broadcasts. Compares the broadcast's
//!    source `FrontendId` to the local frontend's id and either applies
//!    the op to the `BufferMirror` (remote) or skips (own echo).
//!
//! The attach loop (`attach.rs`) is the consumer: each keystroke runs
//! through `classify_key`; each incoming `CrdtOp` runs through
//! `apply_incoming_crdt_op`. Keeping these as standalone functions in
//! a dedicated module makes them unit-testable without spinning up an
//! attach session.
//!
//! # Semantics note: keymap and the text-input predicate
//!
//! `classify_key` assumes the default keymap's "text-input → self-
//! insert" mapping. Users with Lua keymap rebindings for text characters
//! (e.g., binding 'a' to a non-insert command) will see those bindings
//! lost on replica frontends — text-input chars take the optimistic
//! path and never reach the daemon's keymap layer.
//!
//! This is a v1.0-acceptable simplification: most users don't rebind
//! text characters; users who do can fall back to v0.1 round-trip by
//! advertising `crdt_replica: false`. v0.2+ may expand the predicate
//! to consult a frontend-side keymap mirror.

use crate::buffer::BufferId;
use crate::buffer_mirror::{BufferMirror, BufferMirrorError};
use crate::protocol::{FrontendEvent, FrontendId, Key, KeyEvent, Modifiers};
use crate::rope::CrdtOp;
use unicode_width::UnicodeWidthChar;

/// Result of classifying a keystroke for optimistic apply.
///
/// The frontend's keystroke handler matches on this to either take the
/// optimistic path (the concrete actions) or fall through to the v0.1
/// `FrontendEvent::Key` send.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum OptimisticAction {
    /// Insert a single character at the cursor.
    Insert(char),
    /// Delete one byte/grapheme behind the cursor (Backspace).
    DeleteBack,
    /// Delete one byte/grapheme at the cursor (Delete-forward).
    DeleteForward,
    /// Undo this frontend's most recent edit on the active buffer
    /// (M10.11 P1). Triggered by single-key undo bindings whose
    /// modifier set is `Ctrl` and whose `Char` is `_` or `/` — the
    /// two terminal-portable spellings of the default-keymap undo
    /// binding (`builtin/keymaps/default.lua`). Multi-key undo
    /// bindings like `C-x u` fall through to `RoundTrip` because
    /// the optimistic layer doesn't track keymap-prefix state.
    Undo,
    /// No optimistic path applies; fall through to round-trip via
    /// `FrontendEvent::Key`. Covers control-char modifiers (Ctrl, Alt,
    /// Meta, Hyper) that aren't bound to an optimistic action,
    /// function keys, navigation keys, and any keystroke whose
    /// semantics aren't text-input or recognized commands.
    RoundTrip,
}

/// True if the modifier set excludes all editor-control modifiers
/// (Ctrl, Alt, Meta, Hyper). Shift is allowed because capital letters
/// arrive as `Char('A')` with `SHIFT` set — Shift is part of how the
/// character was produced, not a command modifier that changes semantics.
const fn is_text_input_modifiers(mods: Modifiers) -> bool {
    !mods.contains(Modifiers::CTRL)
        && !mods.contains(Modifiers::ALT)
        && !mods.contains(Modifiers::META)
        && !mods.contains(Modifiers::HYPER)
}

/// Classify a key event for the optimistic-apply path.
///
/// Returns:
/// - `Insert(c)` for a printable `Char(c)` with no editor-control modifier.
/// - `DeleteBack` for `Backspace` with no editor-control modifier.
/// - `DeleteForward` for `Delete` with no editor-control modifier.
/// - `RoundTrip` for everything else (modified text input, function
///   keys, arrows, escape, etc.).
///
/// `char::is_control()` filters out ASCII control codes (0x00–0x1F,
/// 0x7F) and Unicode control codes. Tab and Enter qualify as control
/// chars and therefore round-trip — they often have non-insert
/// semantics in editor keymaps (indentation, newline-with-indent).
#[must_use]
pub fn classify_key(key: Key, mods: Modifiers) -> OptimisticAction {
    // M10.11 P1 — single-key undo bindings.
    //
    // The default keymap (`builtin/keymaps/default.lua`) binds four
    // forms of undo: `C-/`, `C-_`, `C-4`, and `C-x u`. Crossterm's
    // raw-terminal parser (`crossterm-0.28.1` /
    // `event/sys/unix/parse.rs:106-113`) only delivers some of
    // these as the literal `Char + Modifiers::CTRL` shape:
    //
    // - 0x01..=0x1A (Ctrl-A..Ctrl-Z) → `Char(letter)` + CTRL
    // - 0x1C..=0x1F → `Char('4')..Char('7')` + CTRL (the offset-
    //   from-'4' convention crossterm uses for non-letter Ctrl
    //   bytes; *not* the "Ctrl-_" / "Ctrl-/" naming users
    //   intuitively expect — that mapping requires Kitty Keyboard
    //   Protocol enhanced mode, which pmacs doesn't currently
    //   negotiate).
    //
    // Practical consequence: when a real terminal user presses
    // Ctrl-_, the byte 0x1F arrives, crossterm produces
    // `Char('7')` + CTRL, *no* default-keymap binding matches.
    // The deliverable undo keystrokes for raw-terminal users are
    // C-4 (byte 0x1C) and C-x u (multi-key, falls through to
    // daemon dispatch).
    //
    // We optimistically recognize `Char('4')` + CTRL as Undo
    // because the default keymap binds it, AND it's the form a
    // real terminal can actually deliver. `Char('/')` and
    // `Char('_')` with CTRL are also recognized for symmetry —
    // they'll match when Kitty enhanced mode is negotiated, or
    // when a non-PTY frontend (future GUI) emits them directly.
    // Multi-key bindings like `C-x u` round-trip because the
    // optimistic layer doesn't track keymap-prefix state.
    //
    // The `mods == CTRL` exact-match (rather than `contains(CTRL)`)
    // ensures combos like `C-S-_` round-trip rather than triggering
    // undo unexpectedly. Lua-rebound forms similarly round-trip.
    if mods == Modifiers::CTRL && matches!(key, Key::Char('/' | '_' | '4')) {
        return OptimisticAction::Undo;
    }
    if !is_text_input_modifiers(mods) {
        return OptimisticAction::RoundTrip;
    }
    match key {
        Key::Char(c) if !c.is_control() => OptimisticAction::Insert(c),
        Key::Backspace => OptimisticAction::DeleteBack,
        Key::Delete => OptimisticAction::DeleteForward,
        _ => OptimisticAction::RoundTrip,
    }
}

/// Compute the `FrontendEvent` to send upstream for a keystroke,
/// applying the optimistic-apply path locally if the mirror is
/// ready **and** the action is paint-eligible.
///
/// This is the keystroke-handler orchestrator: it classifies the
/// key, consults the mirror's readiness + paint-eligibility for the
/// active buffer, and either returns a `FrontendEvent::CrdtOp`
/// (after applying the edit to the local mirror) or a
/// `FrontendEvent::Key` (round-trip path: original keystroke is
/// forwarded as before).
///
/// # Decision flow
///
/// 1. `classify_key(key, mods)` → `OptimisticAction`.
/// 2. `RoundTrip` → return `FrontendEvent::Key`.
/// 3. `Insert(c)` / `DeleteBack` / `DeleteForward`:
///    - Read `mirror.active_buffer()`. None → fall through to
///      `FrontendEvent::Key` (no active buffer known; Refinement 4
///      graceful degradation).
///    - Check `mirror.is_ready(active_buffer)`. False → fall
///      through (mirror not bootstrapped for this buffer).
///    - Check `mirror.cursor_byte_pos(active_buffer)`. None → fall
///      through (cursor position unknown).
///    - **Paint-eligibility gate (post-audit-round-3 F19):**
///      - `Insert(c)`: require `mirror.cursor_at_end_of_line` →
///        Some(true). Mid-line insert falls through to round-trip.
///      - `DeleteBack`: require
///        `mirror.cursor_at_end_of_line_safe_for_delete_back` →
///        Some(true). Mid-line, line-joining, or width-unsafe
///        delete-back falls through to round-trip.
///      - `DeleteForward`: ALWAYS round-trip (no optimistic paint
///        primitive exists for delete-forward; advancing the
///        mirror without painting de-syncs the mirror cursor from
///        the terminal cursor).
///    - Apply the action to the mirror. Errors fall through.
///    - Return `FrontendEvent::CrdtOp { source: my_fid, buffer_id,
///      op: CrdtOp { peer_id, bytes } }`.
///
/// The caller writes whatever `FrontendEvent` is returned. Non-
/// paint-eligible actions round-trip via the daemon's Key path; the
/// daemon's `apply_active_edit` emits a `DaemonKey`-origin CRDT op
/// (F16) which broadcasts to every replica including the source.
/// The source mirror updates via the broadcast, keeping mirror state
/// and terminal cursor coherent.
///
/// # F19 motivation
///
/// Pre-fix, the orchestrator advanced mirror state for non-paint
/// edits (mid-line insert, mid-line backspace, all delete-forward).
/// The terminal cursor stayed at its pre-edit position (no paint
/// primitive fires) until the daemon's `CellDelta` arrived. A fast
/// next keystroke would then run optimistic logic against the
/// already-advanced mirror — `cursor_at_end_of_line` could report
/// "yes" at the mirror's new cursor while the terminal cursor was
/// at the OLD pre-edit position, causing `paint_optimistic_insert`
/// to write at the wrong column.
#[must_use]
pub fn frontend_event_for_keystroke(
    mirror: &mut BufferMirror,
    my_fid: FrontendId,
    pmacs_key: KeyEvent,
) -> FrontendEvent {
    let action = classify_key(pmacs_key.key, pmacs_key.mods);
    let round_trip = || FrontendEvent::Key(pmacs_key);
    if matches!(action, OptimisticAction::RoundTrip) {
        return round_trip();
    }
    // Need: active buffer + mirror ready for it. The cursor-position
    // and cursor-freshness checks only apply to position-targeted
    // actions (Insert / DeleteBack); Undo reverses the last op by
    // peer regardless of cursor position, so it skips those gates.
    let Some(buffer_id) = mirror.active_buffer() else {
        return round_trip();
    };
    if !mirror.is_ready(buffer_id) {
        return round_trip();
    }

    // M10.11 P1 — undo's optimistic path. Undo doesn't depend on
    // cursor position or paint eligibility (stance α: no visual
    // paint for optimistic undo; daemon's CellDelta drives
    // reconciliation). The undo affects content at arbitrary
    // positions; `apply_local_undo` marks the cursor stale so
    // subsequent optimistic keystrokes round-trip until the daemon's
    // `CursorByte` re-grounds.
    if matches!(action, OptimisticAction::Undo) {
        return match mirror.apply_local_undo(buffer_id) {
            Ok(Some(op_bytes)) => FrontendEvent::CrdtOp {
                frontend_id: my_fid,
                buffer_id,
                op: CrdtOp {
                    peer_id: mirror.peer_id(),
                    bytes: op_bytes,
                },
            },
            // Nothing to undo locally (UndoManager stack empty) or
            // loro error. Round-trip the Key event; the daemon's
            // dispatch_key may have its own daemon-peer ops to undo
            // (Lua-driven daemon-side edits), so the Key path remains
            // the right fallback. If the daemon also has nothing, the
            // path silently no-ops — same as v0.1.
            Ok(None) | Err(_) => round_trip(),
        };
    }

    // Position-targeted actions need authoritative cursor state
    // (post-audit-round-4 F22 + F23 freshness invariant). A stale
    // cursor means the mirror's cursor for this buffer hasn't been
    // re-grounded by the daemon's `CursorByte` since the last
    // potential desync.
    if !mirror.is_cursor_fresh(buffer_id) {
        return round_trip();
    }
    let Some(cursor) = mirror.cursor_byte_pos(buffer_id) else {
        return round_trip();
    };

    let result = match action {
        OptimisticAction::Insert(c) => {
            // F19 — only optimistic-apply when paint will fire.
            // Mid-line insert can't be painted by a single Print
            // (cells to the right of cursor would need to shift),
            // so we round-trip and let the daemon's CellDelta drive
            // both visual and mirror update.
            if mirror.cursor_at_end_of_line(buffer_id) != Some(true) {
                return round_trip();
            }
            // Post-audit-round-4 F24 — `paint_optimistic_insert`
            // calls `queue!(Print(c))` which writes one terminal
            // column. Wide chars (width 2) would only paint the
            // base column without the Continuation cell; zero-
            // width chars (combining marks, ZWJ) write a column
            // for what `TextView` renders as a cluster attached to
            // the previous cell. Either mismatch leaves the
            // terminal out of sync with what the daemon's
            // eventual `CellDelta` will paint. Width-unsafe
            // inserts round-trip; the daemon's `CellDelta` drives
            // both visual + mirror update.
            if UnicodeWidthChar::width(c) != Some(1) {
                return round_trip();
            }
            let mut tmp = [0u8; 4];
            let s: &str = c.encode_utf8(&mut tmp);
            let s_len = s.len();
            mirror
                .apply_local_insert(buffer_id, cursor, s)
                .inspect(|_bytes| {
                    mirror.advance_cursor(buffer_id, s_len);
                })
        }
        OptimisticAction::DeleteBack => {
            // F19 — only optimistic-apply when the strict delete-
            // back predicate holds (end-of-line + prev char not '\n'
            // + prev char width == 1). Round-trip otherwise.
            if mirror.cursor_at_end_of_line_safe_for_delete_back(buffer_id) != Some(true) {
                return round_trip();
            }
            match mirror.prev_char_len(buffer_id) {
                Some(n) if n > 0 => {
                    let new_pos = cursor.saturating_sub(n);
                    mirror
                        .apply_local_delete(buffer_id, new_pos, n)
                        .inspect(|_bytes| {
                            mirror.retreat_cursor(buffer_id, n);
                        })
                }
                _ => return round_trip(),
            }
        }
        OptimisticAction::DeleteForward => {
            // F19 — no optimistic paint primitive exists for
            // delete-forward. Always round-trip. Mirror state stays
            // coherent via the daemon's broadcast (F16 ensures the
            // source receives it).
            return round_trip();
        }
        OptimisticAction::Undo => unreachable!("Undo handled above"),
        OptimisticAction::RoundTrip => unreachable!("RoundTrip handled above"),
    };

    match result {
        Ok(op_bytes) => FrontendEvent::CrdtOp {
            frontend_id: my_fid,
            buffer_id,
            op: CrdtOp {
                peer_id: mirror.peer_id(),
                bytes: op_bytes,
            },
        },
        Err(_) => {
            // Optimistic application failed (e.g., mid-codepoint or
            // out-of-range position — shouldn't happen given the
            // char-aware byte counts above, but defensive). Fall
            // through to v0.1 round-trip.
            round_trip()
        }
    }
}

/// Outcome of routing an incoming `InstanceMessage::CrdtOp` through
/// the echo-dedup filter.
#[derive(Debug, Eq, PartialEq)]
pub enum IncomingCrdtOpOutcome {
    /// Op was applied to the mirror (source frontend was not us).
    Applied,
    /// Op was filtered out as a local-edit echo (source frontend
    /// was us; the mirror has already integrated this op via
    /// `apply_local_insert` / `apply_local_delete`).
    SkippedEcho,
}

/// Handle an incoming `CrdtOp` broadcast: filter own-echoes; apply
/// remote ops to the mirror.
///
/// **Filter rule (matches `BufferMirror::apply_remote_op` docstring):**
/// op is an echo iff `source == local_id`. The filter lives at this
/// call site (not in `BufferMirror`) because the mirror is
/// identity-ignorant by design — it operates on op bytes only.
/// Pushing the filter here keeps the mirror reusable in non-session
/// contexts (tests, future Lua bindings) and concentrates the
/// `FrontendId` comparison in one place.
///
/// # Errors
///
/// Propagates [`BufferMirrorError`] from the underlying mirror call.
/// Echo-skip never errors.
pub fn apply_incoming_crdt_op(
    mirror: &mut BufferMirror,
    local_id: FrontendId,
    source: FrontendId,
    buffer_id: BufferId,
    op_bytes: &[u8],
) -> Result<IncomingCrdtOpOutcome, BufferMirrorError> {
    if source == local_id {
        return Ok(IncomingCrdtOpOutcome::SkippedEcho);
    }
    mirror.apply_remote_op(buffer_id, op_bytes)?;
    Ok(IncomingCrdtOpOutcome::Applied)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::crdt::CrdtState;

    // -----------------------------------------------------------------
    // classify_key — the text-input predicate.
    // -----------------------------------------------------------------

    #[test]
    fn classify_ascii_char_no_modifiers_is_insert() {
        assert_eq!(
            classify_key(Key::Char('a'), Modifiers::NONE),
            OptimisticAction::Insert('a')
        );
    }

    #[test]
    fn classify_ascii_char_with_shift_is_still_insert() {
        // Capital letters arrive with SHIFT set; the char itself is
        // already the shifted version.
        assert_eq!(
            classify_key(Key::Char('A'), Modifiers::SHIFT),
            OptimisticAction::Insert('A')
        );
    }

    #[test]
    fn classify_ascii_char_with_ctrl_is_round_trip() {
        // Ctrl+a is a command, not text input.
        assert_eq!(
            classify_key(Key::Char('a'), Modifiers::CTRL),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_ascii_char_with_alt_is_round_trip() {
        assert_eq!(
            classify_key(Key::Char('a'), Modifiers::ALT),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_ascii_char_with_meta_is_round_trip() {
        assert_eq!(
            classify_key(Key::Char('a'), Modifiers::META),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_ascii_char_with_hyper_is_round_trip() {
        assert_eq!(
            classify_key(Key::Char('a'), Modifiers::HYPER),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_space_no_modifiers_is_insert() {
        assert_eq!(
            classify_key(Key::Char(' '), Modifiers::NONE),
            OptimisticAction::Insert(' ')
        );
    }

    #[test]
    fn classify_punctuation_no_modifiers_is_insert() {
        for c in ['.', ',', ';', ':', '!', '?', '@', '#', '$', '%'] {
            assert_eq!(
                classify_key(Key::Char(c), Modifiers::NONE),
                OptimisticAction::Insert(c)
            );
        }
    }

    #[test]
    fn classify_unicode_char_no_modifiers_is_insert() {
        // Non-ASCII printable — multi-byte UTF-8.
        assert_eq!(
            classify_key(Key::Char('é'), Modifiers::NONE),
            OptimisticAction::Insert('é')
        );
        assert_eq!(
            classify_key(Key::Char('中'), Modifiers::NONE),
            OptimisticAction::Insert('中')
        );
    }

    #[test]
    fn classify_backspace_no_modifiers_is_delete_back() {
        assert_eq!(
            classify_key(Key::Backspace, Modifiers::NONE),
            OptimisticAction::DeleteBack
        );
    }

    #[test]
    fn classify_backspace_with_shift_is_still_delete_back() {
        // Shift+Backspace behaves the same as Backspace in default
        // keymap; Shift doesn't change the semantic.
        assert_eq!(
            classify_key(Key::Backspace, Modifiers::SHIFT),
            OptimisticAction::DeleteBack
        );
    }

    #[test]
    fn classify_backspace_with_ctrl_is_round_trip() {
        // Ctrl+Backspace is often "delete previous word" — keymap
        // territory, not optimistic text-input.
        assert_eq!(
            classify_key(Key::Backspace, Modifiers::CTRL),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_delete_no_modifiers_is_delete_forward() {
        assert_eq!(
            classify_key(Key::Delete, Modifiers::NONE),
            OptimisticAction::DeleteForward
        );
    }

    #[test]
    fn classify_delete_with_ctrl_is_round_trip() {
        assert_eq!(
            classify_key(Key::Delete, Modifiers::CTRL),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_function_key_is_round_trip() {
        for n in 1u8..=12 {
            assert_eq!(
                classify_key(Key::F(n), Modifiers::NONE),
                OptimisticAction::RoundTrip
            );
        }
    }

    #[test]
    fn classify_navigation_keys_are_round_trip() {
        for key in [
            Key::Left,
            Key::Right,
            Key::Up,
            Key::Down,
            Key::Home,
            Key::End,
            Key::PageUp,
            Key::PageDown,
        ] {
            assert_eq!(
                classify_key(key, Modifiers::NONE),
                OptimisticAction::RoundTrip
            );
        }
    }

    #[test]
    fn classify_enter_and_tab_are_round_trip() {
        // Enter and Tab are arguably text input but often have
        // editor-specific semantics (newline-with-indent, indent
        // command). Send via round-trip so keymap can dispatch.
        assert_eq!(
            classify_key(Key::Enter, Modifiers::NONE),
            OptimisticAction::RoundTrip
        );
        assert_eq!(
            classify_key(Key::Tab, Modifiers::NONE),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_escape_is_round_trip() {
        assert_eq!(
            classify_key(Key::Escape, Modifiers::NONE),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_unknown_key_is_round_trip() {
        assert_eq!(
            classify_key(Key::Unknown(0x1234), Modifiers::NONE),
            OptimisticAction::RoundTrip
        );
    }

    #[test]
    fn classify_null_char_is_round_trip() {
        // Char('\0') is control; should not optimistic-insert a NUL.
        assert_eq!(
            classify_key(Key::Char('\0'), Modifiers::NONE),
            OptimisticAction::RoundTrip
        );
    }

    // -----------------------------------------------------------------
    // apply_incoming_crdt_op — echo-dedup composition test.
    // -----------------------------------------------------------------

    /// Helper: build a snapshot of a small CRDT replica seeded with
    /// the given text under `peer_id`.
    fn fresh_snapshot(peer_id: u64, initial: &str) -> Vec<u8> {
        let state = CrdtState::new(peer_id).expect("new");
        state.insert(0, initial).expect("seed");
        state.export_snapshot().expect("export")
    }

    // -----------------------------------------------------------------
    // frontend_event_for_keystroke — Day 3 step 3b orchestrator.
    // -----------------------------------------------------------------

    fn key_event(key: Key, mods: Modifiers, fid: FrontendId) -> KeyEvent {
        KeyEvent {
            frontend_id: fid,
            key,
            mods,
            timestamp_ns: 0,
        }
    }

    fn ready_mirror_with_cursor(initial: &str, cursor: usize) -> (BufferMirror, BufferId) {
        let fid = FrontendId(2);
        let mut m = BufferMirror::new(fid);
        let id = BufferId::next();
        m.init_from_snapshot(id, &fresh_snapshot(99, initial))
            .expect("init");
        m.set_cursor_byte_pos(id, cursor);
        (m, id)
    }

    #[test]
    fn keystroke_round_trips_when_mirror_has_no_active_buffer() {
        let mut m = BufferMirror::new(FrontendId(2));
        let fid = FrontendId(2);
        let ev = key_event(Key::Char('a'), Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {} // round-trip
            other => panic!("expected Key (graceful fallback), got {other:?}"),
        }
    }

    #[test]
    fn keystroke_round_trips_when_buffer_not_ready() {
        let fid = FrontendId(2);
        let mut m = BufferMirror::new(fid);
        // Set cursor for a buffer that has no snapshot yet — mirror
        // tracks the cursor but is_ready returns false.
        let id = BufferId::next();
        m.set_cursor_byte_pos(id, 5);
        assert!(!m.is_ready(id));
        let ev = key_event(Key::Char('a'), Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {} // round-trip per Refinement 4
            other => panic!("expected Key (graceful fallback), got {other:?}"),
        }
    }

    #[test]
    fn keystroke_round_trips_for_non_text_input() {
        // Ctrl+a — not text input; round-trip regardless of mirror
        // state.
        let (mut m, _id) = ready_mirror_with_cursor("hello", 5);
        let fid = FrontendId(2);
        let ev = key_event(Key::Char('a'), Modifiers::CTRL, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(k) => {
                assert!(k.mods.contains(Modifiers::CTRL));
            }
            other => panic!("expected Key for non-text-input, got {other:?}"),
        }
    }

    #[test]
    fn keystroke_optimistic_insert_produces_crdt_op_and_advances_cursor() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 5);
        let fid = FrontendId(2);
        let ev = key_event(Key::Char('!'), Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);

        match result {
            FrontendEvent::CrdtOp {
                frontend_id,
                buffer_id,
                op,
            } => {
                assert_eq!(frontend_id, fid);
                assert_eq!(buffer_id, id);
                assert_eq!(op.peer_id, 2);
                assert!(!op.bytes.is_empty());
            }
            other => panic!("expected CrdtOp, got {other:?}"),
        }
        // Mirror state advanced.
        assert_eq!(m.materialize(id).as_deref(), Some("hello!"));
        assert_eq!(m.cursor_byte_pos(id), Some(6));
    }

    #[test]
    fn keystroke_optimistic_insert_with_multibyte_char_advances_by_byte_length() {
        let (mut m, id) = ready_mirror_with_cursor("ab", 2);
        let fid = FrontendId(2);
        let ev = key_event(Key::Char('é'), Modifiers::NONE, fid); // 2 bytes
        let _ = frontend_event_for_keystroke(&mut m, fid, ev);
        assert_eq!(m.materialize(id).as_deref(), Some("abé"));
        // Cursor advanced by 2 (UTF-8 byte length).
        assert_eq!(m.cursor_byte_pos(id), Some(4));
    }

    #[test]
    fn keystroke_optimistic_delete_back_ascii_removes_one_byte() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 5);
        let fid = FrontendId(2);
        let ev = key_event(Key::Backspace, Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::CrdtOp { .. } => {}
            other => panic!("expected CrdtOp, got {other:?}"),
        }
        assert_eq!(m.materialize(id).as_deref(), Some("hell"));
        assert_eq!(m.cursor_byte_pos(id), Some(4));
    }

    #[test]
    fn keystroke_optimistic_delete_back_multibyte_removes_full_char() {
        // Char-boundary-aware: deleting back from after 'é' removes
        // both UTF-8 bytes, not just one (loro rejects mid-codepoint).
        let (mut m, id) = ready_mirror_with_cursor("aé", 3);
        let fid = FrontendId(2);
        let ev = key_event(Key::Backspace, Modifiers::NONE, fid);
        let _ = frontend_event_for_keystroke(&mut m, fid, ev);
        assert_eq!(m.materialize(id).as_deref(), Some("a"));
        assert_eq!(m.cursor_byte_pos(id), Some(1));
    }

    #[test]
    fn keystroke_optimistic_delete_back_at_position_zero_round_trips() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 0);
        let fid = FrontendId(2);
        let ev = key_event(Key::Backspace, Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {} // round-trip — nothing to delete
            other => panic!("expected Key at pos 0, got {other:?}"),
        }
        // Mirror untouched.
        assert_eq!(m.materialize(id).as_deref(), Some("hello"));
    }

    #[test]
    fn keystroke_optimistic_delete_forward_at_end_round_trips() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 5);
        let fid = FrontendId(2);
        let ev = key_event(Key::Delete, Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {} // round-trip — nothing to delete forward
            other => panic!("expected Key at end, got {other:?}"),
        }
        assert_eq!(m.materialize(id).as_deref(), Some("hello"));
    }

    /// Post-audit-round-3 F19: `OptimisticAction::DeleteForward`
    /// **always** round-trips. No paint primitive exists for
    /// forward-delete, so optimistically applying to the mirror
    /// without painting would desync the mirror cursor from the
    /// terminal cursor. The daemon's `CellDelta` + the F16 broadcast
    /// keep both sides in sync via round-trip.
    #[test]
    fn keystroke_optimistic_delete_forward_always_round_trips_f19() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 1);
        let fid = FrontendId(2);
        let ev = key_event(Key::Delete, Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {}
            other => panic!("F19: DeleteForward must round-trip; got {other:?}"),
        }
        // Mirror MUST be untouched — F19 narrowing prevents the
        // mirror from advancing on round-tripped edits.
        assert_eq!(m.materialize(id).as_deref(), Some("hello"));
        assert_eq!(m.cursor_byte_pos(id), Some(1));
    }

    /// F19: `OptimisticAction::Insert` mid-line round-trips
    /// (paint scope is end-of-line only; advancing the mirror
    /// mid-line desyncs from the terminal cursor).
    #[test]
    fn keystroke_optimistic_insert_mid_line_round_trips_f19() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 2); // mid-line
        let fid = FrontendId(2);
        let ev = key_event(Key::Char('X'), Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {}
            other => panic!("F19: mid-line Insert must round-trip; got {other:?}"),
        }
        assert_eq!(m.materialize(id).as_deref(), Some("hello"));
        assert_eq!(m.cursor_byte_pos(id), Some(2));
    }

    /// F24 (post-audit-round-4) — wide char (`UnicodeWidthChar::width
    /// == Some(2)`) Insert round-trips. The optimistic paint
    /// `queue!(Print(c))` writes one column; the daemon's eventual
    /// `CellDelta` paints two cells (base + Continuation).
    #[test]
    fn keystroke_optimistic_insert_wide_char_round_trips_f24() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 5);
        let fid = FrontendId(2);
        // CJK ideograph (width 2).
        let ev = key_event(Key::Char('漢'), Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {}
            other => panic!("F24: wide-char Insert must round-trip; got {other:?}"),
        }
        assert_eq!(m.materialize(id).as_deref(), Some("hello"));
        assert_eq!(m.cursor_byte_pos(id), Some(5));
    }

    /// F24 — combining mark / zero-width Insert round-trips. The
    /// paint writes a column for what `TextView` renders as a
    /// cluster attached to the previous cell.
    #[test]
    fn keystroke_optimistic_insert_combining_mark_round_trips_f24() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 5);
        let fid = FrontendId(2);
        // U+0301 COMBINING ACUTE ACCENT (width 0).
        let ev = key_event(Key::Char('\u{0301}'), Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {}
            other => panic!("F24: zero-width combining-mark Insert must round-trip; got {other:?}"),
        }
        assert_eq!(m.materialize(id).as_deref(), Some("hello"));
    }

    /// F22 (post-audit-round-4) — when the mirror cursor is stale
    /// (a prior `FrontendEvent::Key` may have moved the daemon's
    /// cursor in ways the mirror can't predict), the orchestrator
    /// must round-trip subsequent keystrokes until `CursorByte`
    /// re-grounds the mirror cursor. Otherwise a fast `<left>` then
    /// `x` sequence emits an Insert `CrdtOp` for the byte the cursor
    /// was at BEFORE `<left>`.
    #[test]
    fn keystroke_round_trips_when_cursor_is_stale_f22() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 5);
        m.mark_cursor_stale(id);
        let fid = FrontendId(2);
        let ev = key_event(Key::Char('x'), Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {}
            other => panic!("F22: stale cursor must round-trip subsequent keys; got {other:?}"),
        }
        // Mirror untouched.
        assert_eq!(m.materialize(id).as_deref(), Some("hello"));
        assert_eq!(m.cursor_byte_pos(id), Some(5));
    }

    /// F23 (post-audit-round-4) — `apply_remote_op` marks the cursor
    /// stale. A keystroke between the remote op and the next
    /// `CursorByte` must round-trip.
    #[test]
    fn keystroke_round_trips_after_remote_op_until_cursor_byte_f23() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 5);
        // Remote op: peer inserts "X" at position 0.
        let peer = CrdtState::new(99).expect("peer");
        peer.import_snapshot(&fresh_snapshot(99, "hello"))
            .expect("peer init");
        let v0 = peer.version();
        peer.insert(0, "X").expect("peer insert");
        let op_bytes = peer.export_updates_since(&v0).expect("export");
        m.apply_remote_op(id, &op_bytes).expect("apply remote");

        // Mirror content now "Xhello"; mirror cursor still at 5
        // (no right-gravity adjustment). Without F23 the
        // orchestrator would optimistically insert at byte 5 of
        // "Xhello" — wrong byte for the user's intent.
        let fid = FrontendId(2);
        let ev = key_event(Key::Char('!'), Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {}
            other => panic!("F23: post-remote-op cursor staleness must round-trip; got {other:?}"),
        }

        // After daemon's CursorByte re-grounds the mirror, optimistic
        // path reopens.
        m.set_cursor_byte_pos(id, 6); // post-right-gravity position
        let result2 = frontend_event_for_keystroke(&mut m, fid, ev);
        match result2 {
            FrontendEvent::CrdtOp { .. } => {}
            other => panic!("F23: CursorByte must clear staleness; got {other:?}"),
        }
    }

    /// F19: `OptimisticAction::DeleteBack` mid-line round-trips.
    #[test]
    fn keystroke_optimistic_delete_back_mid_line_round_trips_f19() {
        let (mut m, id) = ready_mirror_with_cursor("hello", 3); // mid-line
        let fid = FrontendId(2);
        let ev = key_event(Key::Backspace, Modifiers::NONE, fid);
        let result = frontend_event_for_keystroke(&mut m, fid, ev);
        match result {
            FrontendEvent::Key(_) => {}
            other => panic!("F19: mid-line DeleteBack must round-trip; got {other:?}"),
        }
        assert_eq!(m.materialize(id).as_deref(), Some("hello"));
        assert_eq!(m.cursor_byte_pos(id), Some(3));
    }

    /// T M10.10 Day 4 — criterion 1 unit acceptance: keystroke-to-
    /// optimistic-apply completes in sub-frame time regardless of
    /// any daemon state.
    ///
    /// Spec criterion 1: "Local edit visible in less than one frame
    /// regardless of instance latency."
    ///
    /// The load-bearing property under Path β is that the orchestrator
    /// completes synchronously — it doesn't wait for the daemon, doesn't
    /// poll, doesn't block on I/O. Mirror update is in-process; produced
    /// `FrontendEvent` is returned by value. Latency to the daemon
    /// affects when the daemon's `CellDelta` arrives back, but doesn't
    /// affect the orchestrator's completion time.
    ///
    /// This test demonstrates the property directly without involving
    /// a daemon: 100 consecutive keystrokes through the orchestrator
    /// must complete in well under 16ms (one frame at 60Hz). In
    /// practice each call is microseconds; the upper bound is
    /// generous to avoid CI flakiness.
    ///
    /// **Path β scope**: this test exercises end-of-line typing
    /// (cursor at content end after each insert). Mid-line typing
    /// would round-trip and incur daemon-latency for paint per Path
    /// β's documented scope.
    #[test]
    fn criterion_1_end_of_line_typing_completes_sub_frame_per_keystroke() {
        use std::time::Instant;
        let (mut m, _id) = ready_mirror_with_cursor("", 0);
        let fid = FrontendId(2);

        let start = Instant::now();
        for c in "the quick brown fox jumps over the lazy dog".chars() {
            let ev = key_event(Key::Char(c), Modifiers::NONE, fid);
            let result = frontend_event_for_keystroke(&mut m, fid, ev);
            // Verify each keystroke took the optimistic path —
            // criterion 1 isn't met if the orchestrator falls through
            // to FrontendEvent::Key (which would await daemon round-
            // trip).
            assert!(
                matches!(result, FrontendEvent::CrdtOp { .. }),
                "criterion 1: orchestrator must produce CrdtOp for end-of-line \
                 text input (not round-trip Key)"
            );
        }
        let elapsed = start.elapsed();
        let per_keystroke = elapsed / 43; // length of the pangram

        // Upper bound per keystroke: 1ms (60× under frame budget).
        // Loose because CI runners vary; tight enough to catch any
        // synchronous-IO regression that would put criterion 1 at risk.
        assert!(
            per_keystroke < std::time::Duration::from_millis(1),
            "criterion 1: per-keystroke orchestrator time {per_keystroke:?} \
             exceeds 1ms (well below 16ms frame budget). Total: {elapsed:?}"
        );
    }

    /// T M10.10 Day 3 step 6 — bootstrap-window typing test.
    ///
    /// Narrates the bootstrap state machine that the M10.10 frontend
    /// goes through on attach. The "bootstrap window" is the time
    /// between session establishment and the frontend's mirror being
    /// ready for optimistic apply — during this window, keystrokes
    /// must gracefully degrade to v0.1 round-trip (Refinement 4).
    /// After the bootstrap completes (`BufferSnapshot` + `CursorByte`
    /// applied), subsequent keystrokes take the optimistic path.
    ///
    /// This test walks the explicit transitions a real attach would
    /// experience (modulo the inter-thread message delivery the wire
    /// transports do):
    /// 1. Pre-bootstrap: empty mirror, type 'h' → `FrontendEvent::Key`.
    /// 2. `BufferSnapshot` arrives (`init_from_snapshot`): mirror has
    ///    state but no active buffer / cursor yet. Type 'i' → still
    ///    Key (no `active_buffer` until `CursorByte` arrives).
    /// 3. `CursorByte` arrives (`set_cursor_byte_pos`): mirror has
    ///    `active_buffer` + cursor; the optimistic predicate now fires
    ///    for in-scope keystrokes.
    /// 4. Post-bootstrap: type 'j' → `FrontendEvent::CrdtOp`.
    ///
    /// Each transition is the boundary that step 3a's wire variants
    /// (`BufferSnapshot`, `CursorByte`) and step 3b's orchestrator
    /// jointly enforce. The narration matters because the bootstrap-
    /// window race condition isn't deterministic at the daemon-e2e
    /// level (the inter-thread message-drain ordering on the
    /// receiver) — exercising the orchestrator's state machine
    /// directly makes the contract observable.
    #[test]
    fn bootstrap_window_keystrokes_round_trip_until_mirror_ready() {
        let fid = FrontendId(2);
        let id = BufferId::next();
        let mut m = BufferMirror::new(fid);

        // -----------------------------------------------------------
        // State 1: pre-bootstrap. Empty mirror; no buffers; no active
        // buffer; no cursor. Refinement 4 graceful-degradation kicks
        // in: keystrokes that would otherwise be optimistic must
        // fall through to FrontendEvent::Key.
        // -----------------------------------------------------------
        assert!(m.active_buffer().is_none());
        assert!(!m.is_ready(id));

        let ev = key_event(Key::Char('h'), Modifiers::NONE, fid);
        let result_1 = frontend_event_for_keystroke(&mut m, fid, ev);
        match result_1 {
            FrontendEvent::Key(_) => {} // expected — graceful fallback
            other => panic!("pre-bootstrap keystroke must round-trip via Key; got {other:?}"),
        }

        // -----------------------------------------------------------
        // State 2: BufferSnapshot processed. Mirror has CRDT state
        // for `id`, but the daemon hasn't yet emitted CursorByte —
        // active_buffer is still None. The orchestrator must still
        // round-trip because there's no active buffer to target.
        // -----------------------------------------------------------
        m.init_from_snapshot(id, &fresh_snapshot(99, "abc"))
            .expect("init from BufferSnapshot");
        assert!(m.is_ready(id));
        assert!(m.active_buffer().is_none()); // CursorByte hasn't fired yet

        let ev = key_event(Key::Char('i'), Modifiers::NONE, fid);
        let result_2 = frontend_event_for_keystroke(&mut m, fid, ev);
        match result_2 {
            FrontendEvent::Key(_) => {} // expected — no active_buffer
            other => panic!(
                "post-BufferSnapshot but pre-CursorByte keystroke must round-trip; \
                 got {other:?}"
            ),
        }

        // -----------------------------------------------------------
        // State 3: CursorByte processed. Mirror has active_buffer +
        // cursor byte position. The optimistic predicate can now
        // fire for in-scope keystrokes. Bootstrap is complete.
        // -----------------------------------------------------------
        m.set_cursor_byte_pos(id, 3); // cursor at end of "abc"
        assert_eq!(m.active_buffer(), Some(id));
        assert_eq!(m.cursor_byte_pos(id), Some(3));

        // -----------------------------------------------------------
        // State 4: post-bootstrap typing. Optimistic path active;
        // keystroke produces FrontendEvent::CrdtOp.
        // -----------------------------------------------------------
        let ev = key_event(Key::Char('j'), Modifiers::NONE, fid);
        let result_3 = frontend_event_for_keystroke(&mut m, fid, ev);
        match result_3 {
            FrontendEvent::CrdtOp {
                frontend_id,
                buffer_id,
                op,
            } => {
                assert_eq!(frontend_id, fid);
                assert_eq!(buffer_id, id);
                assert_eq!(op.peer_id, fid.0);
                assert!(!op.bytes.is_empty());
            }
            other => {
                panic!("post-bootstrap optimistic keystroke must produce CrdtOp; got {other:?}")
            }
        }

        // Mirror state reflects the optimistic apply.
        assert_eq!(m.materialize(id).as_deref(), Some("abcj"));
        assert_eq!(m.cursor_byte_pos(id), Some(4));
    }

    /// The canonical Day 3 echo-dedup test: a local op echoed back
    /// from the daemon (tagged with our `FrontendId`) must be skipped;
    /// a remote op (tagged with a different `FrontendId`) must apply.
    ///
    /// Symmetric coverage — single test exercises both filter
    /// directions so a one-sided filter bug (filters everything OR
    /// filters nothing) fails the test regardless of which way it
    /// breaks.
    #[test]
    fn echo_dedup_skips_own_op_but_applies_remote() {
        // Frontend A's FrontendId is 2; peer_id_from_frontend(2) == 2.
        let local_id = FrontendId(2);
        let remote_id = FrontendId(7);
        let buffer_id = BufferId::next();

        // Bootstrap: A's mirror initializes from a snapshot containing
        // "abc" (the daemon-side initial state).
        let snap = fresh_snapshot(0xABCD, "abc");
        let mut mirror = BufferMirror::new(local_id);
        mirror.init_from_snapshot(buffer_id, &snap).expect("init");
        assert_eq!(mirror.materialize(buffer_id).as_deref(), Some("abc"));

        // A types 'X' — apply_local_insert produces wire-format op
        // bytes attributable to A's peer_id.
        let local_op_bytes = mirror
            .apply_local_insert(buffer_id, 3, "X")
            .expect("local insert");
        assert_eq!(mirror.materialize(buffer_id).as_deref(), Some("abcX"));

        // Echo arrives: daemon broadcasts A's op back to A (tagged
        // with A's FrontendId). The filter must skip it.
        let outcome = apply_incoming_crdt_op(
            &mut mirror,
            local_id,
            local_id, // source == local → echo
            buffer_id,
            &local_op_bytes,
        )
        .expect("echo filter");
        assert_eq!(outcome, IncomingCrdtOpOutcome::SkippedEcho);

        // After echo: mirror unchanged (op was NOT applied a second
        // time). If the filter were broken and the op double-applied,
        // we'd see "abcXX" here.
        assert_eq!(
            mirror.materialize(buffer_id).as_deref(),
            Some("abcX"),
            "echoed own op must not double-apply"
        );

        // Now a remote edit from B (a different FrontendId) arrives.
        // Build a B-side replica that has integrated A's op + B's
        // own edit; we'll deliver B's op-since-A to A's mirror.
        let b_state = CrdtState::new(0xBEEF).expect("b new");
        b_state.import_snapshot(&snap).expect("b bootstrap");
        b_state
            .import_updates(&local_op_bytes)
            .expect("b sees A's op");
        let v_before_b_edit = b_state.version();
        b_state.insert(0, "Z").expect("b insert");
        let remote_op_bytes = b_state
            .export_updates_since(&v_before_b_edit)
            .expect("b op");

        let outcome = apply_incoming_crdt_op(
            &mut mirror,
            local_id,
            remote_id, // source != local → real remote op
            buffer_id,
            &remote_op_bytes,
        )
        .expect("remote apply");
        assert_eq!(outcome, IncomingCrdtOpOutcome::Applied);

        // After remote apply: B's "Z" prepended to A's mirror content.
        assert_eq!(
            mirror.materialize(buffer_id).as_deref(),
            Some("ZabcX"),
            "remote op must apply when source != local"
        );
    }

    /// **F1 gap pin.** The manual checklist originally told operators
    /// to undo with `C-x u`. That is the *wrong* keystroke for the
    /// per-frontend optimistic-undo path Scenario 2 tests: only the
    /// single-key forms (`Ctrl-4`, and — under Kitty enhanced mode —
    /// `Ctrl-/` / `Ctrl-_`) classify as `OptimisticAction::Undo`
    /// (frontend per-peer undo). `C-x` is a multi-key prefix the
    /// optimistic layer has no state for; it classifies `RoundTrip`
    /// and the sequence `C-x u` round-trips to the *daemon's* undo,
    /// which operates on the daemon's CRDT peer and cannot isolate a
    /// single frontend's edits.
    ///
    /// This pins the gap as a tested invariant rather than prose:
    /// if a future change made `C-x` optimistic, or de-classified
    /// `Ctrl-4`, this fails — and the checklist's `Ctrl-4`
    /// instruction (F1 fix) would silently become wrong again.
    #[test]
    fn f1_undo_keystroke_gap_cx_u_round_trips_only_single_key_is_optimistic() {
        // The keystroke the manual checklist (post-F1) and the PTY
        // test both use — reaches frontend per-peer undo.
        assert_eq!(
            classify_key(Key::Char('4'), Modifiers::CTRL),
            OptimisticAction::Undo,
            "Ctrl-4 must be the frontend per-peer optimistic undo \
             (raw-terminal-deliverable; what the checklist now uses)"
        );
        // Kitty-enhanced-mode forms — also optimistic undo (only
        // delivered when Kitty negotiation lands; v0.2).
        assert_eq!(
            classify_key(Key::Char('/'), Modifiers::CTRL),
            OptimisticAction::Undo
        );
        assert_eq!(
            classify_key(Key::Char('_'), Modifiers::CTRL),
            OptimisticAction::Undo
        );
        // `C-x` — the prefix of the OLD (wrong) checklist instruction
        // `C-x u`. Round-trips; the optimistic layer has no multi-key
        // prefix state, so `C-x u` can NEVER compose to frontend
        // per-peer undo — it reaches daemon undo, which Scenario 2's
        // per-frontend-isolation claim is not about.
        assert_eq!(
            classify_key(Key::Char('x'), Modifiers::CTRL),
            OptimisticAction::RoundTrip,
            "C-x must round-trip — it's the daemon-undo prefix, NOT \
             frontend per-peer undo; this is why the checklist had \
             to switch from C-x u to Ctrl-4 (F1)"
        );
        // The lone `u` after `C-x`, seen in isolation by the
        // stateless optimistic layer, is just text — confirming no
        // prefix-composition path to undo exists.
        assert_eq!(
            classify_key(Key::Char('u'), Modifiers::NONE),
            OptimisticAction::Insert('u'),
            "no multi-key prefix state: the 'u' in C-x u is plain \
             text to the optimistic layer; C-x u cannot be \
             frontend-undo by construction"
        );
    }
}
