title: Documentation, References, and Model Agent Use
version: 1.1
alwaysApply: true
scope: code, project-plans
---
# Directive on Documentation, References, and Model Agent Use in Code and Project Plans
To ensure clarity, efficiency, and high-value documentation within code and project plans—and to leverage **model agents** (AI- or automation-based assistants) effectively—contributors must follow these rules:
---
## 1. Documentation and References Must Add Clear Value
- Only include documentation, comments, or reference links when they provide *new, meaningful information* that assists understanding or decision-making.
- Avoid duplicating content already obvious in the codebase, version history, or linked project documents.
---
## 2. Eliminate Redundant or Noisy References
- Remove references that serve no purpose beyond filling space.
- Model agents may automatically flag and suggest removal of trivial references (e.g., links to unchanged boilerplate or self-evident context).
---
## 3. Explicit Role of Model Agents
Model agents are **active participants** in documentation quality control. Their tasks include:
- **Relevance Evaluation**: Automatically analyze references for their substantive contribution before inclusion.
- **Redundancy Detection**: Flag duplicate or trivial references across commits, files, or tasks.
- **Context Linking**: Suggest appropriate higher-level docs (designs, ADRs, meeting notes) when a code change touches multi-stage or cross-team items.
- **Placement Optimization**: Recommend centralization of references (e.g., in plan overviews, ADRs, or merge commit messages) rather than scattered low-value inline references.
- **Consistency Monitoring**: Ensure references align with team standards (e.g., ADR template, architecture repo, or external policy documents).
Contributors must treat agent recommendations as **first-pass reviews** but remain accountable for final human judgment.
---
## 4. Contextual References for Complex Items
- Use **centralized references** for multi-stage features (e.g., architectural docs, research threads).
- Model agents may auto-summarize complex chains of discussion and attach them as a single reference point.
---
## 5. Centralization of Broader Context
- Store overarching context (design docs, proposals, workflows) in accessible, well-indexed places.
- Model agents should assist by **generating reference maps** that track where docs are cited across the codebase.
---
## 6. Focused Documentation
- Documentation should explain **why** and **how** decisions are made, not just what was changed.
- Model agents can auto-generate first-pass explanations from commit metadata, diffs, and linked issues—but humans must refine them for accuracy and intent.
---
## 7. Review and Accountability
- Reviewers and team leads must reject submissions containing unnecessary or low-quality documentation.
- Model agent outputs are aids, not replacements—contributors remain responsible for **final clarity and relevance**.
---
## 8. Continuous Improvement and Agent Feedback Loops
- Encourage iterative development of model agents so their evaluations become more precise over time.
- Contributions should include **feedback on agent suggestions** (e.g., accepted, rejected, or corrected) to train better future outputs.
- Agents should log patterns of “rejected” suggestions for refinement.
G -->|Approves / Requests Revisions| H[Final Documentation]
G -->|Feedback on Agent Suggestions| B
```
---
✅ **Outcome:** By integrating disciplined contributor standards with **model agent augmentation**, the team achieves documentation that is consistently *relevant, concise, centralized, and decision-focused*. AI ensures coverage and noise reduction, while humans ensure precision and judgment.
TimeSafari will implement a **multi-platform notification system** that
TimeSafari will implement a **multi-platform notification system** that delivers **1-3 daily notifications** to keep users connected to gratitude, gifts, and collaborative projects. The system will work across **iOS, Android, Web, and Electron** platforms with **offline-first reliability** and **privacy-preserving architecture**.
delivers **1-3 daily notifications** to keep users connected to gratitude, gifts,
and collaborative projects. The system will work across **iOS, Android, Web,
and Electron** platforms with **offline-first reliability** and
**privacy-preserving architecture**.
### Business Value
### Business Value
@ -31,7 +27,6 @@ delivers **1-3 daily notifications** to keep users connected to gratitude, gifts
**Scope:** Multi-daily local notifications with online/offline flows
**Scope:** Multi-daily local notifications with online/offline flows
**Key Capabilities:**
**Key Capabilities:**
- **Local Notifications:** OS-level delivery on mobile/desktop
- **Local Notifications:** OS-level delivery on mobile/desktop
- **Web Push:** Service Worker-based notifications for web
- **Web Push:** Service Worker-based notifications for web
- **Offline Reliability:** Notifications fire even when app is closed
- **Offline Reliability:** Notifications fire even when app is closed
@ -44,7 +39,6 @@ delivers **1-3 daily notifications** to keep users connected to gratitude, gifts
**Scope:** Native background scheduling and enhanced capabilities
**Scope:** Native background scheduling and enhanced capabilities
- **This Summary:** High-level overview for executive decision-making
---
---
*This executive summary provides the essential business context and strategic
*This executive summary provides the essential business context and strategic direction for TimeSafari's notification system. For detailed technical specifications and implementation guidance, refer to the referenced documents.*
direction for TimeSafari's notification system. For detailed technical
specifications and implementation guidance, refer to the referenced documents.*
**Scope:** v1 (in‑app orchestrator) now; path to v2 (native plugin) next
**Scope:** v1 (in‑app orchestrator) now; path to v2 (native plugin) next
**Goal:** We **will deliver** 1..M local notifications/day with content
**Goal:** We **will deliver** 1..M local notifications/day with content **prefetched** so messages **will display offline**. We **will support** online‑first (API→DB→Schedule) with offline‑first fallback. The system **will enhance** TimeSafari's community-building mission by keeping users connected to gratitude, gifts, and collaborative projects through timely, relevant notifications.
**prefetched** so messages **will display offline**. We **will support**
online‑first (API→DB→Schedule) with offline‑first fallback. The system
> **Implementation Details:** See `notification-system-implementation.md` for detailed code, database schemas, and integration specifics.
**will enhance** TimeSafari's community-building mission by keeping users
> **Canonical Ownership:** This document owns Goals, Tenets, Platform behaviors, Acceptance criteria, and Test cases.
connected to gratitude, gifts, and collaborative projects through timely,
relevant notifications.
> **Implementation Details:** See `notification-system-implementation.md` for
detailed code, database schemas, and integration specifics.
> **Canonical Ownership:** This document owns Goals, Tenets, Platform
> behaviors, Acceptance criteria, and Test cases.
---
---
## 1) Versioning & Intent
## 1) Versioning & Intent
- **v1 (In‑App Orchestrator):** We **will implement** multi‑daily local
- **v1 (In‑App Orchestrator):** We **will implement** multi‑daily local notifications, online/offline flows, templating, SQLite persistence, and eventing **inside the app** using Capacitor Local Notifications.
notifications, online/offline flows, templating, SQLite persistence, and
- **v2 (Plugin):** We **will extract** adapters to a Capacitor/Native plugin to gain native schedulers (WorkManager/AlarmManager; BGTask+UNUserNotificationCenter), native HTTP, and native SQLite **with the same TypeScript API**.
eventing **inside the app** using Capacitor Local Notifications.
- **v2 (Plugin):** We **will extract** adapters to a Capacitor/Native plugin
to gain native schedulers (WorkManager/AlarmManager;
BGTask+UNUserNotificationCenter), native HTTP, and native SQLite **with the
same TypeScript API**.
> We **will retain** the existing web push + Service Worker foundation; the
> We **will retain** the existing web push + Service Worker foundation; the system **will add** reliable local scheduling on mobile and a unified API across platforms.
> system **will add** reliable local scheduling on mobile and a unified API
> across platforms.
---
---
## 2) Design Tenets
## 2) Design Tenets
- **Reliability:** OS‑level delivery once scheduled; no reliance on JS being alive
- **Reliability:** OS‑level delivery once scheduled; no reliance on JS being alive at fire time.
at fire time.
- **Freshness:** Prefer online‑first within a short prefetch window; degrade gracefully to cached content with TTL.
- **Freshness:** Prefer online‑first within a short prefetch window; degrade
- **Extractable:** Clean interfaces (Scheduler, DataStore, Callbacks) so v2 **will swap** adapters without API changes.
gracefully to cached content with TTL.
- **Simplicity:** One‑shot notifications per slot; rolling window scheduling to respect platform caps.
- **Extractable:** Clean interfaces (Scheduler, DataStore, Callbacks) so v2
> **Storage semantics:**`'shared'` = app DB; `'private'` = plugin-owned/native DB (v2). (No functional difference in v1.)
> DB (v2). (No functional difference in v1.)
> **Slot Identity & Scheduling Policy**
> **Slot Identity & Scheduling Policy**
> • **SlotId** uses canonical `HHmm` and remains stable across timezone
> • **SlotId** uses canonical `HHmm` and remains stable across timezone changes.
> changes.
> • **Lead window:** default `prefetchLeadMinutes = 20`; no retries once inside the lead.
> • **Lead window:** default `prefetchLeadMinutes = 20`; no retries once inside
> • **TTL policy:** When offline and content is beyond TTL, **we will skip** the notification (no "(cached)" suffix).
the lead.
> • **Idempotency:** Duplicate "scheduled" deliveries are prevented by a unique index on `(slot_id, fire_at, status='scheduled')`.
> • **TTL policy:** When offline and content is beyond TTL, **we will skip** the
> • **Time handling:** Slots will follow **local wall-clock** time across TZ/DST; `slotId=HHmm` stays constant and we will **recompute fire times** on offset change.
notification (no "(cached)" suffix).
> • **Idempotency:** Duplicate "scheduled" deliveries are prevented by a unique
index on `(slot_id, fire_at, status='scheduled')`.
> • **Time handling:** Slots will follow **local wall-clock** time across TZ/DST;
`slotId=HHmm` stays constant and we will **recompute fire times** on offset change.
---
---
## 5) Data Model & Retention (SQLite)
## 5) Data Model & Retention (SQLite)
**Tables:** `notif_contents`, `notif_deliveries`, `notif_config` (see
**Tables:** `notif_contents`, `notif_deliveries`, `notif_config` (see Implementation document for complete schema)
Implementation document for complete schema)
**Retention:** We **will keep** ~14 days of contents/deliveries (configurable)
**Retention:** We **will keep** ~14 days of contents/deliveries (configurable) and **will prune** via a simple daily job that runs on app start/resume. We **will prune** daily but **will not** VACUUM by default on mobile; disk compaction is deferred.
and **will prune** via a simple daily job that runs on app start/resume. We
**will prune** daily but **will not** VACUUM by default on mobile; disk
compaction is deferred.
**Payload handling:** We **will template**`{title, body}`**before** scheduling;
**Payload handling:** We **will template**`{title, body}`**before** scheduling; we **will not** mutate at delivery time.
we **will not** mutate at delivery time.
---
---
## 6) Scheduling Policy & Slot Math
## 6) Scheduling Policy & Slot Math
- **One‑shot per slot** per day (non‑repeating).
- **One‑shot per slot** per day (non‑repeating).
- **Rolling window:** today's remaining slots; seed tomorrow where platform
- **TZ/DST safe:** We **will recompute** local wall‑times on app resume and whenever timezone/offset changes; then **reschedule**.
- **TZ/DST safe:** We **will recompute** local wall‑times on app resume and
- **Android exactness:** If exact alarms are unavailable or denied, we **will use**`setWindow` semantics via the scheduler adapter.
whenever timezone/offset changes; then **reschedule**.
- **iOS pending cap:** We **will keep** pending locals within typical caps (~64) by limiting the window and canceling/re‑arming as needed.
- **Android exactness:** If exact alarms are unavailable or denied, we
- **Electron rolling window:** On Electron we **will schedule** the **next occurrence per slot** by default; depth (today+tomorrow) **will be** enabled only when auto-launch is on, to avoid drift while the app is closed.
**will use** `setWindow` semantics via the scheduler adapter.
- **iOS pending cap:** We **will keep** pending locals within typical caps (~64)
by limiting the window and canceling/re‑arming as needed.
- **Electron rolling window:** On Electron we **will schedule** the **next
occurrence per slot** by default; depth (today+tomorrow) **will be** enabled only
when auto-launch is on, to avoid drift while the app is closed.
---
---
## 7) Timing & Network Requirements
## 7) Timing & Network Requirements
**Summary:** The notification system uses lightweight, ETag-aware content
**Summary:** The notification system uses lightweight, ETag-aware content fetching with single attempts inside lead windows. All timing constants and detailed network policies are defined in the Implementation document.
fetching with single attempts inside lead windows. All timing constants and
detailed network policies are defined in the Implementation document.
**Key Policies:**
**Key Policies:**
- **Lead policy:** The lead window governs **online-first fetch attempts**, not
- **Lead policy:** The lead window governs **online-first fetch attempts**, not arming. We **will arm** locals **whenever the app runs**, using the freshest available payload.
arming. We **will arm** locals **whenever the app runs**, using the freshest
- **TTL policy:** If offline and content is beyond TTL, we will **skip** the notification (no "cached" suffix).
available payload.
- **Idempotency:** Duplicate "scheduled" rows are prevented by a unique index on `(slot_id, fire_at, status='scheduled')`.
- **TTL policy:** If offline and content is beyond TTL, we will **skip** the
- **Wall-clock rule:** Slots will follow **local wall-clock** across TZ/DST; `slotId=HHmm` stays constant and we will **recompute fire times** on offset change.
notification (no "cached" suffix).
- **Resume debounce:** On app resume/open we will **debounce** pipeline entry points by **30s** per app session to avoid burst fetches.
- **Idempotency:** Duplicate "scheduled" rows are prevented by a unique index on
- **No scheduled background network in v1 (mobile):** Local notifications **will deliver offline once armed**, but **we will not** run timed network jobs when the app is terminated. **Network prefetch will occur only while the app is running** (launch/resume/inside lead). Server-driven push (Web SW) and OS background schedulers are a **v2** capability.
`(slot_id, fire_at, status='scheduled')`.
- **Wall-clock rule:** Slots will follow **local wall-clock** across TZ/DST;
`slotId=HHmm` stays constant and we will **recompute fire times** on offset change.
- **Resume debounce:** On app resume/open we will **debounce** pipeline
entry points by **30s** per app session to avoid burst fetches.
- **No scheduled background network in v1 (mobile):** Local notifications
**will deliver offline once armed**, but **we will not** run timed network jobs
when the app is terminated. **Network prefetch will occur only while the app is
running** (launch/resume/inside lead). Server-driven push (Web SW) and OS
background schedulers are a **v2** capability.
**Platform-Specific Network Access:**
**Platform-Specific Network Access:**
@ -171,18 +118,9 @@ background schedulers are a **v2** capability.
**Optional Background Prefetch (v1):**
**Optional Background Prefetch (v1):**
- **Background Runner (optional, v1):** We **will integrate** Capacitor's
- **Background Runner (optional, v1):** We **will integrate** Capacitor's Background Runner to **opportunistically prefetch** content on iOS/Android when the OS grants background time. This **will not** provide clock-precise execution and **will not** run after user-terminate on iOS. It **will not** be treated as a scheduler. We **will continue** to *arm* local notifications via our rolling window regardless of Runner availability. When Runner fires near a slot (inside `prefetchLeadMinutes`), it **will** refresh content (ETag, 12s timeout) and, behind a flag, **may** cancel & re-arm that slot with the fresh template if within TTL. If no budget or failure, the previously armed local **will** still deliver.
Background Runner to **opportunistically prefetch** content on iOS/Android when
the OS grants background time. This **will not** provide clock-precise execution
and **will not** run after user-terminate on iOS. It **will not** be treated as
a scheduler. We **will continue** to *arm* local notifications via our rolling
window regardless of Runner availability. When Runner fires near a slot (inside
`prefetchLeadMinutes`), it **will** refresh content (ETag, 12s timeout) and,
behind a flag, **may** cancel & re-arm that slot with the fresh template if within
TTL. If no budget or failure, the previously armed local **will** still deliver.
**Implementation Details:** See Implementation document for complete timing
**Implementation Details:** See Implementation document for complete timing constants table, network request profiles, and platform-specific enforcement.
constants table, network request profiles, and platform-specific enforcement.
- **Category ID**: `TS_DAILY` with default `OPEN` action
- **Category ID**: `TS_DAILY` with default `OPEN` action
- **Background budget** is short and OS‑managed; any prefetch work
- **Background budget** is short and OS‑managed; any prefetch work **will complete** promptly.
**will complete** promptly.
- **Mobile local notifications will route via action listeners (not the service worker)**.
- **Mobile local notifications will route via action listeners (not the service worker)**.
- Background Runner **will** offer **opportunistic** network wake (no guarantees;
- Background Runner **will** offer **opportunistic** network wake (no guarantees; short runtime; iOS will not run after force-quit). Locals **will** still deliver offline once armed.
short runtime; iOS will not run after force-quit). Locals **will** still deliver
offline once armed.
**Android**
**Android**
- Exact alarms on **API 31+** may require `SCHEDULE_EXACT_ALARM`. If exact access
- Exact alarms on **API 31+** may require `SCHEDULE_EXACT_ALARM`. If exact access is missing on API 31+, we will use a **windowed trigger (default ±10m)** and surface a settings deep-link.
is missing on API 31+, we will use a **windowed trigger (default ±10m)** and
surface a settings deep-link.
- **We will deep-link users to the exact-alarm settings when we detect denials.**
- **We will deep-link users to the exact-alarm settings when we detect denials.**
- **Channel defaults**: ID `timesafari.daily`, name "TimeSafari Daily",
- **Channel defaults**: ID `timesafari.daily`, name "TimeSafari Daily", importance=high (IDs never change)
importance=high (IDs never change)
- Receivers for reboot/time change **will be handled** by v2 (plugin); in v1, re‑arming **will occur** on app start/resume.
- Receivers for reboot/time change **will be handled** by v2 (plugin); in v1,
re‑arming **will occur** on app start/resume.
- **Mobile local notifications will route via action listeners (not the service worker)**.
- **Mobile local notifications will route via action listeners (not the service worker)**.
- Background Runner **will** offer **opportunistic** network wake (no guarantees;
- Background Runner **will** offer **opportunistic** network wake (no guarantees; short runtime; iOS will not run after force-quit). Locals **will** still deliver offline once armed.
short runtime; iOS will not run after force-quit). Locals **will** still deliver
offline once armed.
**Web**
**Web**
- Requires registered Service Worker + permission; can deliver with browser closed.
- Requires registered Service Worker + permission; can deliver with browser closed. **Web will not offline-schedule**.
**Web will not offline-schedule**.
- Service Worker click handlers are for **web push only**; **mobile locals bypass the SW**.
- Service Worker click handlers are for **web push only**;
- SW examples use `/sw.js` as a placeholder; **wire this to your actual build output path** (e.g., `sw_scripts/notification-click.js` or your combined bundle).
**mobile locals bypass the SW**.
- **Note**: Service workers are **intentionally disabled** in Electron (`src/main.electron.ts`) and web uses VitePWA plugin for minimal implementation.
- SW examples use `/sw.js` as a placeholder; **wire this to your actual build
output path** (e.g., `sw_scripts/notification-click.js` or your combined bundle).
- **Note**: Service workers are **intentionally disabled** in Electron
(`src/main.electron.ts`) and web uses VitePWA plugin for minimal implementation.
**Electron**
**Electron**
- We **will use** native OS notifications with **best-effort scheduling while the
- We **will use** native OS notifications with **best-effort scheduling while the app is running**; true background scheduling will be addressed in v2 (native bridges).
app is running**; true background scheduling will be addressed in v2 (native bridges).
We **will deliver** desktop notifications while the Electron app is running. True
We **will deliver** desktop notifications while the Electron app is running. True **background scheduling when the app is closed** is **out of scope for v1** and **will be addressed** in v2 via native bridges. We **will adopt** one of the following options (in order of fit to our codebase):
**background scheduling when the app is closed** is **out of scope for v1** and
**will be addressed** in v2 via native bridges. We **will adopt** one of the
following options (in order of fit to our codebase):
**In-app scheduler + auto-launch (recommended now):** Keep the orchestrator in
**In-app scheduler + auto-launch (recommended now):** Keep the orchestrator in the main process, **start on login** (tray app, hidden window), and use the **Electron `Notification` API** for delivery. This requires no new OS services and aligns with our PlatformServiceFactory/mixin patterns.
the main process, **start on login** (tray app, hidden window), and use the
**Electron `Notification` API** for delivery. This requires no new OS services
and aligns with our PlatformServiceFactory/mixin patterns.
**Policy (v1):** If the app is **not running**, Electron will **not** deliver
**Policy (v1):** If the app is **not running**, Electron will **not** deliver scheduled locals. With **auto-launch enabled**, we **will achieve** near-mobile parity while respecting OS sleep/idle behavior.
scheduled locals. With **auto-launch enabled**, we **will achieve** near-mobile
parity while respecting OS sleep/idle behavior.
**UX notes:** On Windows we **will set**`appUserModelId` so toasts are
**UX notes:** On Windows we **will set**`appUserModelId` so toasts are attributed correctly; on macOS we **will request** notification permission on first use.
attributed correctly; on macOS we **will request** notification permission on
first use.
**Prerequisites:** We **will require** Node 18+ (global `fetch`) or we
**Prerequisites:** We **will require** Node 18+ (global `fetch`) or we **will polyfill** via `undici` for content fetching in the main process.
**will polyfill** via `undici` for content fetching in the main process.
**Limits:** Title ≤ 50 chars; Body ≤ 200 chars; truncate with ellipsis.
**Limits:** Title ≤ 50 chars; Body ≤ 200 chars; truncate with ellipsis.
**Fallback:** Missing token → `"[Content]"`.
**Fallback:** Missing token → `"[Content]"`.
**Mutation:** We **will** render templates **before** scheduling; no mutation at
**Mutation:** We **will** render templates **before** scheduling; no mutation at delivery time on iOS locals.
delivery time on iOS locals.
---
## 9) Integration with Existing TimeSafari Infrastructure
## 10) Integration with Existing TimeSafari Infrastructure
**Database:** We **will integrate** with existing migration system in
`src/db-sql/migration.ts` following the established `MIGRATIONS` array pattern
**Database:** We **will integrate** with existing migration system in `src/db-sql/migration.ts` following the established `MIGRATIONS` array pattern
**Settings:** We **will extend** existing Settings type in
**Settings:** We **will extend** existing Settings type in `src/db/tables/settings.ts` following the established type extension pattern
`src/db/tables/settings.ts` following the established type extension pattern
**Platform Service:** We **will leverage** existing PlatformServiceMixin database utilities following the established mixin pattern
**Platform Service:** We **will leverage** existing PlatformServiceMixin database
**Service Factory:** We **will follow** the existing `PlatformServiceFactory` singleton pattern for notification service creation
utilities following the established mixin pattern
**Capacitor:** We **will integrate** with existing deep link system in `src/main.capacitor.ts` following the established initialization pattern
**Service Factory:** We **will follow** the existing `PlatformServiceFactory`
**Service Worker:** We **will extend** existing service worker infrastructure following the established `sw_scripts/` pattern (Note: Service workers are intentionally disabled in Electron and have minimal web implementation via VitePWA plugin)
singleton pattern for notification service creation
**API:** We **will use** existing error handling from `src/services/api.ts` following the established `handleApiError` pattern
**Capacitor:** We **will integrate** with existing deep link system in
**Logging:** We **will use** existing logger from `src/utils/logger` following the established logging patterns
`src/main.capacitor.ts` following the established initialization pattern
**Service Worker:** We **will extend** existing service worker infrastructure
**Vue Architecture:** We **will follow** Vue 3 + vue-facing-decorator patterns for component integration (Note: The existing `useNotifications` composable in `src/composables/useNotifications.ts` is currently stub functions with eslint-disable comments and needs implementation)
following the established `sw_scripts/` pattern (Note: Service workers are
**State Management:** We **will integrate** with existing settings system via `PlatformServiceMixin.$saveSettings()` for notification preferences (Note: TimeSafari uses PlatformServiceMixin for all state management, not Pinia stores)
intentionally disabled in Electron and have minimal web implementation via
**Identity System:** We **will integrate** with existing `did:ethr:` (Ethereum-based DID) system for user context
VitePWA plugin)
**API:** We **will use** existing error handling from `src/services/api.ts`
following the established `handleApiError` pattern
**Logging:** We **will use** existing logger from `src/utils/logger` following
the established logging patterns
**Platform Detection:** We **will use** existing `process.env.VITE_PLATFORM`
patterns (`web`, `capacitor`, `electron`)
**Vue Architecture:** We **will follow** Vue 3 + vue-facing-decorator patterns
for component integration (Note: The existing `useNotifications` composable in
`src/composables/useNotifications.ts` is currently stub functions with
eslint-disable comments and needs implementation)
**State Management:** We **will integrate** with existing settings system via
`PlatformServiceMixin.$saveSettings()` for notification preferences (Note:
TimeSafari uses PlatformServiceMixin for all state management, not Pinia stores)
**Identity System:** We **will integrate** with existing `did:ethr:`
(Ethereum-based DID) system for user context
**Testing:** We **will follow** Playwright E2E testing patterns established in TimeSafari
**Testing:** We **will follow** Playwright E2E testing patterns established in TimeSafari
**Database Architecture:** We **will support** platform-specific database backends:
**Database Architecture:** We **will support** platform-specific database backends:
@ -305,87 +200,64 @@ TimeSafari uses PlatformServiceMixin for all state management, not Pinia stores)
- **Android (no exact access):** observed delivery is within **±10 min** of slot time.
occurs; if fetch completes within **12s** → content updated; otherwise offline
- **Web push:** SW push event fetch runs once with **12s** timeout; if it times out, the push still displays (from payload).
policy applies.
- **Electron (app running):** timer-based locals fire on time; on reboot with **Start on Login**, orchestrator re-arms on first run.
- **Android (no exact access):** observed delivery is within **±10 min** of slot
time.
- **Web push:** SW push event fetch runs once with **12s** timeout; if it times
out, the push still displays (from payload).
- **Electron (app running):** timer-based locals fire on time; on reboot with
**Start on Login**, orchestrator re-arms on first run.
- **TTL behavior:** offline & stale → **skip** (no notification posted).
- **TTL behavior:** offline & stale → **skip** (no notification posted).
- **ETag path:** with `304`, last payload remains; no duplicate scheduling rows
- **ETag path:** with `304`, last payload remains; no duplicate scheduling rows (unique index enforced).
(unique index enforced).
- **Cooldown:** calling `deliverStoredNow` twice within **60s** for same slot doesn't produce two notifications.
- **Cooldown:** calling `deliverStoredNow` twice within **60s** for same slot
- **Closed app, armed earlier** → locals fire at slot; title/body match last rendered content (proves "render at schedule time" + adapter API).
doesn't produce two notifications.
- **Closed app, timezone change before slot** → on next resume, app recomputes and re-arms; already armed notifications will still fire on original wall-time
- **Closed app, armed earlier** → locals fire at slot; title/body match last
- **Mobile closed-app, no background network:** Arm at T–hours; kill app; verify locals fire with last rendered text; confirm **no** network egress at delivery.
rendered content (proves "render at schedule time" + adapter API).
- **Web push as network scheduler:** Send push with empty payload → SW fetches within 12s timeout → shows correct text; confirm behavior with browser closed.
- **Closed app, timezone change before slot** → on next resume, app recomputes
- **Electron app not running:** No delivery; with **Start on Login**, after reboot first run fetches and re-arms; subsequent slots fire.
and re-arms; already armed notifications will still fire on original wall-time
- **Runner fires in background (Android/iOS):** With Runner enabled and app backgrounded for ≥30 min, at least one prefetch **will** occur; content cache **will** update; already-armed locals **will** still fire on time.
- **Mobile closed-app, no background network:** Arm at T–hours; kill app; verify
- **Runner re-arm (flagged):** If `runnerRearm=true` and Runner fires inside lead with fresh content + within TTL, the system **will** cancel & re-arm the next slot; delivered text **will** match fresh template.
locals fire with last rendered text; confirm **no** network egress at delivery.
- **Web push as network scheduler:** Send push with empty payload → SW fetches
within 12s timeout → shows correct text; confirm behavior with browser closed.
- **Electron app not running:** No delivery; with **Start on Login**, after
reboot first run fetches and re-arms; subsequent slots fire.
- **Runner fires in background (Android/iOS):** With Runner enabled and app
backgrounded for ≥30 min, at least one prefetch **will** occur; content cache
**will** update; already-armed locals **will** still fire on time.
- **Runner re-arm (flagged):** If `runnerRearm=true` and Runner fires inside lead
with fresh content + within TTL, the system **will** cancel & re-arm the next
slot; delivered text **will** match fresh template.
---
---
## 15) Test Matrix (Essentials)
## 16) Test Matrix (Essentials)
- **Android:** exact vs inexact branch, Doze/App Standby behavior, reboot/time
- **Android:** exact vs inexact branch, Doze/App Standby behavior, reboot/time change, permission denial path, deep‑link to exact‑alarm settings.
change, permission denial path, deep‑link to exact‑alarm settings.
- **iOS:** BG fetch budget limits, pending cap windowing, local notification delivery with app terminated, category actions.
- **iOS:** BG fetch budget limits, pending cap windowing, local notification
- **Web:** SW lifecycle, push delivery with app closed, click handling, no offline scheduling.
*This strategic plan focuses on features and future‑tense deliverables, avoids implementation details, and preserves a clear path from the in‑app orchestrator (v1) to native plugin (v2). For executive overview, see `notification-system-executive-summary.md`. For complete implementation details, see `notification-system-implementation.md`.*
*This strategic plan focuses on features and future‑tense deliverables, avoids implementation details, and preserves a clear path from the in‑app orchestrator (v1) to native plugin (v2).*