Skip to content

feat(9.14.9b): shell-side item alerts — reminders fire with the app closed#108

Merged
th3-br41n merged 1 commit into
mainfrom
feat/9.14.9b-shell-reminders
Jul 7, 2026
Merged

feat(9.14.9b): shell-side item alerts — reminders fire with the app closed#108
th3-br41n merged 1 commit into
mainfrom
feat/9.14.9b-shell-reminders

Conversation

@th3-br41n

Copy link
Copy Markdown
Contributor

Closes the gap 9.14.9 left: due/scheduled task alerts and calendar event reminders ran on a 30s tick inside the app renderer, so nothing fired once the window closed. This hosts the same alerts in the main process on the existing automations SchedulerService — one fire mechanism product-wide, no new scheduling logic.

How it works

  • main/automations/item-alerts.ts (pure, +14 tests): Task/v1 + Event/v1 entity rows → one-shot alert registrations, mirroring the app-side semantics (midnight→09:00 task instants, deadline-wins same-instant collision, per-offset event reminders, base-occurrence recurrence fidelity). Dedupe keys replicate the SDK reminderDedupeKey shape.
  • AutomationsHost gains an optional postAlert port and routes item-alert fires to it (+4 wiring tests: fire w/ source appId+dedupeKey, event offset fire, live unregister on task completion, exactly-once).
  • The deployment derives alerts in hydrateFromEntities, re-derives on any Task/Event write (coalesced, same path as automation-entity writes), reconciles stale ids, and stays host-designation-gated — no multi-device double-fire.
  • index.ts posts through the shared UiNotifyHost under the source app's id (io.brainstorm.tasks / io.brainstorm.calendar), so when an app window is open and both schedulers fire, the host's (appId, dedupeKey) window collapses the duplicate. Calendar's in-app notify now passes due.dedupeKey (Tasks already did).

Posture notes

  • Alerts missed while the shell was closed do not back-fire (scheduler recomputes from now on vault open — same as Reminder/v1; a catch-up pass is a possible follow-up).
  • No new IPC or capability surface: entity reads ride the automations app's existing entities.read:*; postAlert is main-internal; DND/mute/dedupe all enforced by the existing notify host; titles are never persisted (registry stores only ids + fire configs).
  • Alert bodies are plain English from main (same as every existing main-posted notification — mentions, tail-truncation warnings); main-process i18n is a product-wide gap, not introduced here.

Verification

  • bun run verify green; full suite 14,636 passed (one FTS stress-budget flake under concurrent-run load, passes solo in 17s).
  • New e2e (tests/e2e/specs/item-alerts.spec.ts, passes in 1.1m): boot 1 provisions a task with a timed dueAt without ever opening Tasks; boot 2 just reopens the vault — the notification lands in the history attributed to io.brainstorm.tasks within a drain tick. Also proves the alert derives from persisted state across a restart.

Plan: harness docs/implementation-plan.md 9.14.9b ✅ (merged) — 0.1.9 scope row 1 of 2.

🤖 Generated with Claude Code

…h the app closed

9.14.9 shipped due/scheduled task alerts and event reminders in-window
only (a 30s tick inside the app renderer); nothing fired once the window
closed. This hosts the same alerts in the main process on the existing
automations SchedulerService — one fire mechanism product-wide:

- main/automations/item-alerts.ts (pure): Task/v1 + Event/v1 entity rows
  → one-shot alert registrations, mirroring the app-side semantics
  (midnight→09:00 task instants, deadline-wins collisions, per-offset
  event reminders, base-occurrence recurrence fidelity) with dedupe keys
  replicating the SDK reminderDedupeKey shape.
- AutomationsHost routes item-alert fires to a new optional postAlert
  port; wiring derives alerts in hydrateFromEntities, re-derives on
  Task/Event writes, reconciles stale ids; index.ts posts through the
  shared UiNotifyHost under the SOURCE app id, so the (appId, dedupeKey)
  window collapses duplicates when an app window is also open.
- Calendar now passes due.dedupeKey in its in-app notify (Tasks already
  did) so that collapse actually engages.
- e2e: provision a due task without ever opening Tasks, restart the
  shell, assert the notification lands attributed to io.brainstorm.tasks.

Alerts missed while the shell was closed do not back-fire — the
scheduler recomputes from now on vault open, the same posture as
Reminder/v1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@th3-br41n th3-br41n merged commit fa3e355 into main Jul 7, 2026
3 checks passed
@th3-br41n th3-br41n deleted the feat/9.14.9b-shell-reminders branch July 7, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant