Browse Source
- Add GLOSSARY.md with core terminology and cross-references - Add implementation-roadmap.md with 3-phase development plan - Add notification-system.md with Native-First architecture spec - Update ios/Plugin/README.md to reflect actual vs planned implementation status This establishes the foundation for implementing shared SQLite storage, TTL-at-fire enforcement, rolling window safety, and platform completion as outlined in the phased roadmap. Files: 4 changed, 807 insertions(+), 13 deletions(-)research/notification-plugin-enhancement
7 changed files with 903 additions and 13 deletions
@ -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. |
@ -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.* |
@ -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 |
@ -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._ |
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue