Align TV fidelity and recovery behavior #37

Merged
justinzeus merged 2 commits from fm/tv-fidelity-followups into main 2026-11-06 02:35:14 +01:00
Owner

Outcome

Close the reproducible TV fidelity offsets and the specified small behavior gaps before the next test build. The locked prototype and TV specification remain the acceptance criteria. Platform Roboto and the prototype's baked-in CSS behavior are retained; no per-title compensation is added.

AI-assisted (fork-internal) — the fork-internal AI policy waiver applies.

Visible fidelity

Measurements are native 1920×1080 at density 2.0. Row/box coordinates are separate from glyph ink. Reviewer references below name the supplied Sonnet review reports, linked to the corresponding screen pull requests.

What Reviewer evidence Before → after; locked reference
Discover request/receipt stacks Discover review, N1: person rows and receipt panel 3–4 px high st-071 flat row fills at x=1200: 326–423 → 330–427, 444–541 → 448–545, 562–659 → 566–663; references 330–427 / 448–545 / 566–663. Focused Request fill top at x=1280: 689 → 693, reference 693. st-074 flat receipt panel: 266–457 → 270–461, reference 270–460. The inherited inline ratings strut supplies the missing descent; title/subtitle use the existing exact line-box engine.
Shared Library/Discover page heading Discover N2: heading ink 3–4 px high st-036 heading ink rows 161–209 → 165–213, reference 164–213. The CSS line box is restored locally, without changing shared Type tokens. Library and Discover collection/service captures use the same corrected component.
Settings text behind Requests Requests re-review: Settings text 2–5 px low st-091 second-row title ink 396–419 → 394–417, reference 393–415. Subtitle ink 430–452 → 432–454, reference 429–452. Both text boxes now retain CSS leading; residual subtitle glyph ink is +3 top/+2 bottom with Roboto. Row bounds, pitch, icons and pills do not move.
Neutrality for approved Home/caption pairs Home re-review, shared Type/component neutrality requirement 23/23 Home native captures byte-identical before/after the visual changes; st-033 also byte-identical. No Type, Home, caption, avatar-color, separator-color or focus token changes. Library pixel changes are confined to the heading; Requests changes are confined to the Settings background text, not the sheet.

The supplied tv-slice2-shell/compare.py implementation generated the full native pairs and the same numeric columns: mean absolute RGB error, pixels over 12 RGB, and nav mean RGB error. Its output/capture directories and state lists were selected for these screen families. Exact RGB summaries and pairs live with the task proof below; they are measurements, not an automatic visual approval.

Native frame Mean RGB before → after Pixels >12 RGB before → after Nav mean RGB
st-036 heading 3.8713 → 3.7966 2.6715% → 2.6400% 5.8569
st-071 request 10.3027 → 9.5267 16.2917% → 15.5011% 5.1036
st-074 receipt 10.9910 → 10.7864 16.4929% → 16.3105% 5.1036
st-033 caption neutrality 4.2999 → 4.2999 5.6580% → 5.6580% 6.0718

Existing accepted font-only differences remain named: the narrower request subtitles in st-073/st-080/st-110 remove one 36.4 px body line; st-074's previously approved omission of the prototype-only Simulated prefix removes one 31.2 px caption line. The Titles review measured st-062's recovery body as one native line versus two reference lines, with button fill top 322 versus 357.6 (−35.6 px). No font substitution or per-title offset is introduced.

Behavior

