From 07439fd58d7a24f63175f0f55bc995f093f026a1 Mon Sep 17 00:00:00 2001 From: Claw Date: Thu, 30 Jul 2026 11:23:37 -0700 Subject: [PATCH] F-115: NiA dogfood DataStore Preferences UserData docs Document phase C Preferences DataStore on external forma-spike (core-datastore-android-util, OfflineFirstUserDataRepository, FollowTopicUseCase). Findings F18 (library stack, no plugin) and F19 (domain use case for feature follow toggle). Spike assembleDebug verified green (291 tasks); external tree lives under nowinandroid-forma/forma-spike. --- TICKETS.md | 4 ++-- docs/DOGFOOD-NIA.md | 21 +++++++++++++++++++-- docs/GOOGLE-LIBRARIES.md | 2 +- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/TICKETS.md b/TICKETS.md index b02034cd..c96c9934 100644 --- a/TICKETS.md +++ b/TICKETS.md @@ -172,11 +172,11 @@ External multimodule OSS validation of meta-build axioms (structure over configu type-owned plugins, attrs-only call sites, closed matrix). **Not** another in-repo sample. Open coding: **F-115** (`in_progress`, **`priority: now`**, **cron may continue**). **F-094** Portal remains `blocked` (human). -4h workers: pick F-115 phase C remainder (more features / DataStore / sync) while gated; if no ticket has `priority: now` / `cron may continue`, respond `[SILENT]` (audit 2026-07-29 gate — interactive “Go ahead” alone is not enough). +4h workers: pick F-115 phase C remainder (more features / WorkManager sync / Proto DataStore) while gated; if no ticket has `priority: now` / `cron may continue`, respond `[SILENT]` (audit 2026-07-29 gate — interactive “Go ahead” alone is not enough). | ID | Status | Title | Notes | |----|--------|-------|-------| -| F-115 | in_progress | Dogfood Now in Android under Forma | Primary OSS target [`android/nowinandroid`](https://github.com/android/nowinandroid). Design: [`docs/DOGFOOD-NIA.md`](docs/DOGFOOD-NIA.md). **Phase A+B+C Hilt+Room+Firebase+DataStore done:** spike green with Hilt Path A + Room Path B + Firebase Path A + **Preferences DataStore** UserData (`core-datastore-android-util`, `OfflineFirstUserDataRepository`, `FollowTopicUseCase`). Engine: KSP companion (F12) + `androidUtilTarget` (F15). Findings F16–F19. **Next phase C:** more features / WorkManager sync / Proto DataStore. No `androidLibrary`. | +| F-115 | in_progress · **priority: now** · **cron may continue** | Dogfood Now in Android under Forma | Primary OSS target [`android/nowinandroid`](https://github.com/android/nowinandroid). Design: [`docs/DOGFOOD-NIA.md`](docs/DOGFOOD-NIA.md). **Phase A+B+C Hilt+Room+Firebase+DataStore done:** spike green with Hilt Path A + Room Path B + Firebase Path A + **Preferences DataStore** UserData (`core-datastore-android-util`, `OfflineFirstUserDataRepository`, `FollowTopicUseCase`). Engine: KSP companion (F12) + `androidUtilTarget` (F15). Findings F16–F19. **Next phase C:** more features / WorkManager sync / Proto DataStore. No `androidLibrary`. | ## Backlog (lower priority / historical GitHub) diff --git a/docs/DOGFOOD-NIA.md b/docs/DOGFOOD-NIA.md index ad17e608..2f1a3ac7 100644 --- a/docs/DOGFOOD-NIA.md +++ b/docs/DOGFOOD-NIA.md @@ -1,6 +1,6 @@ # Dogfood: Now in Android → Forma (F-115) -**Status:** `in_progress` — phase C Hilt + Room + **Firebase Path A green** (more features next) +**Status:** `in_progress` — phase C Hilt + Room + Firebase + **DataStore Preferences green** (more features / sync next) **Upstream:** [android/nowinandroid](https://github.com/android/nowinandroid) (Apache-2.0) **Pinned checkout (local):** `/Users/claw/work/nowinandroid` @ `7d45eae` (main tip when cloned 2026-07-29) **Dogfood fork:** `/Users/claw/work/nowinandroid-forma` @@ -236,7 +236,22 @@ Workspace: same **`forma-spike`** external tree. | Verify | `forma-spike` `./gradlew :binary:assembleDebug` → **BUILD SUCCESSFUL** (268 tasks); `processDebugGoogleServices` + Crashlytics inject tasks green | | In-repo | Example **14** Path A companions aligned to `transitiveDeps` (same F17 lesson) | -**Still open in phase C:** remaining NiA features (foryou/bookmarks/search/settings), flavors, full designsystem, DataStore UserData, WorkManager sync. +**Still open in phase C (pre-DataStore):** remaining features, full designsystem, DataStore UserData, WorkManager sync. + +### Phase C — DataStore Preferences UserData ✅ (2026-07-30) + +| Step | Result | +|------|--------| +| Module | `core-datastore-android-util` — `hiltAndroidUtil` + Preferences DataStore | +| Source | `NiaPreferencesDataSource` (followed topic ids) + Hilt `DataStoreModule` (`PreferenceDataStoreFactory`) | +| Data | `OfflineFirstUserDataRepository` replaces in-memory UserData | +| Domain | `FollowTopicUseCase` so interests feature stays on domain only (no data types on feature classpath) | +| UI | Interests list Follow chip writes DataStore; topic detail already toggled via data | +| Companions | `transitiveDeps("androidx.datastore:datastore-preferences:1.1.7")` — **no** Gradle plugin (F18) | +| Verify | `forma-spike` `./gradlew :binary:assembleDebug` → **BUILD SUCCESSFUL** (291 tasks) | +| Deferred | Proto DataStore + `datastore-proto` (upstream NiA shape) — later if needed | + +**Still open in phase C:** remaining NiA features (foryou/bookmarks/search/settings), flavors, full designsystem, Proto DataStore parity, WorkManager sync. ### Phase D — Case study write-up @@ -262,6 +277,8 @@ Workspace: same **`forma-spike`** external tree. | F15 | 2026-07-30 | No public `androidUtil(type=)` before helper | Engine needed `androidUtilTarget` (like `resourcesTarget`) so Path B Room DSL can pass derived type + processor features | | F16 | 2026-07-30 | Hilt + Firebase both need Path A on binary | `TargetPluginRegistry` **accumulates** plugins per type (dedup by id). Thin `hiltFirebaseBinary` loads both binding objects then `androidBinary`. | | F17 | 2026-07-30 | Firebase SDKs via `.dep` / `deps()` non-transitive | Crashlytics/Analytics AARs resolve but **without** `firebase-common` → `FirebaseApp` unresolved on binary. **Fix:** type-owned companions use `transitiveDeps(...)` (BOM still `transitivePlatform`). Example 14 companions fixed the same way. | +| F18 | 2026-07-30 | DataStore has no structure Gradle plugin | Preferences DataStore is a **library stack** on `hiltAndroidUtil` (companions at call site). No Path A/B plugin id. Proto DataStore would add JVM `library` + serializer — deferred; Preferences enough to validate UserData edge + follow toggle. | +| F19 | 2026-07-30 | Feature VM → data types without matrix edge | interests.impl depended on domain only; injecting `UserDataRepository` failed KSP resolve. **Fix:** `FollowTopicUseCase` on domain — feature stays domain-facing (cleaner than adding data edge). | ## Local reference commands diff --git a/docs/GOOGLE-LIBRARIES.md b/docs/GOOGLE-LIBRARIES.md index e2abb98c..8d1dc9d0 100644 --- a/docs/GOOGLE-LIBRARIES.md +++ b/docs/GOOGLE-LIBRARIES.md @@ -64,7 +64,7 @@ usage** (not classpath-only comments). | Stack | Why | |-------|-----| | WorkManager | No sample job; add when a ticket needs background work | -| DataStore / Preferences | Sample uses simpler stores; add with a feature need | +| DataStore / Preferences | F-115 NiA spike: Preferences DataStore on `hiltAndroidUtil` (no Gradle plugin — library stack). Proto DataStore deferred | | CameraX / Media3 / Maps / Ads | Product-specific; not Forma meta-build teaching defaults | | Hilt | Sample teaches **Dagger + KSP**; Metro is alternate DI example | | Firebase Auth / Firestore / Remote Config / … | Crashlytics+Analytics establish the **plugin + BOM** pattern; expand per product need |