//! Scroll validation matrix. //! //! The scroll matrix drives the pager binary in a PTY with //! `KIGI_SCROLL_LOG` pointed at a tempfile, then validates the pager's //! flight-recorder JSONL (producer: //! `kigi-tui/src/input/scroll_log.rs`) against gesture invariants. //! //! Layers (per-cell flow, executed by [`runner::run_cell`]): //! [`session`] spawns the primed pager → the cell's [`gestures`] table is //! replayed as timed SGR reports → [`log`] parses and groups the recorder //! JSONL (finalize-synchronized, no fixed sleeps) → the cell's //! [`invariants`] judge the [`cells`] row's verdict, xfail-aware, and //! [`report`] renders the verdicts (table, `report.json`, exit code). //! Entry points: the curated CI tier (`tests/scroll_matrix_curated.rs`) and //! the local full sweep (`src/bin/scroll_matrix.rs`). //! //! ## No pager dependency //! //! The harness reaches the pager **only** through the spawned binary //! (`PAGER_BINARY` / `env::pager_binary`); this module re-declares the wire //! schema instead of importing pager types. That duplication is deliberate: //! [`log::ScrollLogLine`] keeps every always-emitted producer field //! **required**, so a rename/removal on the pager side fails deserialization //! loudly here (schema-drift tripwire), while unknown fields are tolerated //! so additive producer changes don't break older matrix code. The //! producer-side twin lives in `kigi-tui/src/input/mouse/tests.rs` //! (wire-format fixture test asserting the same key set on raw JSON). pub mod cells; pub mod gestures; pub mod invariants; pub mod log; pub mod report; pub mod runner; pub mod session; pub use cells::{CELLS, ExpectedProfile, MatrixCell, Tier, curated}; pub use gestures::{GestureId, WheelStep, direction_counts}; pub use invariants::{InvariantId, InvariantResult, check_log_invariant}; pub use log::{ EVT_FINALIZE, EVT_FLUSH, EVT_STREAM_START, ScrollLogLine, StreamGroup, group_streams, parse_jsonl, parse_jsonl_str, wait_for_finalize_count, }; pub use report::{ CellReport, CellStatus, InvariantReport, InvariantStatus, exit_code, summary_table, write_report_json, }; pub use runner::run_cell; pub use session::{ SessionKind, marker_line, marker_response, marker_screen_row, spawn_marker_session, spawn_settled_marker_session, spawn_streaming_marker_session, topmost_visible_marker, };