What Reviewer/spec evidence Verification / result
Home ratings cache identity Home follow-up; spec 7.8 requires separate title and (series, season) caches HomeRatingCacheTest.episodeScoresShareSeriesSeasonIdentityWithoutCrossingEpisodesOrSeasons and seasonCapacityCountsSeasonsNotEpisodesAndIsIndependentOfTitleCapacity failed before the fix and pass after it. A season retains episode-specific scores/timestamps; another Jellyfin UUID for the same series/season/episode finds the observation. Different episodes/seasons never borrow its score. Six-hour expiry and independent 300-title/300-season limits remain.
Held OK guard Home follow-up; spec 7.1 ignores positive repeats The requested real-event test already exists: HomeKeysTest.heldOkRepeatEventsDoNotReplayButtonsOrActivateCardsBeforeRelease dispatches repeatCount=3 and passes. It checks one button activation and no card activation until release. No duplicate test or weaker assertion was added.
Libraries progressive publication Libraries follow-up; spec 6.4/8 read 200-item chunks LibraryReadFacadeTest.firstTwoHundredTitlesPublishWhileTheNextChunkIsSuspended proves 200 titles publish while the later SDK call waits, then verifies deduplication and the complete disk copy. LibraryProgressiveSurfaceTest.firstChunkPaintsAndAcceptsRemoteInputBeforeTheLastChunk renders the real host, moves focus with a remote key before the final chunk, and keeps the exact title after a new title sorts ahead of it. Native proof: library-first-chunk.png.
Complete saved-copy retention Progressive publication must not replace a complete saved view with a partial refresh Existing LibrarySnapshotStoreTest assertions remain. New failedLaterChunkKeepsTheCompleteSavedCopyOrTheColdPartialWithoutSavingIt proves saved-copy retention and that a cold partial remains usable with a retry tail but is not persisted. Loading-focus publication also respects intervening nav input.
Canonical catalogue row key Libraries follow-up: media type and TMDB identity, not an untyped numeric ID LibraryKeysTest.mixedCatalogueRowsKeepMovieAndSeriesWithTheSameNumericIdentityDistinct renders rows whose movie and series share numeric IDs, navigates to the series and opens the correct title. Row keys now match the cards' canonical identity.
Show again versus Undo Discover N8; spec 6.3.1 announces Show again, not Undo DiscoverKeysTest.notInterestedInEightPressesAndUndoRestoresEveryIndex keeps every original assertion and adds silent-Undo coverage. showAgainRestoresTheHiddenPickAndAnnouncesItsReturn drives real keys through Hidden picks and checks the announcement. Title pages retain ownership of their own toast, avoiding a duplicate adapter toast.
Saved Discover recovery caption States review, N1: “Try again stopped loading” The lane is now More picks, so the existing tail says “More picks stopped loading”. Inspected the real RecoveryCaptureTest saved-Discover capture; the retry action remains Try again.
Durable design done-bar check States N2: the old audit lived outside the repository OwnedSourceAuditTest runs in the design JVM task already required by make test. It scans owned Kotlin sources for untokened dp/sp conversions, numeric Color constructors, generated font sizes below 12 sp, raw household library labels and pagination wording. plantedViolationsFailEachDoneBarRule covers 13 negative cases; ownedScreensUseTokensReadableTextAndViewerFacingNames audits the real sources. Existing rendered-font/wording checks remain.

Small wiring hygiene

What Reviewer evidence Verification / result
Keep the uncertain-submission ledger during signed-in People retry Wiring review, non-blocking item 2 ConductarrAudienceRecoveryTest.retryingSignedInPeopleKeepsTheUncertainSubmissionLedger uses real local HTTP replies: an uncertain 503 POST, People retry, then the same request still yields one POST, not a second submission. Signed-out identities still rebuild; changed credentials/person/URL still select a new identity.
Authorize Home by saved Jellyfin user ID Wiring non-blocking item 5: operator/name changes could hide the viewer's own Jellyfin rows HomeRecoveryTest.renamedHouseholdProfileKeepsItsOwnJellyfinLibraryWithoutAConductarrIdentity keeps the viewer's library with a renamed household key and no Conductarr identity, then verifies a different saved Jellyfin user ID fails closed even with the matching display key. All affected Home callers migrate to the person model.

docker/README.md documents the layouts, progressive/saved publication, cache identity, retry safety and durable checks. No existing assertion is weakened or removed.

Not done

Item Reason / evidence
Another shared caption-facts shift The old Discover N2/Library −3 px finding does not reproduce on merged main after Titles' exact-line-box changes. st-033 reference ink is 670–693, current native 672–694; this branch leaves it byte-identical. No second compensation is applied.
Uniform Home +1–2 px residual No reproducible new box/rhythm defect; leave the already-approved 23 Home captures unchanged. The Settings subtitle glyph residual is quantified above rather than hidden.
A new held-OK repeat test Already present and exercised; no duplicate test added.
LatestNextUpService adoption Explicitly optional in the brief. It carries removed-series/preference/filter behavior and different field selection, so it is not a trivial SDK substitution.
Remaining wiring observations Items 1/3/4/6/7/8/9 remain: coarse request ledger/retired-request semantics; identity behavior after a failed/protected person switch; sequential per-series Home lookups/reload churn; old-token disk cleanup; 403 handling; unavailable-versus-sign-in on first-run outage; live capability refresh. These are not silently folded into a small fidelity patch.
Other review observations outside the named gap set No expansion into debug per-person fixture persistence, empty-hero focus, tall Media info scrolling, pre-31 blur, or new screenshot regression infrastructure. Several old “unused live adapter” and title press-path observations were already superseded by the merged wiring/title slices.
Unheld trailers Still absent until Conductarr supplies the trailer field, as ruled.
Device/release work No ADB, install, device driving, signing, release, version bump, server mutation or Conductarr release. Native proof is Robolectric, not a claim about the physical TV.

