Completes wave 4. Verified by the orchestrator, not self-reported:
assembleDebug / testDebugUnitTest / assembleRelease all exit 0;
102 tests, 1 skipped, 0 failures, 0 errors.
- Settings showed the PocketBase user id instead of the signed-in email,
because login never persisted the email. AuthRepository now writes it to
SettingsStore on success and sign-out clears it; SettingsUiState carries
userEmail in place of userId. AuthRepositoryTest asserts both directions.
- Paparazzi coverage for the five screens library was missing: setup, detail,
scan, locations, settings, each light + dark, populated rather than empty.
Scan cannot show a live camera under Paparazzi, so its tests render the
reticle overlay and the result bottom sheet over a static backdrop.
- Release signing via an optional gitignored app/keystore.properties. Without
it assembleRelease still works and comes out debug-signed, so the build is
not owner-only. R8 deliberately left off; nothing has proven Room, Retrofit,
kotlinx-serialization and ML Kit survive it.
- Top-level README: shared-library model, offline-first architecture, the
push-then-pull last-write-wins conflict rule SPEC requires be documented
here, build/deploy/install steps, and honest current limitations.
The signed APK and the keystore are intentionally not committed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014TyzeWmdTqi7U85iYNGy7P
Both wave-4 workers hit the 5h session limit ~11 minutes in and were then lost
to a sprite suspend. This commit preserves the work that landed before that,
independently verified green (assembleDebug + testDebugUnitTest, 94 tests).
F1-livesync:
- LiveSyncTest + server/live-sync-test.sh: end-to-end exercise against a real
PocketBase (auth, push with client ids, pull, tombstones, cover round-trip).
Gated behind LIVE_SYNC=1 so the normal test task stays green with no server.
- Fix: BookDto.authors must be nullable. PocketBase serializes an unset `json`
field as literal null (unlike text/number, which come back ""/0), so decoding
any real response with empty authors threw. Found by the live test; no fake
had ever reproduced it.
- Fix: cover upload derived its media type from the filename instead of
hardcoding image/jpeg.
F2-release:
- ScreenFixtures + LibraryScreenPaparazziTest: library populated and empty,
light and dark (4 PNGs).
Still owed by wave 4: screenshots for the other five screens, release keystore
+ signed APK, top-level README.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016mTs3kQXQsQwonXpEq7aEw
Nav graph, setup with distinct URL-vs-credential errors, locations tree with reorder
and bulk move, settings; library grid with search/sort/filter, detail with soft-delete
undo, continuous scan with duplicate-ISBN warning.
Verified by orchestrator: assembleDebug exit 0; testDebugUnitTest exit 0,
91 tests, 0 failures, 0 errors (68 -> 91).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>