feat: live SSE updates for the SYST3M reminders section

Add RemindersChanged SSE event so the pending-reminders list in the
SYST3M tab updates live without polling.

Backend emission sites (every path that mutates the reminders table):
- agent_server: store_remind (remind MCP call)
- dashboard.rs: post_cancel_reminder, post_retry_reminder
- questions.rs: cancel_loose_end Reminder kind
- reminder_scheduler: after each delivery batch (any_delivered)

Coordinator gets emit_reminders_snapshot() mirroring the existing
emit_schedules_snapshot() pattern: lists PendingReminder rows from the
broker and emits DashboardEvent::RemindersChanged.

Frontend: applyRemindersChanged(ev) calls renderReminders(ev.reminders)
and is registered as reminders_changed in MUTATION_HANDLERS.

Docs: dashboard.md reminders_changed entry; CLAUDE.md file map updated.
This commit is contained in:
iris 2026-06-05 10:13:16 +02:00 committed by mara
commit a1e46e2b3d
9 changed files with 55 additions and 1 deletions

View file

@ -202,6 +202,14 @@ pub enum DashboardEvent {
seq: u64,
schedules: Vec<hive_sh4re::WireSchedule>,
},
/// Full snapshot of all pending reminders. Emitted after every
/// reminder mutation: agent `remind` calls, operator cancel / retry,
/// and the scheduler tick after each delivery batch. Lets the
/// dashboard's reminders section stay live without polling.
RemindersChanged {
seq: u64,
reminders: Vec<crate::broker::PendingReminder>,
},
}
impl DashboardEvent {
@ -233,6 +241,7 @@ impl DashboardEvent {
DashboardEvent::MetaUpdateRunning { .. } => "meta_update_running",
DashboardEvent::RebuildQueueChanged { .. } => "rebuild_queue_changed",
DashboardEvent::SchedulesChanged { .. } => "schedules_changed",
DashboardEvent::RemindersChanged { .. } => "reminders_changed",
}
}
}
@ -355,6 +364,10 @@ mod tests {
seq: 1,
schedules: Vec::new(),
},
DashboardEvent::RemindersChanged {
seq: 1,
reminders: Vec::new(),
},
];
for ev in samples {
let v: serde_json::Value = serde_json::to_value(&ev).expect("serialise");