Proof location

/root/.treehouse/firstmate-7bab20/2/firstmate/data/tv-fidelity-followups/

  • geometry.md, before/, visual-after/, visual-comparisons/, final-native/, final-comparisons/, final-native-manifest.json
  • Native reference/before/after strips for st-071, st-074 and st-091
  • library-first-chunk.png, discover-saved.png, behavioral result records

The next Sonnet review is one round, blocking only for breaking behavior or a visible deviation. Merge authority remains with Justin; this PR does not merge itself.

Commands and results

Final head: 81073c410d8118d892e60e9cf6c0d0c97ef710cf. git fetch origin main && git merge --no-edit origin/main completed before the final gate pair; main was already current.

Command / scenario Result
Scoped native baseline and recapture through :wolfskin-design:testDebugUnitTest Passed; original comparison script, native pairs and independent ink/box probes recorded above.
Scoped ratings, held-OK, progressive SDK/saved-copy/native-library, Discover and wiring scenarios Passed. The two new cache regressions failed before the cache change.
make test on final head (one invocation) PASS, 2m57s. 665 app + 173 design + 17 client = 855 tests, zero failures/errors/skips. The client smoke also passed: local HTTP profile read → disk reopen → ETag 304 → 503 retains the saved profile, three requests. Gradle reused unchanged design/client test results where up-to-date.
make apk-debug on the same final head (one invocation) PASS, 1m03s Gradle / 68s wall. Produced universal, arm64-v8a, armeabi-v7a and x86_64 debug APKs. Application ID org.justinvisser.wolfskin.tv.debug; existing versionCode remains 64. No install or release was performed.
Final native neutrality check 23/23 Home PNGs and st-033 byte-identical against the untouched baseline. Full comparison reports regenerated under final-comparisons/; PNG SHA-256 manifest records the final head.
Checkout after gates Clean. No proof/scratch files are staged or committed.

An earlier full gate on 04b1bdd6 found the new native progressive test reading the title immediately after its source-size wait (665 app tests, one focus assertion failure). The final commit keeps both exact assertions and runs them through Compose runOnIdle, after UI publication. The full gate then passed on 81073c41; no assertion or scenario was removed. Earlier implementation runs also exposed and corrected the test fixture's SDK overload matcher; a fail-fast source-error assertion prevents that mismatch from hiding behind a deferred wait.

Proof includes final-make-test.log, final-make-apk-debug.log, final-test-counts.json, final JUnit XMLs and APK checksums. Existing build warnings remain: missing optional Media3/MPV binaries use the configured stub, upstream deprecations/configuration-time classpath resolution, codec diagnostics and GC allocation warnings. They did not fail either final gate.

