=== M-authexpiry-fix attempts=1 quota_waits=0 hard_fails=0 === cost=$1.3351339999999998 turns=44 err=? --- result (tail) --- ar onlineSearchJob` to `internal var onlineSearchJob`, matching the file's existing convention (same reasoning already documented on `performOnlineSearch`) of loosening visibility so tests can synchronize on it directly. - `app/app/src/test/java/org/modg/bookshelf/ui/library/LibraryViewModelTest.kt`: after `gate.countDown()`, added `vm.onlineSearchJob?.join()` so the test genuinely waits for the cancelled job to finish before returning, with a comment explaining why. No changes to the feature logic, SPEC, build files, or anything else — nothing else in the gate's failure pointed at the auth-expiry implementation itself. **Verification:** - `assembleDebug` → exit 0. - `testDebugUnitTest` → exit 0, reran 4 more times with `--rerun` after the fix, all clean (previously failed on run 2 of 2 before the fix). - Test count: 355 passed, 2 skipped, 0 failures (baseline was 337) — via summed XML. - `verifyPaparazziDebug` → exit 0. - Recorded the 4 new Paparazzi snapshots (`library-auth-expired-{light,dark}`, `settings-auth-expired-{light,dark}`) and viewed all four PNGs: library grid shows the "Signed out — sign in again to sync" sync bar; settings shows "Your session expired. Sign in again." with a "Sign in" button. Both match spec's design language in light and dark, and `git status` confirmed no other snapshots were touched by the record run. - Grepped a forced recompile for Kotlin warnings in touched files: none. - Final full sequence run in order (assembleDebug → testDebugUnitTest → verifyPaparazziDebug): all exit 0. I did not re-review the original worker's auth-expiry design/logic (token refresh, full re-pull, AuthExpired propagation) since none of that was implicated by the gate failure — per instructions, I only touched what was making the gate red.