refactor: Pre-phase-6 review cleanup.
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled

- Propagate serialization errors in output path
instead of unwrap_or_default() silently writing
blank lines (main.rs, handler.rs).
- Cap selection undo stack at 50 entries to bound
memory on heavy multi-select usage (menu.rs).
- Break TUI event loop on dead action channel
instead of silently dropping keypresses (lib.rs).
- Log dropped handler hook events when channel is
full (handler.rs).
- Reject menu and headless DSL tests that have no
assertions at compile time (codegen.rs).
- Document filter_text ownership design in TUI and
exec/handler error asymmetry in CompositeHandler.
This commit is contained in:
2026-03-14 15:26:31 -04:00
parent 8077469d19
commit cd1927fa9f
5 changed files with 57 additions and 12 deletions

View File

@@ -71,12 +71,21 @@ async fn run_inner(
// Send initial resize
let size = terminal.size()?;
let list_height = size.height.saturating_sub(1);
let _ = action_tx
if action_tx
.send(Action::Resize {
height: list_height,
})
.await;
.await
.is_err()
{
tracing::warn!("core channel closed before TUI started");
return Ok(());
}
// Local copy of filter text for immediate cursor positioning.
// Synced from core on every StateChanged. Core is the source
// of truth: if IPC or a hook changes the filter, the next
// broadcast overwrites this.
let mut filter_text = String::new();
let mut view_state: Option<ViewState> = None;
let mut event_stream = EventStream::new();
@@ -124,12 +133,16 @@ async fn run_inner(
mode = *m;
pending = PendingKey::None;
}
let _ = action_tx.send(action).await;
if action_tx.send(action).await.is_err() {
break; // core is gone
}
}
}
Event::Resize(_, h) => {
let list_height = h.saturating_sub(1);
let _ = action_tx.send(Action::Resize { height: list_height }).await;
if action_tx.send(Action::Resize { height: list_height }).await.is_err() {
break;
}
}
_ => {}
}