You are Worker F3 on the Bookshelf project (~/bookshelf). You are FINISHING wave 4. FIRST READ (contract — follow exactly, do not restate): ~/bookshelf/docs/SPEC.md ("Design language", "Screens", "Quality bar") ~/bookshelf/docs/HANDOFF.md (state + hazards already paid for — read the hazards) ## Where things actually stand (do not re-derive this; it is verified) Waves 1-3 are DONE. Wave 4 was launched once and both workers were killed ~11 minutes in by the 5h session quota plus a sprite suspend. Their partial work is COMMITTED and verified green at `a4adf83`: `assembleDebug` + `testDebugUnitTest` pass, 94 tests, 0 failures. Already done, DO NOT redo: - The live-server sync test is FINISHED and PASSING against the real PocketBase -- auth, push with client-generated ids, pull, last-write-wins, tombstones, and the cover byte-for-byte round-trip. That was wave 4's biggest risk and it is closed. `server/live-sync-test.sh` + `org.modg.bookshelf.livesync.LiveSyncTest`. LEAVE BOTH ALONE, and leave `server/` alone entirely. - Library screen screenshots (populated + empty, light + dark) and the reusable `app/app/src/test/java/org/modg/bookshelf/ui/screens/ScreenFixtures.kt`. FOLLOW that file's patterns; do not invent a second approach. ## Your scope — four tasks, in this order 1. **Fix the settings-email gap FIRST** (it changes what task 2 renders). Settings currently shows the PocketBase user id instead of the signed-in email, because `AuthRepository`/`SettingsStore` never persist the email at login. Persist it on successful login and show it in Settings. Small, surgical change -- do not redesign auth. Add/extend a unit test that actually asserts the email is persisted. 2. **Paparazzi screenshots for the five REMAINING screens** -- setup, detail, scan, locations, settings -- each in BOTH light and dark, with realistic populated state (a plausible shelf of books, placeholder cover art), not empty states. The library screen is already done. The scan screen cannot show a live camera in Paparazzi: render its overlay/reticle and the result bottom sheet over a static backdrop, and SAY SO in your report. 3. **Release signing + signed APK.** Generate a release keystore, wire a signingConfig into `app/app/build.gradle.kts`, produce a signed release APK. The keystore and its passwords MUST be gitignored -- credentials in `app/keystore.properties` (gitignored), read from the build file, with a graceful fallback so the build still works for anyone WITHOUT the keystore. State the passwords in your report so the owner can rebuild. `minifyEnabled` is false today: if you enable R8 you must PROVE the signed APK still builds and that Room/Retrofit/kotlinx-serialization/ML Kit survive it. If you cannot prove it, leave R8 OFF and say so. Leaving it off is an acceptable answer. 4. **Top-level `README.md`** -- what this is, the two-person shared-library model, architecture (offline-first Room + PocketBase, push-then-pull last-write-wins sync), how to build, how to deploy the server (point at `server/deploy/`), how to install the APK, and an honest "current limitations" section. SPEC requires the LWW conflict rule be documented here. Reuse real content from `server/README.md` and `docs/SPEC.md`; do not contradict them. Include that the app has never run on a physical device. ## Boundaries - You are the ONLY worker running. No file-ownership conflicts this time. - Do NOT touch `server/`, `LiveSyncTest.kt`, or `live-sync-test.sh`. - Do NOT weaken or delete existing tests to get green. 94 tests pass now; that number must not go DOWN. - Do not modify the six screens' behavior just to make them easier to screenshot. If a screen is hard to render in isolation, that is a finding to REPORT, not a licence to restructure it. (Task 1 is the one deliberate exception, and it is a data-layer fix.) ## Build/verify — use the serialized wrapper, never ./gradlew directly ~/bookshelf/tasks/gw assembleDebug ~/bookshelf/tasks/gw testDebugUnitTest ~/bookshelf/tasks/gw recordPaparazziDebug ~/bookshelf/tasks/gw assembleRelease ## Definition of done — actually run these, WAIT for them, report REAL exit codes 1. All four commands exit 0. `testDebugUnitTest` has ZERO failures and >= 94 tests. 2. Screenshot PNGs exist on disk for all SIX screens x light/dark. List their paths. 3. A signed release APK exists. Give its exact path, size, and the output of `~/toolchain/android-sdk/build-tools/37.0.0/apksigner verify --print-certs ` (or an explanation if that tool is unavailable). 4. `git status` shows NO keystore and NO keystore.properties as tracked/untracked-to-be -committed. Verify it and say so explicitly. 5. Do NOT run `git commit` yourself. Leave the work in the working tree; the orchestrator verifies and commits. (Hazard #7.) ## Do not repeat an earlier worker's mistake A worker once ended its turn saying "tests are running in the background, I'll report when done." That is a FAILURE. Run it, WAIT, report observed exit codes. A truthfully reported gap is worth far more than a false green. If you run out of room, STOP and report exactly which of the four tasks are complete and which are not -- a partial result you describe accurately is recoverable; a false claim of completion is not. ## Report (short — read by a token-constrained orchestrator) - real exit codes for all four commands, and the test count - the screenshot PNG paths, the signed APK path + size + signer info - which of the four tasks are DONE and which are not - anything in SPEC's design language you think the screens get WRONG, now that you can finally see them rendered. Be candid — the owner explicitly cares how this looks.