What happens
One event can produce several identical notices. Two instances, both observed on the reference
machine during FR-UI-070's manual run (2026-08-27):
Missing file reference on project reload (step 15). One deleted .nam, two identical notices:
state.reference.not_found: The file "{display_name}" (hash {hash}) could not be found. (nam_02.nam (hash f3ee3a69…))
state.reference.not_found: The file "{display_name}" (hash {hash}) could not be found. (nam_02.nam (hash f3ee3a69…))
spawn_recall has two deliberate triggers — crates/namir-clap/src/state_ext.rs:61 when the host
loads state, and crates/namir-clap/src/audio.rs:178 as activation's replay. Both comments
anticipate both running ("replay onto it too"; "most hosts load state before the first
activate()"). Each pushes its own notice at crates/namir-clap/src/worker_jobs.rs:139, and nothing
deduplicates. The replay being idempotent does not make its reporting idempotent.
Device removal (step 8). Two app.audio_io.device_lost notices, one per direction — and
indistinguishable from each other, because {direction} is never substituted (#15).
Consequence
Compounds the undismissable-notice issue filed alongside this one: in the plugin these are two rows
that cannot be removed, not one.
Fix
Deduplicate on push — same code and same detail already present means no second row — or have
the recall report only on a state transition rather than on every replay. The device case wants the
direction rendered as well, which #15 covers.
Evidence
docs/manual-tests/fr-ui-070-non-modal-error-notices.md, executed run, finding 5.
What happens
One event can produce several identical notices. Two instances, both observed on the reference
machine during FR-UI-070's manual run (2026-08-27):
Missing file reference on project reload (step 15). One deleted
.nam, two identical notices:spawn_recallhas two deliberate triggers —crates/namir-clap/src/state_ext.rs:61when the hostloads state, and
crates/namir-clap/src/audio.rs:178as activation's replay. Both commentsanticipate both running ("replay onto it too"; "most hosts load state before the first
activate()"). Each pushes its own notice atcrates/namir-clap/src/worker_jobs.rs:139, and nothingdeduplicates. The replay being idempotent does not make its reporting idempotent.
Device removal (step 8). Two
app.audio_io.device_lostnotices, one per direction — andindistinguishable from each other, because
{direction}is never substituted (#15).Consequence
Compounds the undismissable-notice issue filed alongside this one: in the plugin these are two rows
that cannot be removed, not one.
Fix
Deduplicate on push — same
codeand samedetailalready present means no second row — or havethe recall report only on a state transition rather than on every replay. The device case wants the
direction rendered as well, which #15 covers.
Evidence
docs/manual-tests/fr-ui-070-non-modal-error-notices.md, executed run, finding 5.