docs: first on-device test results and metadata-source research
Records the coil3 StateFlow trap (a Kotlin warning, not an error, that silently blanked every book cover) so a future session greps for it, and the two Open Library cover defects behind it. METADATA-SOURCES.md answers the user's research question about alternative lookup sources: measurements over a 60-ISBN sample drawn from a third-party catalogue, the options with costs, and a recommendation to fix diagnosis before buying coverage. Nothing there is implemented — the user asked to be consulted first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CDcPottghJXEvfYKqFM7zf
This commit is contained in:
@@ -285,3 +285,52 @@ library, scaffold — each light + dark).
|
||||
survive minification.
|
||||
4. Still-open user questions, unchanged: where the server will actually live, and
|
||||
the two account emails for `create-user.sh`.
|
||||
|
||||
## First on-device test — 2026-09-09
|
||||
The user installed the signed APK on a real phone. It runs. This closes the
|
||||
"never been run" gap that waves 1-4 all carried. Six issues came back; five were
|
||||
fixed directly by the orchestrator in commit `356f639` (they were small, and
|
||||
spinning up Sonnet workers for two-line Compose edits costs more than it saves).
|
||||
|
||||
**The one worth remembering** — `BookCover` branched on `painter.state`, but in
|
||||
coil3 that is a `StateFlow<State>`, not a `State`. Every `is
|
||||
AsyncImagePainter.State.X` arm was therefore always false, and because a `when`
|
||||
used as a statement needs no `else`, it compiled clean and drew NOTHING — no
|
||||
cover, no placeholder, no error icon. Kotlin emitted "Check for instance is
|
||||
always 'false'" as a *warning* on four consecutive lines and the build stayed
|
||||
green. **Grep the build log for `always 'false'` before accepting a wave**; that
|
||||
warning class is a silent-dead-code detector and this build had it for months.
|
||||
|
||||
Two more cover defects sat behind it, both verified against the live service:
|
||||
- `covers.openlibrary.org/b/isbn/{isbn}-L.jpg` answers **200 with a 43-byte 1x1
|
||||
transparent GIF** for an edition with no art. Any image loader calls that a
|
||||
successful load. Only `?default=false` turns a miss into a 404.
|
||||
- OL's DTO synthesized that URL unconditionally, so `MetadataMerger`'s
|
||||
fill-blanks rule could never reach Google Books' thumbnail. The SPEC'd cover
|
||||
fallback was dead code. Cover URLs now come from OL's own `cover` object.
|
||||
|
||||
Also fixed: sync bar clipped by rounded display corners (now owns its
|
||||
navigation-bar inset, wider horizontal padding, moved into Scaffold's `bottomBar`
|
||||
slot); setup screen's Password field hidden behind the IME (`safeDrawingPadding`
|
||||
outside `verticalScroll`, plus Next/Next/Done IME actions and
|
||||
`windowSoftInputMode=adjustResize`); library card titles reflowed (20sp leading,
|
||||
author gets its own 4dp gap); scan sheet now names the ISBN and says
|
||||
"Searching…" instead of showing a bare spinner.
|
||||
|
||||
| Check | Result |
|
||||
|---|---|
|
||||
| `./tasks/gw assembleDebug` | exit 0 |
|
||||
| `./tasks/gw testDebugUnitTest` | exit 0 — 106 tests, 1 skipped, 0 failures |
|
||||
| `./tasks/gw verifyPaparazziDebug` | exit 0 against re-recorded snapshots |
|
||||
| `./tasks/gw assembleRelease` | exit 0 — 41,777,376 bytes |
|
||||
| `apksigner verify` | V2 signer `CN=Bookshelf, O=Montanaro` — real release key |
|
||||
|
||||
### Open, not started: metadata coverage
|
||||
The user reported 1 of 3 scans resolving, and asked for **research, not a
|
||||
change**. Findings are in `docs/METADATA-SOURCES.md`. Headline: Open Library
|
||||
answered 88% of a 60-ISBN sample, keyless Google Books returned **429 on 60 of
|
||||
60** requests, and both clients collapse every non-200 into `null` — so a
|
||||
rate-limited lookup reaches the user as "No match found." Recommended order is a
|
||||
free Google Books API key, then distinguishing "couldn't ask" from "not found",
|
||||
then retry/backoff, before adding any new source. **Awaiting the user's decision;
|
||||
do not implement unasked.**
|
||||
|
||||
Reference in New Issue
Block a user