You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
9.7 KiB
242 lines
9.7 KiB
# TimeSafari Notifications — LLM Implementation Directive (v2.0)
|
|
_Last updated: August 12, 2025_
|
|
|
|
## 0) Role & Objective
|
|
**You are the implementation LLM.** Build an **offline-first daily notifications system** for Android (Kotlin) and iOS (Swift) that **prefetches -> caches -> schedules -> displays** content **without requiring network at display time**. Favor **reliability over richness**.
|
|
|
|
## 1) Golden Rules
|
|
1. **Follow the pipeline:** **Prefetch → Cache → Schedule → Display.**
|
|
2. **Never depend on network at display time.** All assets must be local.
|
|
3. **Design for failure.** Always have a last-known-good and an emergency fallback.
|
|
4. **Keep content scannable (<3s), single message, actionable.**
|
|
5. **Measure everything** (fetch success, delivery, engagement, stale usage).
|
|
6. **Minimize battery impact** and respect platform limitations and user settings.
|
|
7. **Ask only when needed:** if a required input is missing, use the defaults below; otherwise proceed.
|
|
|
|
## 2) Default Assumptions (use unless overridden)
|
|
- **Product mode:** Lightweight Daily Updates (text + emoji) with option to extend to media later.
|
|
- **Fetch size:** 1–2 KB JSON daily.
|
|
- **User schedule default:** 07:30 local time, daily.
|
|
- **Quiet hours:** None (app-level quiet hours supported but disabled by default).
|
|
- **Analytics:** Local log + pluggable uploader (no-op by default).
|
|
|
|
## 3) Deliverables
|
|
Produce the following artifacts:
|
|
|
|
### Android (Kotlin)
|
|
- `:core`: models, storage, metrics, fallback manager.
|
|
- `:data`: fetchers (WorkManager), mappers, cache policy.
|
|
- `:notify`: scheduler (AlarmManager), receiver, channels.
|
|
- App manifest entries & permissions.
|
|
- Unit tests for fallback, scheduling, metrics.
|
|
- README with battery optimization instructions (OEMs).
|
|
|
|
### iOS (Swift)
|
|
- `NotificationKit`: models, storage, metrics, fallback manager.
|
|
- BGTaskScheduler registration + handler.
|
|
- UNUserNotificationCenter scheduling + categories + attachments.
|
|
- Unit tests for fallback, scheduling, metrics.
|
|
- README with Background App Refresh caveats + Focus/Summary notes.
|
|
|
|
## 4) Permissions & Required Setup
|
|
### Android Manifest
|
|
```xml
|
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
<uses-permission android:name="android.permission/SCHEDULE_EXACT_ALARM" />
|
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
```
|
|
- Create a high-importance **NotificationChannel** `timesafari.daily`.
|
|
- If **SCHEDULE_EXACT_ALARM** denied on Android 12+, auto-fallback to inexact.
|
|
|
|
### iOS App Setup (AppDelegate / SceneDelegate)
|
|
- Register `BGTaskScheduler` with ID `com.timesafari.daily-fetch`.
|
|
- Request alerts, sound, badge via `UNUserNotificationCenter`.
|
|
- Create category `DAILY_UPDATE` with a primary `View` action.
|
|
- Ensure Background Modes: **Background fetch**, **Remote notifications** (optional for future push).
|
|
|
|
## 5) Data Model (keep minimal, versioned)
|
|
### Canonical Schema (language-agnostic)
|
|
```
|
|
NotificationContent v1
|
|
- id: string (uuid)
|
|
- title: string
|
|
- body: string (plain text; may include simple emoji)
|
|
- scheduledTime: epoch millis (client-local target)
|
|
- mediaUrl: string? (for future; must be mirrored to local path before use)
|
|
- fetchTime: epoch millis
|
|
```
|
|
### Kotlin
|
|
```kotlin
|
|
@Entity
|
|
data class NotificationContent(
|
|
@PrimaryKey val id: String,
|
|
val title: String,
|
|
val body: String,
|
|
val scheduledTime: Long,
|
|
val mediaUrl: String?,
|
|
val fetchTime: Long
|
|
)
|
|
```
|
|
### Swift
|
|
```swift
|
|
struct NotificationContent: Codable {
|
|
let id: String
|
|
let title: String
|
|
let body: String
|
|
let scheduledTime: TimeInterval
|
|
let mediaUrl: String?
|
|
let fetchTime: TimeInterval
|
|
}
|
|
```
|
|
|
|
## 6) Storage Layers
|
|
**Tier 1: Key-Value (quick)** — next payload, last fetch timestamp, user prefs.
|
|
**Tier 2: DB (structured)** — history, media metadata, analytics events.
|
|
**Tier 3: Files (large assets)** — images/audio; LRU cache & quotas.
|
|
|
|
- Android: SharedPreferences/DataStore + Room + `context.cacheDir/notifications/`
|
|
- iOS: UserDefaults + Core Data/SQLite + `Library/Caches/notifications/`
|
|
|
|
## 7) Background Execution
|
|
### Android — WorkManager
|
|
- Periodic daily work with constraints (CONNECTED network).
|
|
- Total time budget ~10m; use **timeouts** (e.g., fetch ≤30s, overall ≤8m).
|
|
- On exception/timeout: **schedule from cache**; then `Result.success()` or `Result.retry()` per policy.
|
|
|
|
### iOS — BGTaskScheduler
|
|
- `BGAppRefreshTask` with aggressive time budgeting (10–30s typical).
|
|
- Submit next request immediately at start of handler.
|
|
- Set `expirationHandler` first; cancel tasks cleanly; **fallback to cache** on failure.
|
|
|
|
## 8) Scheduling & Display
|
|
### Android
|
|
- Prefer `AlarmManager.setExactAndAllowWhileIdle()` if permitted; else inexact.
|
|
- Receiver builds notification using **BigTextStyle** for long bodies.
|
|
- Limit actions to ≤3; default: `View` (foreground intent).
|
|
|
|
### iOS
|
|
- `UNCalendarNotificationTrigger` repeating at preferred time.
|
|
- Category `DAILY_UPDATE` with `View` action.
|
|
- Media attachments **only if local**; otherwise skip gracefully.
|
|
|
|
## 9) Fallback Hierarchy (must implement)
|
|
1. **Foreground prefetch path** if app is open.
|
|
2. **Background fetch** with short network timeout.
|
|
3. **Last good cache** (annotate staleness: “as of X”).
|
|
4. **Emergency phrases** (rotate from static list).
|
|
|
|
Provide helper:
|
|
- `withStaleMarker(content) -> content'` appends age label (e.g., “from 3h ago”).
|
|
|
|
## 10) Failure Matrix & Responses
|
|
| Scenario | Detect | Action |
|
|
|---|---|---|
|
|
| No network / timeout | Exceptions / status | Use last-good; schedule |
|
|
| Invalid JSON | Parse error | Use emergency content; log |
|
|
| Storage full | Write error | Evict old; retry minimal payload |
|
|
| Notifications disabled | OS state | In-app education screen |
|
|
| Background killed | Gaps in execution | Catch-up next foreground open |
|
|
|
|
## 11) Metrics (local first; uploader optional)
|
|
Track per attempt:
|
|
```
|
|
NotificationMetrics v1
|
|
- scheduledTime, actualDeliveryTime?
|
|
- contentAge (ms)
|
|
- engagement: {TAPPED, DISMISSED, IGNORED}?
|
|
- failureReason?
|
|
- platformInfo (oem, os version, app state)
|
|
```
|
|
- Compute: **Fetch Success Rate**, **Delivery Rate**, **Engagement Rate**, **Stale Content Rate**.
|
|
|
|
## 12) Testing Requirements
|
|
### Matrix (minimum)
|
|
- Android 12+ foreground/background/killed; with/without Battery Saver; Wi‑Fi/Mobile/Offline.
|
|
- iOS 16+ background/Low Power/Focus/Scheduled Summary on & off.
|
|
- Offline at trigger time (must still display).
|
|
|
|
### Unit Tests (examples)
|
|
- Fallback when fetch fails (uses last-good and marks stale).
|
|
- Exact vs inexact scheduling path selected correctly.
|
|
- Metrics recorded for each stage.
|
|
|
|
## 13) UX Standards
|
|
- One clear message; no clutter.
|
|
- ≤2 actions; primary takes user into app.
|
|
- Respect quiet hours if configured.
|
|
- Provide onboarding: value explanation → permission request → time picker → test notification → tips for OEM battery settings (Android) or Focus/Summary (iOS).
|
|
|
|
## 14) Code Stubs (must generate & wire)
|
|
### Android — Worker (core pattern)
|
|
```kotlin
|
|
class DailyContentWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) {
|
|
override suspend fun doWork(): Result = try {
|
|
withTimeout(8.minutes) {
|
|
val content = fetchDailyContent(timeout = 30.seconds)
|
|
saveToCache(content)
|
|
scheduleNotification(content)
|
|
}
|
|
Result.success()
|
|
} catch (e: TimeoutCancellationException) {
|
|
scheduleFromCache(); Result.success()
|
|
} catch (e: Exception) {
|
|
scheduleFromCache(); Result.retry()
|
|
}
|
|
}
|
|
```
|
|
### iOS — BG Refresh Handler (core pattern)
|
|
```swift
|
|
func handleBackgroundRefresh(_ task: BGAppRefreshTask) {
|
|
scheduleNextRefresh()
|
|
var finished = false
|
|
task.expirationHandler = { if !finished { cancelNetwork(); task.setTaskCompleted(success: false) } }
|
|
fetchDailyContent(timeout: 15) { result in
|
|
defer { finished = true; task.setTaskCompleted(success: result.isSuccess) }
|
|
switch result {
|
|
case .success(let content): quickSave(content); scheduleNotification(content)
|
|
case .failure: scheduleFromCache()
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 15) Security & Privacy
|
|
- Use HTTPS; pin if required.
|
|
- Strip PII from payloads; keep content generic by default.
|
|
- Store only what is necessary; apply cache quotas; purge on logout/uninstall.
|
|
- Respect OS privacy settings (Focus, Scheduled Summary, Quiet Hours).
|
|
|
|
## 16) Troubleshooting Playbook (LLM should generate helpers)
|
|
- Android: verify permission, channel, OEM battery settings; `adb shell dumpsys notification`.
|
|
- iOS: check authorization, Background App Refresh, Low Power, Focus/Summary state.
|
|
|
|
## 17) Roadmap Flags (implement behind switches)
|
|
- `FEATURE_MEDIA_ATTACHMENTS` (default off).
|
|
- `FEATURE_PERSONALIZATION_ENGINE` (time/frequency, content types).
|
|
- `FEATURE_PUSH_REALTIME` (server-driven for urgent alerts).
|
|
|
|
## 18) Definition of Done
|
|
- Notifications deliver daily at user-selected time **without network**.
|
|
- Graceful fallback chain proven by tests.
|
|
- Metrics recorded locally; viewable log.
|
|
- Clear onboarding and self-diagnostic screen.
|
|
- Battery/OS constraints documented; user education available.
|
|
|
|
## 19) Quick Start (LLM execution order)
|
|
1. Scaffold modules (Android + iOS).
|
|
2. Implement models + storage + fallback content.
|
|
3. Implement schedulers (AlarmManager / UNCalendarNotificationTrigger).
|
|
4. Implement background fetchers (WorkManager / BGTaskScheduler).
|
|
5. Wire onboarding + test notification.
|
|
6. Add metrics logging.
|
|
7. Ship minimal, then iterate.
|
|
|
|
---
|
|
|
|
### Appendix A — Emergency Fallback Lines
|
|
- "🌅 Good morning! Ready to make today amazing?"
|
|
- "💪 Every small step forward counts. You've got this!"
|
|
- "🎯 Focus on what you can control today."
|
|
- "✨ Your potential is limitless. Keep growing!"
|
|
- "🌟 Progress over perfection, always."
|
|
|