rename 'docs' directory to 'doc'

This commit is contained in:
2026-03-14 19:52:40 -06:00
parent ca6a75ded8
commit 11561991bd
198 changed files with 35779 additions and 115297 deletions

View File

@@ -0,0 +1,395 @@
# iOS Implementation Directive: App Launch Recovery & Missed Notification Detection
**Author**: Matthew Raymer
**Date**: 2025-12-08
**Status**: Active Implementation Directive - iOS Only
**Version**: 1.0.0
**Last Synced With Plugin Version**: v1.1.0
## Purpose
This directive provides **descriptive overview and integration guidance** for iOS-specific recovery and missed notification detection:
1. App Launch Recovery (cold/warm/terminated)
2. Missed Notification Detection
3. App Termination Detection
4. Background Task Registration for Boot Recovery
**⚠️ CRITICAL**: This document is **descriptive and integrative**. The **normative implementation instructions** are in the Phase 13 directives below. **If any code or behavior in this file conflicts with a Phase directive, the Phase directive wins.**
**Reference**: See [Plugin Requirements](./alarms/03-plugin-requirements.md) for requirements that Phase directives implement.
**Reference**: See [Platform Capability Reference](./alarms/01-platform-capability-reference.md) for iOS OS-level facts.
**⚠️ IMPORTANT**: For implementation, use the phase-specific directives (these are the canonical source of truth):
- **[Phase 1: Cold Start Recovery](./ios-implementation-directive-phase1.md)** - Minimal viable recovery
- Implements: [Plugin Requirements §3.1.2](./alarms/03-plugin-requirements.md#312-app-cold-start) (iOS equivalent)
- Explicit acceptance criteria, rollback safety, data integrity checks
- **Start here** for fastest implementation
- **[Phase 2: App Termination Detection & Recovery](./ios-implementation-directive-phase2.md)** - Comprehensive termination handling
- Implements: iOS-specific app termination scenarios
- Prerequisite: Phase 1 complete
- **[Phase 3: Background Task Registration & Boot Recovery](./ios-implementation-directive-phase3.md)** - Background task enhancement
- Implements: BGTaskScheduler registration for boot recovery
- Prerequisites: Phase 1 and Phase 2 complete
**See Also**: [Unified Alarm Directive](./alarms/000-UNIFIED-ALARM-DIRECTIVE.md) for master coordination document.
---
## 1. Implementation Overview
### 1.1 What Needs to Be Implemented
| Feature | Status | Priority | Location |
| ------- | ------ | -------- | -------- |
| App Launch Recovery | ❌ Missing | **High** | `DailyNotificationPlugin.swift` - `load()` method |
| Missed Notification Detection | ⚠️ Partial | **High** | `DailyNotificationPlugin.swift` - new method |
| App Termination Detection | ❌ Missing | **High** | `DailyNotificationPlugin.swift` - recovery logic |
| Background Task Registration | ⚠️ Partial | **Medium** | `AppDelegate.swift` - BGTaskScheduler registration |
### 1.2 Implementation Strategy
**Phase 1** Cold start recovery only
- Missed notification detection + future notification verification
- No termination detection, no boot handling
- **See [Phase 1 directive](./ios-implementation-directive-phase1.md) for implementation**
**Phase 2** App termination detection & full recovery
- Termination detection via UNUserNotificationCenter state comparison
- Comprehensive recovery of all schedules (notify + fetch)
- Past notifications marked as missed, future notifications rescheduled
- **See [Phase 2 directive](./ios-implementation-directive-phase2.md) for implementation**
**Phase 3** Background task registration & boot recovery
- BGTaskScheduler registration for boot recovery
- Next occurrence rescheduled for repeating schedules
- **See [Phase 3 directive](./ios-implementation-directive-phase3.md) for implementation**
---
## 2. iOS-Specific Considerations
### 2.1 Key Differences from Android
**iOS Advantages**:
- ✅ Notifications persist across app termination (OS-guaranteed)
- ✅ Notifications persist across device reboot (OS-guaranteed)
- ✅ No force stop equivalent (iOS doesn't have user-facing force stop)
**iOS Challenges**:
- ❌ App code does NOT run when notification fires (only if user taps)
- ❌ Background execution severely limited (BGTaskScheduler only)
- ❌ Cannot rely on background execution for recovery
- ❌ Must detect missed notifications on app launch
**Platform Reference**: See [Platform Capability Reference §3](./alarms/01-platform-capability-reference.md#3-ios-notification-capability-matrix) for complete iOS behavior matrix.
### 2.2 Recovery Scenario Mapping
**Android → iOS Mapping**:
| Android Scenario | iOS Equivalent | Detection Method |
| ---------------- | -------------- | --------------- |
| `COLD_START` | App Launch After Termination | Check if notifications exist vs DB state |
| `FORCE_STOP` | App Terminated by System | Check if notifications missing vs DB state |
| `BOOT` | Device Reboot | BGTaskScheduler registration (Phase 3) |
| `WARM_START` | App Resume (Foreground) | Check app state on resume |
**Note**: iOS doesn't have a user-facing "force stop" equivalent. System termination is detected by comparing UNUserNotificationCenter state with database state.
### 2.3 iOS APIs Used
**Notification Management**:
- `UNUserNotificationCenter.current()` - Notification center
- `UNUserNotificationCenter.getPendingNotificationRequests()` - Check scheduled notifications
- `UNUserNotificationCenter.add()` - Schedule notifications
**Background Tasks**:
- `BGTaskScheduler.shared` - Background task scheduler
- `BGTaskScheduler.register()` - Register background task handlers
- `BGAppRefreshTaskRequest` - Background fetch requests
**App Lifecycle**:
- `applicationWillTerminate` - App termination notification
- `applicationDidBecomeActive` - App foreground notification
- `applicationDidEnterBackground` - App background notification
---
## 3. Implementation: ReactivationManager (iOS)
**⚠️ Illustrative only** See Phase 1 and Phase 2 directives for canonical implementation.
**ReactivationManager Responsibilities by Phase**:
| Phase | Responsibilities |
| ----- | ---------------- |
| 1 | Cold start only (missed detection + verify/reschedule future) |
| 2 | Adds termination detection & recovery |
| 3 | Background task registration & boot recovery |
**For implementation details, see**:
- [Phase 1: ReactivationManager creation](./ios-implementation-directive-phase1.md#2-implementation-reactivationmanager)
- [Phase 2: Termination detection](./ios-implementation-directive-phase2.md#2-implementation-termination-detection)
### 3.1 Create New File
**File**: `ios/Plugin/DailyNotificationReactivationManager.swift`
**Purpose**: Centralized recovery logic for app launch scenarios
### 3.2 Class Structure
**⚠️ Illustrative only** See Phase 1 for canonical implementation.
```swift
import Foundation
import UserNotifications
/**
* Manages recovery of notifications on app launch
* Handles cold start, warm start, and termination recovery scenarios
*
* @author Matthew Raymer
* @version 1.0.0
*/
class DailyNotificationReactivationManager {
private static let TAG = "DNP-REACTIVATION"
private let notificationCenter = UNUserNotificationCenter.current()
private let database: DailyNotificationDatabase
private let storage: DailyNotificationStorage
init(database: DailyNotificationDatabase, storage: DailyNotificationStorage) {
self.database = database
self.storage = storage
}
/**
* Perform recovery on app launch
* Detects scenario (cold/warm/termination) and handles accordingly
*/
func performRecovery() async {
do {
NSLog("\(Self.TAG): Starting app launch recovery")
// Step 1: Detect scenario
let scenario = try await detectScenario()
NSLog("\(Self.TAG): Detected scenario: \(scenario)")
// Step 2: Handle based on scenario
switch scenario {
case .termination:
try await handleTerminationRecovery()
case .coldStart:
try await handleColdStartRecovery()
case .warmStart:
try await handleWarmStartRecovery()
case .none:
NSLog("\(Self.TAG): No recovery needed")
}
NSLog("\(Self.TAG): App launch recovery completed")
} catch {
NSLog("\(Self.TAG): Error during app launch recovery: \(error)")
}
}
// ... implementation methods below ...
}
```
---
## 4. Recovery Scenario Detection
### 4.1 Scenario Detection Algorithm
**Platform Reference**: [iOS §3.1.1](./alarms/01-platform-capability-reference.md#311-notifications-survive-app-termination) - Notifications survive app termination
**Detection Logic**:
```swift
enum RecoveryScenario {
case none // No recovery needed (first launch or warm resume)
case coldStart // App launched after termination, notifications may exist
case termination // App terminated, notifications missing vs DB
case warmStart // App resumed from background (optimization only)
}
func detectScenario() async throws -> RecoveryScenario {
// Step 1: Check if database has schedules
let schedules = try database.getEnabledSchedules()
if schedules.isEmpty {
return .none // First launch
}
// Step 2: Get pending notifications from UNUserNotificationCenter
let pendingNotifications = try await notificationCenter.pendingNotificationRequests()
// Step 3: Compare DB state with notification center state
let dbNotificationIds = Set(schedules.flatMap { $0.getScheduledNotificationIds() })
let pendingIds = Set(pendingNotifications.map { $0.identifier })
// Step 4: Determine scenario
if pendingIds.isEmpty && !dbNotificationIds.isEmpty {
// DB has schedules but no notifications scheduled
return .termination
} else if !pendingIds.isEmpty && !dbNotificationIds.isEmpty {
// Both have data - check if they match
if dbNotificationIds != pendingIds {
return .coldStart // Mismatch indicates recovery needed
} else {
return .warmStart // Match indicates warm resume
}
}
return .none
}
```
**For complete implementation, see**: [Phase 1 directive](./ios-implementation-directive-phase1.md#3-scenario-detection)
---
## 5. Missed Notification Detection
### 5.1 Detection Logic
**Platform Reference**: [iOS §3.2.1](./alarms/01-platform-capability-reference.md#321-app-code-does-not-run-when-notification-fires) - App code does not run when notification fires
**iOS Behavior**: When a notification fires, the app code does NOT execute. The notification is displayed, but the app must detect missed notifications on the next app launch.
**Detection Steps**:
1. Query database for notifications with `scheduled_time < currentTime`
2. Filter for notifications with `delivery_status != 'delivered'`
3. Mark as `'missed'` in database
4. Record in history table
**For complete implementation, see**: [Phase 1 directive](./ios-implementation-directive-phase1.md#4-missed-notification-detection)
---
## 6. Background Task Registration
### 6.1 BGTaskScheduler Registration
**Platform Reference**: [iOS §3.1.3](./alarms/01-platform-capability-reference.md#313-background-tasks-for-prefetching) - Background tasks for prefetching
**iOS Limitation**: BGTaskScheduler cannot be used for critical scheduling. It's system-controlled and not guaranteed.
**Use Case**: BGTaskScheduler is used for:
- Prefetching content (not critical timing)
- Boot recovery (system may defer)
- Background maintenance (best effort)
**Registration Location**: `AppDelegate.swift` or `SceneDelegate.swift`
**For complete implementation, see**: [Phase 3 directive](./ios-implementation-directive-phase3.md#2-background-task-registration)
---
## 7. Testing Strategy
### 7.1 iOS Testing Tools
**Simulator Testing**:
- `xcrun simctl` - Simulator control
- Xcode Instruments - Performance profiling
- Console.app - System log viewing
**Device Testing**:
- Xcode Device Console - Real device logs
- Settings → Developer → Background App Refresh - Control background execution
### 7.2 Test Scenarios
**Phase 1 Tests**:
- Cold start recovery
- Missed notification detection
- Future notification verification
**Phase 2 Tests**:
- App termination detection
- Comprehensive recovery
- Multiple schedules recovery
**Phase 3 Tests**:
- Background task registration
- Boot recovery (simulated)
- Background task execution
**For complete test procedures, see**: [iOS Test Scripts](../test-apps/ios-test-app/test-phase1.sh)
---
## 8. Platform-Specific Notes
### 8.1 Notification Persistence
**iOS Advantage**: Notifications persist automatically across:
- App termination
- Device reboot (for calendar/time triggers)
**App Responsibility**: Must still:
- Detect missed notifications on app launch
- Reschedule future notifications if needed
- Track delivery status in database
### 8.2 Background Execution Limits
**iOS Limitation**: Background execution is severely limited:
- BGTaskScheduler is system-controlled
- Cannot rely on background execution for recovery
- Must handle recovery on app launch
**Workaround**: Use BGTaskScheduler for prefetching only, not for critical scheduling.
### 8.3 Timing Tolerance
**iOS Limitation**: Calendar-based notifications have ±180 second tolerance.
**Impact**: Notifications may fire up to 3 minutes early or late.
**Mitigation**: Account for tolerance in missed notification detection logic.
---
## 9. Next Steps
1. **Start with Phase 1**: Implement cold start recovery
- See [Phase 1 directive](./ios-implementation-directive-phase1.md)
- Focus on missed notification detection
- Verify future notifications are scheduled
2. **Proceed to Phase 2**: Add termination detection
- See [Phase 2 directive](./ios-implementation-directive-phase2.md)
- Implement comprehensive recovery
- Handle multiple schedules
3. **Complete Phase 3**: Background task registration
- See [Phase 3 directive](./ios-implementation-directive-phase3.md)
- Register BGTaskScheduler handlers
- Implement boot recovery
---
## 10. References
- [Platform Capability Reference](./alarms/01-platform-capability-reference.md) - iOS OS-level facts
- [Plugin Requirements](./alarms/03-plugin-requirements.md) - Requirements this directive implements
- [Android Implementation Directive](./android-implementation-directive.md) - Android equivalent for comparison
- [iOS Recovery Scenario Mapping](./ios-recovery-scenario-mapping.md) - Detailed scenario mapping
- [iOS Core Data Migration Guide](./ios-core-data-migration.md) - Database migration guide
---
**Document Version**: 1.0.0
**Last Updated**: 2025-12-08
**Next Review**: After Phase 1 implementation