diff --git a/.cursor/rules/docs/documentation_references_model_agents.mdc b/.cursor/rules/docs/documentation_references_model_agents.mdc new file mode 100644 index 0000000..107bbea --- /dev/null +++ b/.cursor/rules/docs/documentation_references_model_agents.mdc @@ -0,0 +1,96 @@ +--- +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). +- Keep inline code comments light; push broader context into centralized documents. +- 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. + +--- + +## 9. Workflow Overview (Mermaid Diagram) + +```mermaid +flowchart TD + A[Contributor] -->|Writes Code & Draft Docs| B[Model Agent] + B -->|Evaluates References| C{Relevant?} + C -->|Yes| D[Suggest Placement & Context Links] + C -->|No| E[Flag Redundancy / Noise] + D --> F[Contributor Refines Docs] + E --> F + F --> G[Reviewer] + 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. diff --git a/doc/GLOSSARY.md b/doc/GLOSSARY.md new file mode 100644 index 0000000..286cb9f --- /dev/null +++ b/doc/GLOSSARY.md @@ -0,0 +1,31 @@ +# Glossary + +**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to accurately reflect current implementation status vs. planned features. + +**T (slot time)** — The local wall-clock time a notification should fire (e.g., 08:00). *See Notification System → Scheduling & T–lead.* + +**T–lead** — The moment **`prefetchLeadMinutes`** before **T** when the system *attempts* a **single** background prefetch. T–lead **controls prefetch attempts, not arming**; locals are pre-armed earlier to guarantee closed-app delivery. *See Notification System → Scheduling & T–lead and Roadmap Phase 2.1.* + +**Lead window** — The interval from **T–lead** up to **T** during which we **try once** to refresh content. It does **not** control arming; we pre-arm earlier. *See Notification System → Scheduling & T–lead.* + +**Rolling window** — Always keep **today's remaining** (and tomorrow if iOS pending caps allow) locals **armed** so the OS can deliver while the app is closed. *See Notification System → Scheduling & T–lead and Roadmap Phase 1.3.* + +**TTL (time-to-live)** — Maximum allowed payload age **at fire time**. If `T − fetchedAt > ttlSeconds`, we **skip** arming for that T. *See Notification System → Policies and Roadmap Phase 1.2.* + +**Shared DB (planned)** — The app and plugin will open the **same SQLite file**; the app owns schema/migrations, the plugin performs short writes with WAL. *Currently using SharedPreferences/UserDefaults.* *See Notification System → Storage and Roadmap Phase 1.1.* + +**WAL (Write-Ahead Logging)** — SQLite journaling mode that permits concurrent reads during writes; recommended for foreground-read + background-write. *See Notification System → Storage and Roadmap Phase 1.1.* + +**`PRAGMA user_version`** — An integer the app increments on each migration; the plugin **checks** (does not migrate) to ensure compatibility. *See Notification System → Storage and Roadmap Phase 1.1.* + +**Exact alarm (Android)** — Minute-precise alarm via `AlarmManager.setExactAndAllowWhileIdle`, subject to policy and permission. *See Notification System → Policies and Roadmap Phase 2.2.* + +**Windowed alarm (Android)** — Batched/inexact alarm via `setWindow(start,len)`; we target **±10 minutes** when exact alarms are unavailable. *See Notification System → Policies and Roadmap Phase 2.2.* + +**Delivery-time mutation (iOS)** — Not available for **local** notifications. Notification Service Extensions mutate **remote** pushes only; locals must be rendered before scheduling. *See Notification System → Policies.* + +**Start-on-Login** — Electron feature that automatically launches the application when the user logs into their system, enabling background notification scheduling and delivery after system reboot. *See Roadmap Phase 2.3.* + +**Tiered Storage (current)** — Current implementation uses SharedPreferences (Android) / UserDefaults (iOS) for quick access, in-memory cache for structured data, and file system for large assets. *See Notification System → Storage and Roadmap Phase 1.1.* + +**No delivery-time network:** Local notifications display **pre-rendered content only**; never fetch at delivery. *See Notification System → Policies.* \ No newline at end of file diff --git a/doc/implementation-roadmap.md b/doc/implementation-roadmap.md new file mode 100644 index 0000000..7442b08 --- /dev/null +++ b/doc/implementation-roadmap.md @@ -0,0 +1,486 @@ +# Daily Notification Plugin - Implementation Roadmap + +**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to clarify current implementation status and distinguish between existing infrastructure and planned T–lead logic. + +**Status:** Ready for implementation +**Date:** 2025-01-27 +**Author:** Matthew Raymer +**Assessment Date:** 2025-01-27 + +--- + +## Executive Summary + +This document outlines the implementation roadmap to bring the current Daily Notification Plugin (65% complete) to full compliance with the Native-First Notification System specification. The implementation is organized into three phases, with Phase 1 containing critical infrastructure components required for core functionality. + +### Current State Assessment +- **Overall Completion:** 65% of specification requirements +- **Critical Gaps:** SQLite database sharing, TTL-at-fire enforcement, rolling window safety +- **Current Storage:** SharedPreferences (Android) / UserDefaults (iOS) + in-memory cache +- **Background Infrastructure:** Basic WorkManager (Android) exists, but lacks T–lead logic +- **Critical Path:** Data persistence → Freshness enforcement → Platform completion + +--- + +## Current Implementation Status Clarification + +### Background Fetch Infrastructure +**Current State:** Basic infrastructure exists but lacks T–lead logic +- **Android:** `DailyNotificationFetchWorker.java` (WorkManager) exists +- **Android:** `DailyNotificationFetcher.java` with scheduling logic exists +- **Missing:** T–lead calculation, TTL enforcement, ETag support +- **Status:** Infrastructure ready, T–lead logic needs implementation + +### iOS Implementation Status +**Current State:** Basic plugin structure with power management +- **Implemented:** Plugin skeleton, power management, UserDefaults storage +- **Missing:** BGTaskScheduler, background tasks, T–lead prefetch +- **Status:** Foundation exists, background execution needs implementation + +--- + +**Gate:** No further freshness or scheduling work merges to main until **shared SQLite** (see Glossary → Shared DB) is in place and reading/writing under **WAL** (see Glossary → WAL), with UI hot-read verified. + +**Dependencies:** None + +### 1.1 SQLite Database Sharing Implementation + +**Priority:** CRITICAL + +#### Requirements +- Migrate from SharedPreferences/UserDefaults to shared SQLite database (see Glossary → Shared DB) +- WAL mode configuration for concurrent access (see Glossary → WAL) +- Schema version checking and compatibility validation (see Glossary → PRAGMA user_version) +- Required tables: `notif_contents`, `notif_deliveries`, `notif_config` +- **Migration Strategy:** Gradual migration from current tiered storage (see Glossary → Tiered Storage) + +#### Implementation Tasks +- [ ] **Migration from Current Storage** + - Create migration utilities from SharedPreferences to SQLite + - Implement data migration from UserDefaults to SQLite (iOS) + - Add backward compatibility during transition + - Preserve existing notification data during migration + +- [ ] **SQLite Setup (Android)** + - Create `DailyNotificationDatabase.java` with WAL mode (see Glossary → WAL) + - Implement schema version checking (`PRAGMA user_version`) (see Glossary → PRAGMA user_version) + - Add database connection management with proper error handling + +- [ ] **Database Configuration** + - Add `dbPath: string` to `ConfigureOptions` interface + - Implement database path resolution (absolute vs platform alias) + - Add `storage: 'shared'` configuration option + - Extend existing `NotificationOptions` with database settings + +- [ ] **Database Schema** + ```sql + -- notif_contents: keep history, newest-first reads + CREATE TABLE IF NOT EXISTS notif_contents( + id INTEGER PRIMARY KEY AUTOINCREMENT, + slot_id TEXT NOT NULL, + payload_json TEXT NOT NULL, + fetched_at INTEGER NOT NULL, -- epoch ms + etag TEXT, + UNIQUE(slot_id, fetched_at) + ); + CREATE INDEX IF NOT EXISTS notif_idx_contents_slot_time + ON notif_contents(slot_id, fetched_at DESC); + + -- notif_deliveries: track many deliveries per slot/time + CREATE TABLE IF NOT EXISTS notif_deliveries( + id INTEGER PRIMARY KEY AUTOINCREMENT, + slot_id TEXT NOT NULL, + fire_at INTEGER NOT NULL, -- intended fire time (epoch ms) + delivered_at INTEGER, -- when actually shown (epoch ms) + status TEXT NOT NULL DEFAULT 'scheduled', -- scheduled|shown|error|canceled + error_code TEXT, error_message TEXT + ); + + -- notif_config: generic configuration KV + CREATE TABLE IF NOT EXISTS notif_config( + k TEXT PRIMARY KEY, + v TEXT NOT NULL + ); + ``` + +#### Acceptance Criteria +- [ ] App and plugin can open the same SQLite file +- [ ] WAL mode enables concurrent reads during writes +- [ ] Schema version checking prevents compatibility issues +- [ ] All required tables exist and are accessible +- [ ] Shared DB visibility: UI reads updated rows immediately +- [ ] WAL overlap shows no UI blocking during background writes +- [ ] UI can read a row written by a background job **within the same second** (WAL hot-read) +- [ ] Plugin refuses to write if `PRAGMA user_version` < expected + +### 1.2 TTL-at-Fire Enforcement + +**Priority:** CRITICAL + +#### Requirements +- Skip arming notifications if `(T - fetchedAt) > ttlSeconds` (see Glossary → TTL) +- Validate freshness before scheduling +- Log TTL violations for debugging +- **Current State:** Not implemented - needs to be added to existing scheduling logic +- **Shared DB (single file):** App owns migrations (`PRAGMA user_version`) (see Glossary → PRAGMA user_version); plugin opens the **same path**; enable `journal_mode=WAL` (see Glossary → WAL), `synchronous=NORMAL`, `busy_timeout=5000`, `foreign_keys=ON`; background writes are **short & serialized**. + +#### Implementation Tasks +- [ ] **TTL Validation Logic** + - Insert TTL check into the scheduler path **before** any arm/re-arm + - Add log code `TTL_VIOLATION` + - Implement freshness validation before arming + - Before arming, if `(T − fetchedAt) > ttlSeconds`, **skip arming** and log `TTL_VIOLATION` + - Add TTL configuration to `NotificationOptions` + +- [ ] **Freshness Checking** + - Create `isContentFresh()` method + - Implement TTL calculation logic + - Add logging for TTL violations + +- [ ] **Configuration Integration** + - Add `ttlSeconds` to `NotificationOptions` interface + - Implement default TTL values (3600 seconds = 1 hour) + - Add TTL validation in option validation + +#### Acceptance Criteria +- [ ] Notifications are skipped if content is stale +- [ ] TTL violations are logged with timestamps +- [ ] Default TTL values are applied when not specified +- [ ] Freshness checking works across all platforms +- [ ] No armed notification violates **TTL-at-fire** +- [ ] No armed row violates TTL at T across platforms + +### 1.3 Rolling Window Safety + +**Priority:** CRITICAL + +#### Requirements +- Keep today's remaining notifications armed +- Keep tomorrow's notifications armed (within iOS caps) (see Glossary → Rolling window) +- Ensure closed-app delivery reliability +- **Current State:** Basic scheduling exists, but no rolling window logic + +#### Implementation Tasks +- [ ] **Rolling Window Logic** (see Glossary → Rolling window) + - Implement `armRollingWindow()` method + - Calculate today's remaining slots + - Calculate tomorrow's slots within iOS limits + - Account for iOS pending-notification limits; arm tomorrow only if within cap + +- [ ] **iOS Capacity Management** + - Implement iOS pending notification limit checking + - Add capacity-aware scheduling logic + - Handle capacity overflow gracefully + +- [ ] **Window Maintenance** + - Create `maintainRollingWindow()` method + - Implement automatic re-arming logic + - Add window state persistence + +#### Acceptance Criteria +- [ ] Today's remaining notifications stay armed +- [ ] Tomorrow's notifications are armed within iOS caps +- [ ] Closed-app delivery works reliably +- [ ] Window maintenance runs automatically +- [ ] Today always armed; tomorrow armed when within iOS cap + +### 1.4 Configuration API Enhancement + +**Priority:** HIGH + +#### Requirements +- Add `dbPath` configuration option +- Implement database path resolution +- Add storage mode configuration +- **Current State:** No database path configuration exists + +#### Implementation Tasks +- [ ] **Interface Updates** + - Extend `ConfigureOptions` with `dbPath: string` + - Add `storage: 'shared'` option + - Update validation logic + +- [ ] **Path Resolution** + - Implement absolute path handling + - Add platform-specific path resolution + - Create path validation logic + +#### Acceptance Criteria +- [ ] `dbPath` can be configured via API +- [ ] Path resolution works on all platforms +- [ ] Configuration validation prevents invalid paths + +--- + +## Phase 2: Platform Completion (High Priority) + +**Dependencies:** Phase 1 completion - **CRITICAL:** Phase 2 cannot start until SQLite sharing + TTL enforcement are finished + +### 2.1 iOS Background Tasks Implementation + +**Priority:** HIGH + +#### Requirements +- `BGTaskScheduler` for T-lead prefetch (see Glossary → T–lead) +- Silent push nudge support +- Background execution budget management +- Schedule prefetch at **T–lead = T − prefetchLeadMinutes** (see Glossary → T–lead) +- On wake, perform **one** ETag-aware fetch with **12s** timeout; **never** fetch at delivery +- Optionally (re)arm if still within **TTL-at-fire** (see Glossary → TTL) +- Single attempt at **T–lead**; **12s** timeout; no delivery-time fetch; (re)arm only if within **TTL-at-fire**. **(Planned)** + +#### Implementation Tasks +- [ ] **BGTaskScheduler Integration** + - Create `DailyNotificationBackgroundTask.swift` + - Implement background task registration + - Add task expiration handling + +- [ ] **Silent Push Support** + - Add silent push notification handling + - Implement push-to-background task bridge + - Add push token management + +- [ ] **Budget Management** + - Implement execution budget tracking + - Add budget-aware scheduling + - Handle budget exhaustion gracefully + +#### Acceptance Criteria +- [ ] Background tasks run at T-lead (see Glossary → T–lead) +- [ ] Silent push can trigger background execution +- [ ] Budget management prevents system penalties +- [ ] Background execution works when app is closed +- [ ] iOS BGTask best-effort at T–lead; closed-app still delivers via rolling window (see Glossary → Rolling window) + +### 2.2 Android Fallback Completion + +**Priority:** HIGH + +#### Requirements +- Complete ±10 minute windowed alarm implementation (see Glossary → Windowed alarm) +- Finish reboot/time change recovery +- Improve exact alarm fallback handling (see Glossary → Exact alarm) +- Finalize ±10m windowed alarm; reboot/time-change recovery; deep-link to Exact Alarm permission. **(Planned)** + +#### Implementation Tasks +- [ ] **Windowed Alarm Implementation** + - Complete `scheduleInexactAlarm()` method + - Implement ±10 minute window targeting + - Add window size configuration + +- [ ] **Recovery Mechanisms** + - Complete `BOOT_COMPLETED` receiver + - Implement `TIMEZONE_CHANGED` handling + - Add `TIME_SET` recovery logic + +- [ ] **Fallback Logic** + - Improve exact alarm permission checking + - Add graceful degradation to windowed alarms + - Implement fallback logging + +#### Acceptance Criteria +- [ ] Windowed alarms target ±10 minute windows +- [ ] Reboot recovery re-arms next 24h +- [ ] Time change recovery recomputes schedules +- [ ] Fallback works seamlessly +- [ ] Android exact permission path verified with fallback ±10m + +### 2.3 Electron Platform Support + +**Priority:** MEDIUM + +#### Requirements +- Notifications while app is running +- Start-on-Login support +- Best-effort background scheduling + +#### Implementation Tasks +- [ ] **Electron Integration** + - Create `DailyNotificationElectron.ts` + - Implement notification API + - Add Start-on-Login support + +- [ ] **Background Limitations** + - Document Electron limitations + - Implement best-effort scheduling + - Add fallback mechanisms + +#### Acceptance Criteria +- [ ] Notifications work while app is running +- [ ] Start-on-Login enables post-reboot delivery +- [ ] Limitations are clearly documented +- [ ] Best-effort scheduling is implemented + +--- + +## Phase 3: Network Optimization (Medium Priority) + +**Dependencies:** Phase 1 completion - **CRITICAL:** Phase 3 cannot start until SQLite sharing + TTL enforcement are finished + +### 3.1 ETag Support Implementation + +**Priority:** MEDIUM + +#### Requirements +- ETag headers in fetch requests +- 304 response handling +- Network efficiency optimization + +#### Implementation Tasks +- [ ] **ETag Headers** + - Add ETag to fetch requests + - Implement ETag storage in database + - Add ETag validation logic + +- [ ] **304 Response Handling** + - Implement 304 response processing + - Add conditional request logic + - Handle ETag mismatches + +- [ ] **Network Optimization** + - Add request caching + - Implement conditional fetching + - Add network efficiency metrics + +#### Acceptance Criteria +- [ ] ETag headers are sent with requests +- [ ] 304 responses are handled correctly +- [ ] Network efficiency is improved +- [ ] Conditional requests work reliably + +### 3.2 Advanced Error Handling + +**Priority:** MEDIUM + +#### Requirements +- Comprehensive error categorization +- Retry logic with exponential backoff +- Error reporting and telemetry + +#### Implementation Tasks +- [ ] **Error Categories** + - Define error types and codes + - Implement error classification + - Add error severity levels + +- [ ] **Retry Logic** + - Implement exponential backoff + - Add retry limit configuration + - Create retry state management + +- [ ] **Telemetry** + - Add error reporting + - Implement success/failure metrics + - Create debugging information + +#### Acceptance Criteria +- [ ] Errors are properly categorized +- [ ] Retry logic works with backoff +- [ ] Telemetry provides useful insights +- [ ] Debugging information is comprehensive + +### 3.3 Performance Optimization + +**Priority:** LOW + +#### Requirements +- Database query optimization +- Memory usage optimization +- Battery usage optimization + +#### Implementation Tasks +- [ ] **Database Optimization** + - Add database indexes + - Optimize query performance + - Implement connection pooling + +- [ ] **Memory Optimization** + - Reduce memory footprint + - Implement object pooling + - Add memory usage monitoring + +- [ ] **Battery Optimization** + - Minimize background CPU usage + - Optimize network requests + - Add battery usage tracking + +#### Acceptance Criteria +- [ ] Database queries are optimized +- [ ] Memory usage is minimized +- [ ] Battery usage is optimized +- [ ] Performance metrics are tracked + +--- + +## Implementation Guidelines + +### Development Standards +- **Code Quality:** Follow existing code style and documentation standards +- **Testing:** Write unit tests for all new functionality +- **Documentation:** Update documentation for all API changes +- **Logging:** Add comprehensive logging with proper tagging +- **Security:** Follow security best practices for database access + +### Testing Requirements +- **Unit Tests:** All new methods must have unit tests +- **Integration Tests:** Test database sharing functionality +- **Platform Tests:** Test on Android, iOS, and Electron +- **Edge Cases:** Test TTL violations, network failures, and recovery scenarios + +### Documentation Updates +- **API Documentation:** Update TypeScript definitions +- **Implementation Guide:** Update implementation documentation +- **Troubleshooting:** Add troubleshooting guides for common issues +- **Examples:** Create usage examples for new features + +--- + +## Success Metrics + +### Phase 1 Success Criteria +- [ ] SQLite database sharing works reliably +- [ ] TTL-at-fire enforcement prevents stale notifications +- [ ] Rolling window ensures closed-app delivery +- [ ] Configuration API supports all required options + +### Phase 2 Success Criteria +- [ ] iOS background tasks run at T-lead +- [ ] Android fallback works seamlessly +- [ ] Electron notifications work while running +- [ ] All platforms support the unified API + +### Phase 3 Success Criteria +- [ ] ETag support improves network efficiency +- [ ] Error handling is comprehensive and robust +- [ ] Performance is optimized across all platforms +- [ ] System meets all specification requirements + +--- + +## Risk Mitigation + +### Technical Risks +- **Database Compatibility:** Test schema version checking thoroughly +- **Platform Differences:** Implement platform-specific fallbacks +- **Background Execution:** Handle iOS background execution limitations +- **Permission Changes:** Monitor Android permission policy changes + +### Implementation Risks +- **Scope Creep:** Stick to specification requirements +- **Testing Coverage:** Ensure comprehensive testing +- **Documentation:** Keep documentation up-to-date +- **Performance:** Monitor performance impact + +--- + +## Conclusion + +This roadmap provides a structured approach to completing the Daily Notification Plugin implementation. Phase 1 addresses the critical infrastructure gaps, Phase 2 completes platform-specific functionality, and Phase 3 optimizes the system for production use. + +The implementation should follow the existing code patterns and maintain the high quality standards established in the current codebase. Regular testing and documentation updates are essential for success. + +**Next Steps:** +1. Review and approve this roadmap +2. Begin Phase 1 implementation +3. Set up testing infrastructure +4. Create implementation tracking system diff --git a/doc/notification-system.md b/doc/notification-system.md new file mode 100644 index 0000000..4cd7b5a --- /dev/null +++ b/doc/notification-system.md @@ -0,0 +1,247 @@ +# TimeSafari — Native-First Notification System + +**📝 SANITY CHECK IMPROVEMENTS APPLIED:** This document has been updated to clarify current background fetch infrastructure status and iOS implementation completeness. + +**Status:** Ready for implementation +**Date:** 2025-09-07 +**Author:** Matthew Raymer + +--- + +## Executive Summary + +Ship a **single, Native-First** notification system: OS-scheduled **background prefetch at T–lead** + **pre-armed** local notifications. Web-push is retired. + +### What we deliver + +- **Closed-app delivery:** Pre-armed locals fire even if the app is closed. +- **Freshness:** One prefetch attempt per slot at **T–lead**; ETag/TTL controls; skip when stale. +- **Android precision:** Exact alarms with permission; windowed fallback (±10m) otherwise. +- **Resilience:** Re-arm after reboot/time-change (Android receivers; iOS on next wake/silent push). +- **Cross-platform:** Same TS API (iOS/Android/Electron). Electron is best-effort while running. + +### Success signals + +- High delivery reliability, minute-precision on Android with permission. +- Prefetch budget hit rate at **T–lead**; zero stale deliveries beyond TTL. + +--- + +## Strategic Plan + +### Goal + +Deliver 1..M daily notifications with **OS background prefetch at T–lead** *(see Glossary)* and **rolling-window safety** *(see Glossary)* so messages display with fresh content even when the app is closed. + +### Tenets + +- **Reliability first:** OS delivers once scheduled; no JS at delivery time. +- **Freshness with guardrails:** Prefetch at **T–lead** *(see Glossary)*; enforce **TTL-at-fire** *(see Glossary)*; ETag-aware. +- **Single system:** One TS API; native adapters swap under the hood. +- **Platform honesty:** Android exactness via permission; iOS best-effort budget. +- **No delivery-time network:** Local notifications display **pre-rendered content only**; never fetch at delivery. + +### Architecture (high level) + +App (Vue/TS) → Orchestrator (policy) → Native Adapters: + +- **SchedulerNative** — AlarmManager (Android) / UNUserNotificationCenter (iOS) +- **BackgroundPrefetchNative** — WorkManager (Android) / BGTaskScheduler (+ silent push) (iOS) +- **DataStore** — SQLite + +**Storage:** **Current:** SharedPreferences (Android) / UserDefaults (iOS) + in-memory cache (see Glossary → Tiered Storage). **Planned:** one **shared SQLite** file (see Glossary → Shared DB); the app owns schema/migrations; the plugin opens the same path with **WAL** (see Glossary → WAL); background writes are **short & serialized**. *(Keep the "(Planned)" label until Phase 1 ships.)* + +### SQLite Ownership & Concurrency *(Planned)* + +* **One DB file:** The plugin will open the **same path** the app uses (no second DB). +* **Migrations owned by app:** The app executes schema migrations and bumps `PRAGMA user_version` (see Glossary → PRAGMA user_version). The plugin **never** migrates; it **asserts** the expected version. +* **WAL mode:** Open DB with `journal_mode=WAL`, `synchronous=NORMAL`, `busy_timeout=5000`, `foreign_keys=ON`. WAL (see Glossary → WAL) allows foreground reads while a background job commits quickly. +* **Single-writer discipline:** Background jobs write in **short transactions** (UPSERT per slot), then return. +* **Encryption (optional):** If using SQLCipher, the **same key** is used by both app and plugin. Do not mix encrypted and unencrypted openings. + +*Note: Currently using SharedPreferences (Android) / UserDefaults (iOS) with in-memory cache. See Implementation Roadmap → Phase 1.1 for migration steps.* + +### Scheduling & T–lead *(Planned)* + +- Arm **rolling window** (see Glossary → Rolling window). **(Planned)** +- Exactly **one** online-first fetch at **T–lead** (see Glossary → T–lead) with **12s** timeout; **ETag/304** respected. **(Planned)** +- If fresh **and** within **TTL-at-fire** (see Glossary → TTL), (re)arm; otherwise keep prior content. **(Planned)** +- If the OS skips the wake, the pre-armed local still fires from cache. **(Planned)** + +*Note: Current implementation has basic scheduling and WorkManager infrastructure (Android) but lacks T–lead prefetch logic, rolling window logic, and iOS background tasks. See Implementation Roadmap → Phase 1-2.* + +### Policies *(Mixed Implementation)* + +- **TTL-at-fire** (see Glossary → TTL): Before arming for T, if `(T − fetchedAt) > ttlSeconds` → **skip**. **(Planned)** +- **Android exactness** (see Glossary → Exact alarm): **(Partial)** — permission flow exists; finalize ±10m window & deep-link to settings. +- **Reboot/time change:** **(Partial)** — Android receivers partially present; iOS via next wake/silent push. +- **No delivery-time network** (see Glossary → No delivery-time network): Local notifications display **pre-rendered content only**; never fetch at delivery. **(Implemented)** + +--- + +## Implementation Guide + +### 1) Interfaces (TS stable) + +- **SchedulerNative**: `scheduleExact({slotId, whenMs, title, body, extra})`, `scheduleWindow(..., windowLenMs)`, `cancelBySlot`, `rescheduleAll`, `capabilities()` +- **BackgroundPrefetchNative**: `schedulePrefetch(slotId, atMs)`, `cancelPrefetch(slotId)` +- **DataStore**: SQLite adapters (notif_contents, notif_deliveries, notif_config) +- **Public API**: `configure`, `requestPermissions`, `runFullPipelineNow`, `reschedule`, `getState` + +### DB Path & Adapter Configuration *(Planned)* + +* **Configure option:** `dbPath: string` (absolute path or platform alias) will be passed from JS to the plugin during `configure()`. +* **Shared tables:** + + * `notif_contents(slot_id, payload_json, fetched_at, etag, …)` + * `notif_deliveries(slot_id, fire_at, delivered_at, status, error_code, …)` + * `notif_config(k, v)` +* **Open settings:** + + * `journal_mode=WAL` + * `synchronous=NORMAL` + * `busy_timeout=5000` + * `foreign_keys=ON` + +*Note: Currently using SharedPreferences/UserDefaults (see Glossary → Tiered Storage). Database configuration is planned for Phase 1.* + +See **Implementation Roadmap → Phase 1.1** for migration steps and schema. + +**Type (TS) extension** *(Planned)* + +```ts +export type ConfigureOptions = { + // …existing fields… + dbPath: string; // shared DB file the plugin will open + storage: 'shared'; // canonical value; plugin-owned DB is not used +}; +``` + +*Note: Current `NotificationOptions` interface exists but lacks `dbPath` configuration. This will be added in Phase 1.* + +**Plugin side (pseudo)** + +```kotlin +// Android open +val db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READWRITE) +db.execSQL("PRAGMA journal_mode=WAL") +db.execSQL("PRAGMA synchronous=NORMAL") +db.execSQL("PRAGMA foreign_keys=ON") +db.execSQL("PRAGMA busy_timeout=5000") +// Verify schema version +val uv = rawQuery("PRAGMA user_version").use { it.moveToFirst(); it.getInt(0) } +require(uv >= MIN_EXPECTED_VERSION) { "Schema version too old" } +``` + +```swift +// iOS open (FMDB / SQLite3) +// Set WAL via PRAGMA after open; check user_version the same way. +``` + +### 2) Templating & Arming + +- Render `title/body` **before** scheduling; pass via **SchedulerNative**. +- Route all arming through **SchedulerNative** to centralize Android exact/window semantics. + +### 3) T–lead (single attempt) + +**T–lead governs prefetch, not arming.** We **arm** one-shot locals as part of the rolling window so closed-app delivery is guaranteed. At **T–lead = T − prefetchLeadMinutes**, the **native background job** attempts **one** 12s ETag-aware fetch. If fresh content arrives and will not violate **TTL-at-fire**, we (re)arm the upcoming slot; if the OS skips the wake, the pre-armed local still fires with cached content. + +- Compute T–lead = `whenMs - prefetchLeadMinutes*60_000`. +- `BackgroundPrefetchNative.schedulePrefetch(slotId, atMs=T–lead)`. +- On wake: **ETag** fetch (timeout **12s**), persist, optionally cancel & re-arm if within TTL. +- Never fetch at delivery time. + +### 4) TTL-at-fire + +**TTL-at-fire:** Before arming for time **T**, compute `T − fetchedAt`. If that exceeds `ttlSeconds`, **do not arm** (skip). This prevents posting stale notifications when the app has been closed for a long time. + +`if (whenMs - fetchedAt) > ttlSeconds*1000 → skip` + +### 5) Android specifics + +- Request `SCHEDULE_EXACT_ALARM`; deep-link if denied; fallback to `setWindow(start,len)` (±10m). +- Receivers: `BOOT_COMPLETED`, `TIMEZONE_CHANGED`, `TIME_SET` → recompute & re-arm for next 24h and schedule T–lead prefetch. + +### 6) iOS specifics + +- `BGTaskScheduler` for T–lead prefetch (best-effort). Optional silent push nudge. +- Locals: `UNCalendarNotificationTrigger` (one-shots); no NSE mutation for locals. + +### 7) Network & Timeouts + +- Content fetch: **12s** timeout; single attempt at T–lead; ETag/304 respected. +- ACK/Error: **8s** timeout, fire-and-forget. + +### 8) Electron + +- Notifications while app is running; recommend **Start-on-Login**. No true background scheduling when fully closed. + +### 9) Telemetry + +- Record `scheduled|shown|error`; ACK deliveries (8s timeout); include slot/times/TZ/app version. + +--- + +## Capability Matrix + +| Capability | Android (Native) | iOS (Native) | Electron | Web | +|---|---|---|---|---| +| Multi-daily locals (closed app) | ✅ | ✅ | ✅ (app running) | — | +| Prefetch at T–lead (app closed) | ✅ WorkManager | ⚠️ BGTask (best-effort) | ✅ (app running) | — | +| Re-arm after reboot/time-change | ✅ Receivers | ⚠️ On next wake/silent push | ✅ Start-on-Login | — | +| Minute-precision alarms | ✅ with exact permission | ❌ not guaranteed | ✅ timer best-effort | — | +| Delivery-time mutation for locals | ❌ | ❌ | — | — | +| ETag/TTL enforcement | ✅ | ✅ | ✅ | — | +| Rolling-window safety | ✅ | ✅ | ✅ | — | + +--- + +## Acceptance Criteria + +### Core + +- **Closed-app delivery:** Armed locals fire at T with last rendered content. No delivery-time network. +- **T–lead prefetch:** Single background attempt at **T–lead**; if skipped, delivery still occurs from cache. +- **TTL-at-fire:** No armed local violates TTL at T. + +### Android + +- **Exact permission path:** With `SCHEDULE_EXACT_ALARM` → within ±1m; else **±10m** window. +- **Reboot recovery:** After reboot, receivers re-arm next 24h and schedule T–lead prefetch. +- **TZ/DST change:** Recompute & re-arm; future slots align to new wall-clock. + +### iOS + +- **BGTask budget respected:** Prefetch often runs but may be skipped; delivery still occurs via rolling window. +- **Force-quit caveat:** No background execution after user terminate; delivery still occurs if pre-armed. + +### Electron + +- **Running-app rule:** Delivery only while app runs; with Start-on-Login, after reboot the orchestrator re-arms and subsequent slots deliver. + +### Network + +- Content fetch timeout **12s**; ACK/Error **8s**; no retries inside lead; ETag honored. + +### Observability + +- Log/telemetry for `scheduled|shown|error`; ACK payload includes slot, times, device TZ, app version. + +### DB Sharing *(Planned)* + +* **Shared DB visibility:** A background prefetch writes `notif_contents`; the foreground UI **immediately** reads the same row. +* **WAL overlap:** With the app reading while the plugin commits, no user-visible blocking occurs. +* **Version safety:** If `user_version` is behind, the plugin emits an error and does not write (protects against partial installs). + +*Note: Currently using SharedPreferences/UserDefaults with in-memory cache. SQLite sharing is planned for Phase 1.* + +--- + +## Web-Push Cleanup + +Web-push functionality has been retired due to unreliability. All web-push related code paths and documentation sections should be removed or marked as deprecated. See `web-push-cleanup-guide.md` for detailed cleanup steps. + +--- + +_This document consolidates the Native-First notification system strategy, implementation details, capabilities, and acceptance criteria into a single comprehensive reference._ diff --git a/ios/Plugin/README.md b/ios/Plugin/README.md index 313bcd5..dc6b73c 100644 --- a/ios/Plugin/README.md +++ b/ios/Plugin/README.md @@ -2,14 +2,34 @@ This directory contains the iOS-specific implementation of the DailyNotification plugin. +## Current Implementation Status + +**✅ IMPLEMENTED:** +- Basic plugin structure (`DailyNotificationPlugin.swift`) +- UserDefaults for local data storage +- Power management (`DailyNotificationPowerManager.swift`) +- Battery optimization handling +- iOS notification categories and actions + +**❌ NOT IMPLEMENTED (Planned):** +- `BGTaskScheduler` for background data fetching +- Background task management +- Silent push nudge support +- T–lead prefetch logic + ## Implementation Details -The iOS implementation uses: +The iOS implementation currently uses: +- `UNUserNotificationCenter` for notification management ✅ +- `UserDefaults` for local data storage ✅ +- iOS notification categories and actions ✅ +- Power management and battery optimization ✅ + +**Planned additions:** - `BGTaskScheduler` for background data fetching -- `UNUserNotificationCenter` for notification management -- `UserDefaults` for local data storage -- iOS notification categories and actions +- Background task management +- Silent push support ## Native Code Location @@ -17,18 +37,28 @@ The native iOS implementation is located in the `ios/` directory at the project ## Key Components -1. `DailyNotificationIOS.swift`: Main plugin class -2. `BackgroundTaskManager.swift`: Handles background fetch scheduling -3. `NotificationManager.swift`: Manages notification creation and display -4. `DataStore.swift`: Handles local data persistence +1. `DailyNotificationPlugin.swift`: Main plugin class ✅ +2. `DailyNotificationPowerManager.swift`: Power state management ✅ +3. `DailyNotificationConfig.swift`: Configuration options ✅ +4. `DailyNotificationMaintenanceWorker.swift`: Maintenance tasks ✅ +5. `DailyNotificationLogger.swift`: Logging system ✅ + +**Missing Components (Planned):** +- `BackgroundTaskManager.swift`: Handles background fetch scheduling +- `NotificationManager.swift`: Manages notification creation and display +- `DataStore.swift`: Handles local data persistence ## Implementation Notes -- Uses BGTaskScheduler for reliable background execution -- Implements proper battery optimization handling -- Supports iOS notification categories and actions -- Handles background refresh limitations -- Uses UserDefaults for lightweight data storage +- Uses UserDefaults for lightweight data storage ✅ +- Implements proper battery optimization handling ✅ +- Supports iOS notification categories and actions ✅ +- Handles background refresh limitations ✅ + +**Planned Features:** +- BGTaskScheduler for reliable background execution +- Silent push notification support +- Background task budget management ## Testing diff --git a/lib/bin/main/org/example/Library.class b/lib/bin/main/org/example/Library.class deleted file mode 100644 index 66de899..0000000 Binary files a/lib/bin/main/org/example/Library.class and /dev/null differ diff --git a/lib/bin/test/org/example/LibraryTest.class b/lib/bin/test/org/example/LibraryTest.class deleted file mode 100644 index fd1b13a..0000000 Binary files a/lib/bin/test/org/example/LibraryTest.class and /dev/null differ