What happens
In the CLAP plugin, some notices can never be dismissed. The Dismiss button sits beyond the right
edge of the editor, and the editor cannot be widened. Since nothing else removes a notice, the row
stays for the lifetime of the plugin instance, permanently occupying part of a screen that already
cannot show every FR-UI-020 element at once.
Observed in Reaper on the reference machine during FR-UI-070's manual run (2026-08-27), step 14.
Cause — four choices, each defensible alone
- The row does not wrap.
crates/namir-ui/src/notices.rs:28 lays each notice out as
ui.horizontal, label first and button after. An egui horizontal layout does not wrap, so a long
label pushes the button past the edge.
- The editor cannot be resized.
crates/namir-clap/src/gui.rs:87 fixes GUI_WIDTH/GUI_HEIGHT
at 960x640 and :196 returns can_resize() == false, deliberately — FR-CLAP-110 (host-driven
resize) is a Should that was scoped out. So the standalone's escape hatch, widening the window,
does not exist.
- Notices never expire.
push_notice appends to an unbounded Vec in both shells
(crates/namir-app/src/host.rs:208, crates/namir-clap/src/shared.rs:212) and Dismiss is the
only removal path (:456 / :220). No expiry, no severity-based timeout, no cap.
- The text is about twice as long as it needs to be, because the code and message are rendered
twice on several paths — filed separately as the duplication issue.
Nobody chose the outcome; it is the composition. Notably (4), which looks like a presentation defect
in isolation, is what makes (1) bite.
Fix
Either half prevents it:
- Pin
Dismiss so it is always on screen — a right-to-left layout for the button, or draw it before
the label.
- Let the label wrap or truncate with the full text on hover.
Bounding or expiring the notice list (3) is a separate improvement worth considering on its own: an
unbounded list of undismissable rows can in principle consume the whole editor.
Evidence
docs/manual-tests/fr-ui-070-non-modal-error-notices.md, executed run, finding 7 — and step 6 of the
same script passes in the standalone, where the button is reachable, which isolates the cause to the
fixed editor rather than to the dismissal logic.
What happens
In the CLAP plugin, some notices can never be dismissed. The
Dismissbutton sits beyond the rightedge of the editor, and the editor cannot be widened. Since nothing else removes a notice, the row
stays for the lifetime of the plugin instance, permanently occupying part of a screen that already
cannot show every FR-UI-020 element at once.
Observed in Reaper on the reference machine during FR-UI-070's manual run (2026-08-27), step 14.
Cause — four choices, each defensible alone
crates/namir-ui/src/notices.rs:28lays each notice out asui.horizontal, label first and button after. An egui horizontal layout does not wrap, so a longlabel pushes the button past the edge.
crates/namir-clap/src/gui.rs:87fixesGUI_WIDTH/GUI_HEIGHTat 960x640 and
:196returnscan_resize() == false, deliberately — FR-CLAP-110 (host-drivenresize) is a Should that was scoped out. So the standalone's escape hatch, widening the window,
does not exist.
push_noticeappends to an unboundedVecin both shells(
crates/namir-app/src/host.rs:208,crates/namir-clap/src/shared.rs:212) andDismissis theonly removal path (
:456/:220). No expiry, no severity-based timeout, no cap.twice on several paths — filed separately as the duplication issue.
Nobody chose the outcome; it is the composition. Notably (4), which looks like a presentation defect
in isolation, is what makes (1) bite.
Fix
Either half prevents it:
Dismissso it is always on screen — a right-to-left layout for the button, or draw it beforethe label.
Bounding or expiring the notice list (3) is a separate improvement worth considering on its own: an
unbounded list of undismissable rows can in principle consume the whole editor.
Evidence
docs/manual-tests/fr-ui-070-non-modal-error-notices.md, executed run, finding 7 — and step 6 of thesame script passes in the standalone, where the button is reachable, which isolates the cause to the
fixed editor rather than to the dismissal logic.