## Outcome Close the reproducible TV fidelity offsets and the specified small behavior gaps before the next test build. The locked [prototype](https://pages.justinvisser.org/wolfskin/tv-prototype-v2-opus/) and [TV specification](https://pages.justinvisser.org/wolfskin/tv-spec) remain the acceptance criteria. Platform Roboto and the prototype's baked-in CSS behavior are retained; no per-title compensation is added. **AI-assisted (fork-internal)** — the fork-internal AI policy waiver applies. ## Visible fidelity Measurements are native 1920×1080 at density 2.0. Row/box coordinates are separate from glyph ink. Reviewer references below name the supplied Sonnet review reports, linked to the corresponding screen pull requests. | What | Reviewer evidence | Before → after; locked reference | | --- | --- | --- | | Discover request/receipt stacks | [Discover review](https://git.justinvisser.org/justinzeus/wolfskin/pulls/33), N1: person rows and receipt panel 3–4 px high | st-071 flat row fills at x=1200: 326–423 → **330–427**, 444–541 → **448–545**, 562–659 → **566–663**; references 330–427 / 448–545 / 566–663. Focused Request fill top at x=1280: 689 → **693**, reference 693. st-074 flat receipt panel: 266–457 → **270–461**, reference 270–460. The inherited inline ratings strut supplies the missing descent; title/subtitle use the existing exact line-box engine. | | Shared Library/Discover page heading | Discover N2: heading ink 3–4 px high | st-036 heading ink rows 161–209 → **165–213**, reference **164–213**. The CSS line box is restored locally, without changing shared Type tokens. Library and Discover collection/service captures use the same corrected component. | | Settings text behind Requests | [Requests re-review](https://git.justinvisser.org/justinzeus/wolfskin/pulls/32): Settings text 2–5 px low | st-091 second-row title ink 396–419 → **394–417**, reference 393–415. Subtitle ink 430–452 → **432–454**, reference 429–452. Both text boxes now retain CSS leading; residual subtitle glyph ink is +3 top/+2 bottom with Roboto. Row bounds, pitch, icons and pills do not move. | | Neutrality for approved Home/caption pairs | [Home re-review](https://git.justinvisser.org/justinzeus/wolfskin/pulls/31), shared Type/component neutrality requirement | **23/23 Home native captures byte-identical** before/after the visual changes; st-033 also byte-identical. No Type, Home, caption, avatar-color, separator-color or focus token changes. Library pixel changes are confined to the heading; Requests changes are confined to the Settings background text, not the sheet. | The supplied `tv-slice2-shell/compare.py` implementation generated the full native pairs and the same numeric columns: mean absolute RGB error, pixels over 12 RGB, and nav mean RGB error. Its output/capture directories and state lists were selected for these screen families. Exact RGB summaries and pairs live with the task proof below; they are measurements, not an automatic visual approval. | Native frame | Mean RGB before → after | Pixels >12 RGB before → after | Nav mean RGB | | --- | ---: | ---: | ---: | | st-036 heading | 3.8713 → 3.7966 | 2.6715% → 2.6400% | 5.8569 | | st-071 request | 10.3027 → 9.5267 | 16.2917% → 15.5011% | 5.1036 | | st-074 receipt | 10.9910 → 10.7864 | 16.4929% → 16.3105% | 5.1036 | | st-033 caption neutrality | 4.2999 → 4.2999 | 5.6580% → 5.6580% | 6.0718 | Existing accepted font-only differences remain named: the narrower request subtitles in st-073/st-080/st-110 remove one 36.4 px body line; st-074's previously approved omission of the prototype-only Simulated prefix removes one 31.2 px caption line. The Titles review measured st-062's recovery body as one native line versus two reference lines, with button fill top 322 versus 357.6 (−35.6 px). No font substitution or per-title offset is introduced. ## Behavior | What | Reviewer/spec evidence | Verification / result | | --- | --- | --- | | Home ratings cache identity | Home follow-up; spec 7.8 requires separate title and (series, season) caches | `HomeRatingCacheTest.episodeScoresShareSeriesSeasonIdentityWithoutCrossingEpisodesOrSeasons` and `seasonCapacityCountsSeasonsNotEpisodesAndIsIndependentOfTitleCapacity` failed before the fix and pass after it. A season retains episode-specific scores/timestamps; another Jellyfin UUID for the same series/season/episode finds the observation. Different episodes/seasons never borrow its score. Six-hour expiry and independent 300-title/300-season limits remain. | | Held OK guard | Home follow-up; spec 7.1 ignores positive repeats | The requested real-event test already exists: `HomeKeysTest.heldOkRepeatEventsDoNotReplayButtonsOrActivateCardsBeforeRelease` dispatches repeatCount=3 and passes. It checks one button activation and no card activation until release. No duplicate test or weaker assertion was added. | | Libraries progressive publication | Libraries follow-up; spec 6.4/8 read 200-item chunks | `LibraryReadFacadeTest.firstTwoHundredTitlesPublishWhileTheNextChunkIsSuspended` proves 200 titles publish while the later SDK call waits, then verifies deduplication and the complete disk copy. `LibraryProgressiveSurfaceTest.firstChunkPaintsAndAcceptsRemoteInputBeforeTheLastChunk` renders the real host, moves focus with a remote key before the final chunk, and keeps the exact title after a new title sorts ahead of it. Native proof: `library-first-chunk.png`. | | Complete saved-copy retention | Progressive publication must not replace a complete saved view with a partial refresh | Existing `LibrarySnapshotStoreTest` assertions remain. New `failedLaterChunkKeepsTheCompleteSavedCopyOrTheColdPartialWithoutSavingIt` proves saved-copy retention and that a cold partial remains usable with a retry tail but is not persisted. Loading-focus publication also respects intervening nav input. | | Canonical catalogue row key | Libraries follow-up: media type and TMDB identity, not an untyped numeric ID | `LibraryKeysTest.mixedCatalogueRowsKeepMovieAndSeriesWithTheSameNumericIdentityDistinct` renders rows whose movie and series share numeric IDs, navigates to the series and opens the correct title. Row keys now match the cards' canonical identity. | | Show again versus Undo | Discover N8; spec 6.3.1 announces Show again, not Undo | `DiscoverKeysTest.notInterestedInEightPressesAndUndoRestoresEveryIndex` keeps every original assertion and adds silent-Undo coverage. `showAgainRestoresTheHiddenPickAndAnnouncesItsReturn` drives real keys through Hidden picks and checks the announcement. Title pages retain ownership of their own toast, avoiding a duplicate adapter toast. | | Saved Discover recovery caption | [States review](https://git.justinvisser.org/justinzeus/wolfskin/pulls/35), N1: “Try again stopped loading” | The lane is now **More picks**, so the existing tail says “More picks stopped loading”. Inspected the real `RecoveryCaptureTest` saved-Discover capture; the retry action remains Try again. | | Durable design done-bar check | States N2: the old audit lived outside the repository | `OwnedSourceAuditTest` runs in the design JVM task already required by `make test`. It scans owned Kotlin sources for untokened dp/sp conversions, numeric Color constructors, generated font sizes below 12 sp, raw household library labels and pagination wording. `plantedViolationsFailEachDoneBarRule` covers 13 negative cases; `ownedScreensUseTokensReadableTextAndViewerFacingNames` audits the real sources. Existing rendered-font/wording checks remain. | ## Small wiring hygiene | What | Reviewer evidence | Verification / result | | --- | --- | --- | | Keep the uncertain-submission ledger during signed-in People retry | [Wiring review](https://git.justinvisser.org/justinzeus/wolfskin/pulls/36), non-blocking item 2 | `ConductarrAudienceRecoveryTest.retryingSignedInPeopleKeepsTheUncertainSubmissionLedger` uses real local HTTP replies: an uncertain 503 POST, People retry, then the same request still yields **one POST**, not a second submission. Signed-out identities still rebuild; changed credentials/person/URL still select a new identity. | | Authorize Home by saved Jellyfin user ID | Wiring non-blocking item 5: operator/name changes could hide the viewer's own Jellyfin rows | `HomeRecoveryTest.renamedHouseholdProfileKeepsItsOwnJellyfinLibraryWithoutAConductarrIdentity` keeps the viewer's library with a renamed household key and no Conductarr identity, then verifies a different saved Jellyfin user ID fails closed even with the matching display key. All affected Home callers migrate to the person model. | `docker/README.md` documents the layouts, progressive/saved publication, cache identity, retry safety and durable checks. No existing assertion is weakened or removed. ## Not done | Item | Reason / evidence | | --- | --- | | Another shared caption-facts shift | The old Discover N2/Library −3 px finding **does not reproduce on merged main** after Titles' exact-line-box changes. st-033 reference ink is 670–693, current native 672–694; this branch leaves it byte-identical. No second compensation is applied. | | Uniform Home +1–2 px residual | No reproducible new box/rhythm defect; leave the already-approved 23 Home captures unchanged. The Settings subtitle glyph residual is quantified above rather than hidden. | | A new held-OK repeat test | Already present and exercised; no duplicate test added. | | LatestNextUpService adoption | Explicitly optional in the brief. It carries removed-series/preference/filter behavior and different field selection, so it is not a trivial SDK substitution. | | Remaining wiring observations | Items 1/3/4/6/7/8/9 remain: coarse request ledger/retired-request semantics; identity behavior after a failed/protected person switch; sequential per-series Home lookups/reload churn; old-token disk cleanup; 403 handling; unavailable-versus-sign-in on first-run outage; live capability refresh. These are not silently folded into a small fidelity patch. | | Other review observations outside the named gap set | No expansion into debug per-person fixture persistence, empty-hero focus, tall Media info scrolling, pre-31 blur, or new screenshot regression infrastructure. Several old “unused live adapter” and title press-path observations were already superseded by the merged wiring/title slices. | | Unheld trailers | Still absent until Conductarr supplies the trailer field, as ruled. | | Device/release work | No ADB, install, device driving, signing, release, version bump, server mutation or Conductarr release. Native proof is Robolectric, not a claim about the physical TV. | ## Proof location `/root/.treehouse/firstmate-7bab20/2/firstmate/data/tv-fidelity-followups/` - `geometry.md`, `before/`, `visual-after/`, `visual-comparisons/`, `final-native/`, `final-comparisons/`, `final-native-manifest.json` - Native reference/before/after strips for st-071, st-074 and st-091 - `library-first-chunk.png`, `discover-saved.png`, behavioral result records The next Sonnet review is one round, blocking only for breaking behavior or a visible deviation. Merge authority remains with Justin; this PR does not merge itself. ## Commands and results Final head: `81073c410d8118d892e60e9cf6c0d0c97ef710cf`. `git fetch origin main && git merge --no-edit origin/main` completed before the final gate pair; main was already current. | Command / scenario | Result | | --- | --- | | Scoped native baseline and recapture through `:wolfskin-design:testDebugUnitTest` | Passed; original comparison script, native pairs and independent ink/box probes recorded above. | | Scoped ratings, held-OK, progressive SDK/saved-copy/native-library, Discover and wiring scenarios | Passed. The two new cache regressions failed before the cache change. | | `make test` on final head (one invocation) | **PASS, 2m57s**. 665 app + 173 design + 17 client = **855 tests**, zero failures/errors/skips. The client smoke also passed: local HTTP profile read → disk reopen → ETag 304 → 503 retains the saved profile, three requests. Gradle reused unchanged design/client test results where up-to-date. | | `make apk-debug` on the same final head (one invocation) | **PASS, 1m03s** Gradle / 68s wall. Produced universal, arm64-v8a, armeabi-v7a and x86_64 debug APKs. Application ID `org.justinvisser.wolfskin.tv.debug`; existing versionCode remains 64. No install or release was performed. | | Final native neutrality check | **23/23 Home PNGs and st-033 byte-identical** against the untouched baseline. Full comparison reports regenerated under `final-comparisons/`; PNG SHA-256 manifest records the final head. | | Checkout after gates | Clean. No proof/scratch files are staged or committed. | An earlier full gate on `04b1bdd6` found the new native progressive test reading the title immediately after its source-size wait (665 app tests, one focus assertion failure). The final commit keeps both exact assertions and runs them through Compose `runOnIdle`, after UI publication. The full gate then passed on `81073c41`; no assertion or scenario was removed. Earlier implementation runs also exposed and corrected the test fixture's SDK overload matcher; a fail-fast source-error assertion prevents that mismatch from hiding behind a deferred wait. Proof includes `final-make-test.log`, `final-make-apk-debug.log`, `final-test-counts.json`, final JUnit XMLs and APK checksums. Existing build warnings remain: missing optional Media3/MPV binaries use the configured stub, upstream deprecations/configuration-time classpath resolution, codec diagnostics and GC allocation warnings. They did not fail either final gate.
justinzeus added 2 commits 2026-11-06 02:26:59 +01:00
Synchronize progressive focus assertions with UI publication
All checks were successful
review/design-claude Claude review: PASS, no blocking finding (head 81073c41)
81073c410d
Author
Owner

