Room entities/DAOs/DB, PocketBase Retrofit client + auth interceptor, SyncEngine (push-then-pull, LWW, tombstones, client-generated ids), SettingsStore, AppContainer. Open Library + Google Books merge, ISBN validation, CameraX + ML Kit scanner plumbing. Verified by orchestrator: assembleDebug exit 0; testDebugUnitTest exit 0, 68 tests, 0 failures, 0 errors. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bThmkmyUUdqQpy3MXFFe5
54 lines
3.1 KiB
Plaintext
54 lines
3.1 KiB
Plaintext
You are Worker C on the Bookshelf project (~/bookshelf). Implement the DATA LAYER.
|
|
|
|
FIRST, READ THESE — they are the contract, follow them exactly, do not invent
|
|
alternative names or restate them back to me:
|
|
~/bookshelf/docs/SPEC.md (authoritative product/technical spec)
|
|
~/bookshelf/docs/HANDOFF.md (operational state and gotchas already paid for)
|
|
|
|
## Your scope — these packages ONLY, under app/app/src/main/java/org/modg/bookshelf/
|
|
data.local Room: BookEntity/BookcaseEntity/ShelfEntity, SyncState, Converters,
|
|
BookDao/BookcaseDao/ShelfDao, BookshelfDatabase
|
|
data.remote PocketBaseApi (Retrofit), request/response DTOs, PbAuthInterceptor
|
|
data.repo BookRepository, LocationRepository, AuthRepository, SyncEngine
|
|
data.prefs SettingsStore (DataStore: server URL, auth token, per-collection
|
|
sync cursors, last-sync time)
|
|
Plus `AppContainer` (manual DI, per SPEC "NO Hilt/kapt") and its wiring into
|
|
the existing BookshelfApplication.kt.
|
|
|
|
## HARD BOUNDARIES — you share this repo with Worker D, running right now
|
|
- DO NOT create or edit anything under `data.metadata`, `ui.scan`, or any `ui.*`
|
|
package. Those are Worker D's / wave 3's. Touching them WILL cause a conflict.
|
|
- DO NOT edit `app/build.gradle.kts` or `gradle/libs.versions.toml`. Every
|
|
dependency you need (room+ksp, retrofit, kotlinx-serialization, okhttp,
|
|
datastore, work-runtime, robolectric, coroutines-test) is ALREADY declared and
|
|
wired. If you genuinely believe something is missing, DO NOT add it — say so in
|
|
your final report and work around it.
|
|
- Worker D will need metadata lookup reachable from AppContainer. Do NOT try to
|
|
wire it. Just leave AppContainer easy to extend; D exposes a plain class that
|
|
gets wired later.
|
|
|
|
## Build/verify — CRITICAL
|
|
Never run `./gradlew` directly; a second worker builds concurrently and you will
|
|
corrupt each other's build. ALWAYS build with the serialized wrapper:
|
|
~/bookshelf/tasks/gw assembleDebug
|
|
~/bookshelf/tasks/gw testDebugUnitTest
|
|
It takes the lock and may block until the other worker's build finishes. That is
|
|
expected — wait for it, do not bypass it.
|
|
|
|
## Definition of done — all must actually pass, verified by you, not assumed
|
|
1. `~/bookshelf/tasks/gw assembleDebug` exits 0.
|
|
2. `~/bookshelf/tasks/gw testDebugUnitTest` exits 0.
|
|
3. Real unit tests with real assertions (SPEC: "Do not write assertion-free tests"):
|
|
- SyncEngine conflict resolution / last-write-wins on `updated`
|
|
- push ordering + syncState transitions, incl. 404-on-update -> drop local,
|
|
409/duplicate-id -> switch to PATCH
|
|
- client-side 15-char lowercase-alnum id generation
|
|
- DAO queries via Robolectric, proving `deleted = 0` filtering works
|
|
4. Soft delete everywhere. All reads come from Room. Nothing blocks on network.
|
|
|
|
## Report back (keep it short — it is read by a token-constrained orchestrator)
|
|
- exact pass/fail of the two gradle commands above
|
|
- files created, one line each
|
|
- anything in SPEC.md you could NOT satisfy, and why. Do not paper over gaps:
|
|
a truthfully reported gap is worth more than a false green.
|