Notifications & Nudges
Notification Memory & Reminders
Mining captured Android notifications into durable facts (via the #90 review queue) and time-bound reminders (via a dormant reminders table) — reusing nearly everything already built.
Situation
Android notifications have been captured as events since Wave 2a but used only passively for recall/briefing. This is the P3 "memory" slice of the Notification Intelligence track (Events→Reactions: P0 typed events, P2 triggers, P3 memory, P4 acting) — chosen first for highest immediate value and heaviest reuse of dormant infrastructure: the reminders table + helpers already exist with insertReminder having no caller, the briefing already surfaces reminders, Pebble timeline delivery is already wired, and the #90 facts pipeline and extractor pattern (runMemoryExtract) are proven.
A single new extraction pass (runNotificationExtract) splits each notification into durable facts (→ the reviewed #90 queue) and time-bound reminders (→ the reminders table, auto-active); the only genuinely new mechanism is a category-gated push cron firing at due time, since no due-time fire path exists today.
Key decisions
Facts stay reviewed; reminders go auto-active
Facts keep the #90 gate (proposed → Alex confirms) since they're durable and sensitive; reminders bypass manual review because a time-critical reminder can't wait for the app to be opened, and a wrong one is low-harm (one briefing line or push, dismissable).
category is orthogonal to the existing type column
reminders.type stays the legacy delivery-channel marker (alarm/timeline/notification, kept for the dormant helpers + Pebble path); a new category column (appointment/travel/delivery/payment/follow-up/other) is what actually gates push.
Category→delivery config, not per-item review
A KV-backed map defaults appointment/travel/payment to push and delivery/follow-up/other to brief-only, editable in /settings — this is what makes automatic delivery coherent without per-item friction.
Conservative due-date resolution
The model resolves relative/absolute times to an absolute Europe/London due_at; a reminder with no resolvable due is dropped (or surfaced as a fact instead) rather than guessed.
P0 typed events deliberately not built first
The extractor is LLM-driven and reasons over raw title/text directly; deterministic typing only pays for itself for rule-based trigger matching (P2), so it stays out of this slice.
Architecture
A new best-effort cron mines notification events into facts and reminders through existing pipelines; a second new cron adds the missing due-time push fire path.
runMemoryExtract — reads notification events since a high-water mark, calls a fast model for strict JSON {facts, reminders}, writes facts via insertMemory and reminders via insertReminder; never throws.source marker distinguishing notification-derived reminders; back-compat safe.pending reminders in the push-set within a lead window, firing via notify() and marking them fired — the status transition is the dedupe.getUpcomingReminders already surfaces all upcoming reminders — notification-derived ones appear automatically, no change needed.Risks & guardrails
Guessed due dates
Mitigated by dropping any reminder whose time can't be confidently resolved, rather than inventing a date.
Push noise from over-eager extraction
Mitigated by a conservative extraction prompt (mirrors runMemoryExtract's "skip transient/trivial/uncertain") and by defaulting most categories to brief-only rather than push.
Re-processing the same notifications repeatedly
A processed-event high-water mark (KV) prevents the extractor from re-mining notifications it has already seen each run.
Silent reminder writes without review
Accepted risk, explicitly reasoned through: reminders are time-bound and low-harm to get wrong (dismissable, one push/briefing line), unlike durable facts which keep the #90 gate.
Delivery
Migration + db layer
Migration 022 adds reminders.category (+ source); pure extraction/config/gate logic built under tests first.
Extract + push crons
runNotificationExtract and runReminderPush built and registered in the scheduled() dispatch.
Config route + settings UI
GET/POST reminder-config route plus a six-category push/brief editor in web /settings.
Verification + deploy
Full-suite + type-check verification; PR-only, D1 migration 022 required at deploy, held for Alex.
Out of scope
docs/superpowers/specs/2026-06-21-notification-memory-reminders-design.mdplan ·
docs/superpowers/plans/2026-06-21-notification-memory-reminders.md