Review (Claude Sonnet, one round): PASS, no blocking finding. Reviewed head 81073c410d8118d892e60e9cf6c0d0c97ef710cf.

Visual (my own native 1920x1080 measurement against the locked frames):

  • Discover request/receipt stacks: person-row fills at x=1500 are exact (329-428 / 447-546 / 565-664), the focused Request button fill is exact (693-723), and the receipt panel is exact (270-461).
  • Shared page heading: ink rows 165-213 against reference 164-213; header subtitles and pills move with it.
  • Settings behind Requests: title improves, subtitle ends up +3/+2 px against the reference (it was +1/0). The PR names this Roboto residual. It nets +0.03 mean RGB error on the 10 Settings-background pairs. Non-blocking.
  • Neutrality: all 23 Home captures, Discover st-033 and every Title-page capture are byte-identical to before. No token or Type change. Pixel changes are boxed to the headers, request/receipt sheets and Settings text.

Behaviour (read against the code and tests):

  • Home ratings cache: separate title and (series, season) caches, 300 entries each, correct capacity accounting and expiry.
  • Libraries: the first 200 titles publish while the next chunk is suspended, with no duplicates. A failed later chunk keeps the complete saved copy and never writes a partial one. A cold partial keeps a retry tail. Focus follows the title id, and loading focus respects intervening input.
  • Typed catalogue row keys keep a movie and a series with the same TMDB id distinct.
  • Undo is silent, Show again announces "Back in your picks.", and title pages own their own toast.
  • OwnedSourceAuditTest really reads the sources (13 planted cases, token file exempt). My regex simulation over 99 files found 0 violations in 0.03 s. It runs under make test through the app test task's dependency on the design unit tests.
  • Both wiring fixes preserve person isolation and the uncertain-submission ledger. No double submit.

