| name | offline-first-expert |
| description | Expert guidance for offline-first KMP and Android architectures using Store5, Room, SQLDelight, Ktor. Always trigger this skill when designing repositories, databases, caching, offline sync, Fetchers, SourceOfTruth, Updaters, Bookkeepers. |
Offline-First Expert
Smart guidelines for Store5 + Room/SQLDelight in KMP. Terse syntax. Max token economy.
Use Store5 for KMP-wide caching, sync, conflict logic. Keep architecture clean: Repository hides Store. Use `MutableSharedFlow` with `DROP_OLDEST` to bound memory.
1. Quick Decisions
2. Core Constraints
- **NEVER** leak `Store`, `StoreReadResponse`, or `StoreWriteRequest` to UI. Wrap in Repository.
- **NEVER** return empty collections from SourceOfTruth reader when absent; return `null` → trigger Fetcher.
- **NEVER** combine `expireAfterWrite` and `expireAfterAccess` in MemoryPolicy builder; throws error.
- **NEVER** call `awaitComplete()` in Turbine unit tests for Store streams; they are infinite.
- **ALWAYS** return observable `Flow` from SourceOfTruth reader. One-shot flow breaks reactivity.
- **ALWAYS** implement TTL validator + 0-20% jitter to prevent thundering herd.
- **ALWAYS** catch `CancellationException` first and rethrow it when catching exceptions in Fetcher builders.
- **ALWAYS** target the final output (Domain/Output) type in the Store5 `Validator`, not the local DB entity type.
- **ALWAYS** use `StoreReadRequest.localOnly(key)` for offline-only configurations.
3. Store5 Features & Niche Rules
- Fetcher: Origin data source (Network/API).
- Niche: Wrap/prefer
Fetcher.ofResult to bypass exception overhead. Use ofFlow for streaming/paging.
- SourceOfTruth (SoT): Local persistent DB (Room/SQLDelight).
- Niche: Reader MUST return observable Flow. Reader MUST return
null (not empty collection) on absent data to trigger Fetcher.
- Converter: Net DTO ⇄ DB Entity ⇄ Domain Model mapper.
- Niche: Required in
MutableStore to write domain model back to DB.
- Validator: Cache validity gate.
- Niche: Serving stale-while-revalidate first. Add 0-20% TTL jitter to prevent thundering herds.
- Updater: Local update publisher to network.
- Niche: Returns
UpdaterResult. Scheduled for sync retries on fail.
- Bookkeeper: Sync error tracker.
- Niche: Tracks failed keys. Blocks fetch if Updater needs retry.
- MemoryPolicy: Eviction config.
- Niche: Combining
expireAfterWrite and expireAfterAccess throws exception.
- StoreMultiCache: Multi-instance cache (Experimental).
- Niche: Requires
@ExperimentalStoreApi. Use only for divergent key domains.
4. Code Samples
Ensure KMP patterns are followed. The repository class must wrap the store, and only the repository should expose data to the UI layer.