Repository navigation
Proactive reminders 1/3: event reminders (approval waiting, failed, finished) in app and desktop #353
Copy link
Copy link
Closed
Labels
agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a templateMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a templateagent-workingAn agent has claimed this issue (the claim comment names the branch)An agent has claimed this issue (the claim comment names the branch)area:automationScheduled tasks and automationScheduled tasks and automationarea:uiWeb/desktop UI and copyWeb/desktop UI and copyenhancementNew feature or requestNew feature or request
Description
Why
FlyBot is passive today: the user has to open it to learn that an approval is waiting, a task failed, or a task finished. Phase 1 of proactive reminders gives the minimum useful loop without any new infrastructure.
Part of a 3-phase proactive-reminders track. Phase 2: scheduled tasks. Phase 3: 24/7 runtime and external channels. Related: #349 (Agent inbox board), #352 (deployment).
Scope
- Triggers (event-based): approval waiting (and waiting too long), task or Bot run failed, task finished, something newly assigned to me (team mode later).
- Delivery: in-app notification plus desktop notification. Each reminder links to the card or conversation that needs action.
- Controls: per-trigger on/off, quiet hours, merge repeated reminders into one, one-click mute from the reminder itself.
- Reason line: every reminder says why it fired (e.g. "waiting for your approval for 15 min").
- Safety: reminders only notify. They never execute actions; irreversible actions still go through approval.
- Personal vs team: personal mode covers my approvals and my Bots. Team mode must respect [Team] Gate cross-owner agent routes by per-Bot grants (default deny; superseded the publication gate) #51 grants and never remind someone about tasks they cannot see; the model reuses
assigner / owner / executingBotfrom [Feature RFC] Agent inbox board: one place for tasks, approvals and failures (personal first, team second) #349.
Acceptance
- Each of the 3 core triggers produces exactly one reminder per event, with a working link.
- Quiet hours and mute are respected; no duplicate spam after restart.
- No reminder text leaks content the user is not allowed to see.
- UI follows the guidelines in [Feature RFC] Agent inbox board: one place for tasks, approvals and failures (personal first, team second) #349 (one word per action, no native confirm dialogs, empty states and hints).
Out of scope
Scheduled or recurring tasks (phase 2), running while the app is closed (phase 3), Slack/email delivery (phase 3).
Process
Implementation via cloud OpenCode, review via Codex; bots do not hand-write code.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a templateMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a templateagent-workingAn agent has claimed this issue (the claim comment names the branch)An agent has claimed this issue (the claim comment names the branch)area:automationScheduled tasks and automationScheduled tasks and automationarea:uiWeb/desktop UI and copyWeb/desktop UI and copyenhancementNew feature or requestNew feature or request
Activity
Birfy commentedon Oct 19, 2026
Triage on main
7b9e90b, 2026-10-19 ~12:10 Asia/Shanghai: needs-human, not agent-ready. Question for the owner: start phase 1 (in-app + desktop reminders for approval waiting / failed / finished)? Also how it relates to the Agent inbox board (#349): one notification source for both, or separate?Birfy commentedon Oct 20, 2026
Triage (maintenance, 2026-10-20 08:04 Asia/Shanghai)
Checked on main
a45fc8c.Already on main
core/src/client/approval-notices.jsfires one notification per approval that starts waiting while the window is in the background or shows another chat; click opens that chat. Never asks for OS permission.Expected behavior
When one of my own Bots finishes or fails a turn, or an approval has waited too long, and I am not looking at that chat, I get one notification that says why ("Coder finished", "Coder failed: ", "Waiting for your approval for 15 min") and opens that chat on click. A notification only notifies: it never approves, rejects or sends anything.
First slice (smallest shippable step)
approval-notices.js(same rules: only when the window is in the background or shows another chat, only if the OS already allows notifications, one per event viatag) with finished and failed for my own Bots' chats.core/test/approval-notices.test.js; doc line indocs/subsystems/core-client.md.Details I decided (say if you disagree)
Question for the owner
Is this first slice OK: (a) desktop notifications for finished and failed, plus one Notifications switch, quiet hours later; (b) the same plus quiet hours and "waiting too long" now; or (c) wait and build it together with the #349 board?
Recommendation: (a).
Birfy commentedon Oct 20, 2026
Owner decision (2026-10-20): Confirmed option (a): first step only — add completion and failure notifications for the owner's own Bots, with a Notifications toggle in settings. Tapping a notification opens the matching chat (no approve-in-notification). Do-not-disturb and 'waiting too long' reminders come later.
Birfy commentedon Oct 20, 2026
Claimed by maintenance run (2026-10-20 08:55 Asia/Shanghai), branch
feat/353-finish-fail-notificationson Birfy/FlyBot, following the Owner decision above.Birfy commentedon Oct 20, 2026
Minor decisions for the first slice (PR #470), 2026-10-20 09:02 Asia/Shanghai:
{name} finished/{name} failed: <reason>; the reason is the failure's message, else its code (an AUTH message is never shown, as today), cut at 160 characters. Body: the group's name for a group turn, else empty — no reply text, so nothing private shows on a lock screen.prefs.notifications, on unless false), covering approvals too. Events while it is off stay "told", so switching it on brings no backlog.tag(ds-bot-turn-<session>:<turn>:<time>); the host keeps the last 20 ended turns in memory only, and a window skips anything older than its opening, so a restart repeats nothing.