Scope: no existing test weakened, nothing under app/src/main, no release/signing/version change.

Non-blocking notes:

  • DiscoverState.restore now requires showToast; all callers are migrated.
  • conductarr-home-real.png differs in tile-art loading state, a capture-timing artefact.
  • On the saved-copy path the completed copy is emitted before it is written to disk.

I did not regenerate the captures (no Gradle, per brief); the measurements are mine, taken on the lane's native PNGs. Their mean-error figures reproduce the PR table. Full report: data/review-wolfskin-37/report.md.

**Review (Claude Sonnet, one round): PASS, no blocking finding.** Reviewed head `81073c410d8118d892e60e9cf6c0d0c97ef710cf`. Visual (my own native 1920x1080 measurement against the locked frames): - Discover request/receipt stacks: person-row fills at x=1500 are exact (329-428 / 447-546 / 565-664), the focused Request button fill is exact (693-723), and the receipt panel is exact (270-461). - Shared page heading: ink rows 165-213 against reference 164-213; header subtitles and pills move with it. - Settings behind Requests: title improves, subtitle ends up +3/+2 px against the reference (it was +1/0). The PR names this Roboto residual. It nets +0.03 mean RGB error on the 10 Settings-background pairs. Non-blocking. - Neutrality: all 23 Home captures, Discover st-033 and every Title-page capture are byte-identical to before. No token or Type change. Pixel changes are boxed to the headers, request/receipt sheets and Settings text. Behaviour (read against the code and tests): - Home ratings cache: separate title and (series, season) caches, 300 entries each, correct capacity accounting and expiry. - Libraries: the first 200 titles publish while the next chunk is suspended, with no duplicates. A failed later chunk keeps the complete saved copy and never writes a partial one. A cold partial keeps a retry tail. Focus follows the title id, and loading focus respects intervening input. - Typed catalogue row keys keep a movie and a series with the same TMDB id distinct. - Undo is silent, Show again announces "Back in your picks.", and title pages own their own toast. - `OwnedSourceAuditTest` really reads the sources (13 planted cases, token file exempt). My regex simulation over 99 files found 0 violations in 0.03 s. It runs under `make test` through the app test task's dependency on the design unit tests. - Both wiring fixes preserve person isolation and the uncertain-submission ledger. No double submit. Scope: no existing test weakened, nothing under `app/src/main`, no release/signing/version change. Non-blocking notes: - `DiscoverState.restore` now requires `showToast`; all callers are migrated. - `conductarr-home-real.png` differs in tile-art loading state, a capture-timing artefact. - On the saved-copy path the completed copy is emitted before it is written to disk. I did not regenerate the captures (no Gradle, per brief); the measurements are mine, taken on the lane's native PNGs. Their mean-error figures reproduce the PR table. Full report: `data/review-wolfskin-37/report.md`.
justinzeus merged commit e9a92eba49 into main 2026-11-06 02:35:14 +01:00
Sign in to join this conversation.
No reviewers
No labels
exploring
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: justinzeus/wolfskin#37
No description provided.