Polish Discover sheets and Library row motion #77

Closed
justinzeus wants to merge 0 commits from fm/polish-lane-b into fm/tv-round2
Owner

Outcome

Polish Discover requests, filter chips, and Library rows without changing their logical focus or submission timing.

Idea Change Design files Native regression
P01 — filter chip colours Fade fill, text/glyph tint, and the constant-width border over focusMove; keep existing scale and OK behaviour DiscoverScreen.kt, LibraryScreen.kt DiscoverPolishTest.chipColoursCrossfadeOverFocusMove, LibraryPolishTest.toolbarChipColoursCrossfadeOverFocusMove
P03 — sending feedback Keep the request button width and show Sending… until the service answers; ignore repeated OK as before DiscoverScreen.kt, DiscoverOverlay.kt DiscoverPolishTest.requestButtonSaysSendingUntilTheServerAnswers
P04 — receipt entrance Fade the complete outcome block once after Sending; keep the title and ratings stationary; reopen existing outcomes at rest DiscoverOverlay.kt DiscoverPolishTest.receiptFadesInOnceAfterSending, reopenedUnconfirmedOutcomeRestsImmediately
P05 / E03 — no row-entry replay Save revealed row identities in each screen visit; retain them across lazy disposal and Back, not fresh entries or people ScreenEntry.kt, Motion.kt LibraryPolishTest.backFromTitleKeepsRowsAtRest, HomePolishRowsTest.scrollBackShelfDoesNotReplay, DiscoverPolishTest.scrollBackLaneDoesNotReplay
P06 — Discover panel fades Fade Request, Hidden receipt, and Show again with one scrim; retain inert exit copies and return logical focus immediately DiscoverOverlay.kt, DiscoverScreen.kt DiscoverPolishTest.requestSheetFadesInAndOutWithoutClickThrough
P11 — changed Library results Give genuinely changed membership/order a new reveal identity; reveal visible rows together and leave same-result commits at rest LibraryGridState.kt, LibraryScreen.kt LibraryPolishTest.sortChangeRevealsVisibleRowsTogether
P02 — Discover toast call site Use the shared fading toast host; leave the existing dismissal timer unchanged DiscoverOverlay.kt Shared toast motion belongs to Lane E; Discover neighbours cover this caller

Files above are under wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/. The three new regression files are in the matching src/test package. Every new motion regression also runs with LocalReducedMotion provides true.

Approved decisions

  • P01: “the mock shows only the Discover chips. The Library toolbar chips are the same component family and are named in P01's "Where", so both are built.” Title-page season chips remain with E07's owner.
  • P03: “During Sending, OK is ignored and Back closes (unchanged). Reopening a sheet that is still sending shows "Sending…" at once, with no fade.” The copy uses single-character U+2026; no glyph is shown while Sending.
  • P04: “A sheet that opens, or reopens, already in an outcome phase renders at rest with no fade. Only the Sending → outcome transition fades.” Done/Close owns logical focus from the first frame.
  • P05 / E03: “A fresh visit (tab switch through navigation.replace, or a person switch) starts with an empty memory. The approved tab entrance and every first appearance are unchanged.” Skeletons are recorded only when enabled; one saved-visit rule covers Library, Home, and Discover.
  • P06: “Focus ownership returns on the close frame exactly as today.” “Only one scrim is ever drawn.” Every sheet in the Discover container fades, including Hidden receipt and Show again. Retained exits reject focus, keys, and pointer actions; non-null content replacement does not restart the panel fade.
  • P11: “A toggle that leaves the same result does nothing.” Ordered library IDs, or catalogueKey for catalogues, control the revision. Focus stays on the toolbar and the index still resets to zero.
  • P02: “The timers that clear the toast (ShellSurface.kt:68–74, DiscoverScreen.kt:60, TitleNotice) stay as they are.” Only the Discover call site changes; shared host motion and toast frame strips belong to Lane E.

Base and ownership

Target: fm/tv-round2. Rebased onto the published shared base 74b737fb52bfbb2cc7afa0b0288ae59e67232320 without rewriting it. The base commit is included until Lane E lands, as required by the lane protocol.

Only Lane B's assigned files are edited. The combined revision-7 written spec is owned by Lane C, so no spec, token, or other lane-owned file is changed here.

Verification

App neighbours: 5 passed, 0 failed, 0 skipped across TitleRequestSafetyTest, LibraryProgressiveSurfaceTest, and DiscoverRefreshMotionTest.

bash docker/gradle.sh debug :wolfskin-design:cacheRobolectricSdk :app:testDefaultDebugUnitTest \
  --tests 'org.justinvisser.wolfskin.tv.TitleRequestSafetyTest' \
  --tests 'org.justinvisser.wolfskin.tv.LibraryProgressiveSurfaceTest' \
  --tests 'org.justinvisser.wolfskin.tv.DiscoverRefreshMotionTest' \
  -x :wolfskin-design:testDebugUnitTest

Design scope: 114 passed, 0 failed, 0 skipped across the 12 required classes, including all 20 new normal/reduced-motion cases.

bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest \
  --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' \
  --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' \
  --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' \
  --tests 'org.justinvisser.wolfskin.design.DiscoverKeysTest' \
  --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest' \
  --tests 'org.justinvisser.wolfskin.design.DiscoverDetailsFocusTest' \
  --tests 'org.justinvisser.wolfskin.design.LibraryKeysTest' \
  --tests 'org.justinvisser.wolfskin.design.LibraryCaptureTest' \
  --tests 'org.justinvisser.wolfskin.design.LibrarySpacingRegressionTest' \
  --tests 'org.justinvisser.wolfskin.design.HomeRowEntryTest' \
  --tests 'org.justinvisser.wolfskin.design.MotionSurfaceTest' \
  --tests 'org.justinvisser.wolfskin.design.ScreenEntryNavigationTest'

Native frame proof

Published native 1920×1080 captures and samples.csv indexes:

/root/.treehouse/firstmate-7bab20/2/firstmate/data/ui-polish-build/lane-b/<idea>/{before,after}/

Idea Strips, both normal and reduced motion
P01 discover-chips, library-toolbar: 16 frames each, including readable incoming/outgoing labels at 96 ms
P03 sending: 12 frames; after also includes reopening while the server is still pending
P04 receipt: 15 frames; settled/reopened unconfirmed outcome pair
P05 library-back: 15 return frames and 15 genuinely fresh-entry frames
P06 request-sheet: 12 open frames and 8 close frames, with scrim and high-contrast panel probes
P11 sort-rating: 15 frames plus unchanged-result before/after pair
E03 home-scroll-back, discover-scroll-back: 15 return frames; Home also records a genuinely new shelf's first appearance

The Home proof uses actual native lazy-list scroll-out and scroll-back with the queued Compose dispatcher and requestScrollToItem; the authorized scripted fallback was not used. Frame zero on return is already settled; genuinely new entries still reveal. The inline rowReveal documentation records this saved-visit contract.

Only native Robolectric surfaces were exercised. No TV box, ADB, emulator, full suite, APK build, or deployment was used. All Gradle commands went through docker/gradle.sh and its shared lock.

CSV timeMs is relative to each strip's first captured frame; captures advance the manual Compose clock in 16 ms steps. The matching PNGs preserve the complete surface, while the CSV records the sampled coordinates and channels.

Final pixel-preservation check

After native image comparison found a one-pixel resting glyph offset, the busy button's inner resting row was constrained to the existing button height. The focused and unfocused glyphs now use the original centering geometry.

49 passed, 0 failed, 0 skipped after that normalization:

bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest \
  --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' \
  --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' \
  --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' \
  --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest'

All seven settled references are pixel-identical before/after: st-120, focus-toolbar-chip, st-072, st-074, st-071, st-021, and st-022. The animated receipt's final panel also matches st-074 exactly.

Native sample choice: the proposed near-black P06 panel probe differed by one channel level near settling. The regression instead samples a high-contrast interior Request-heading pixel and the scrim, records those coordinates, and keeps the same monotonicity tolerance. The complete native frames remain available for inspecting every pixel.

All baseline, intermediate, and final commands with results
Base commit: 74b737fb52bfbb2cc7afa0b0288ae59e67232320 (rebased before feature edits).
Branch: fm/polish-lane-b. Target: fm/tv-round2.

Baseline run 1:
bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest'
Result: compiled, but all three runners rejected JUnit's Parameters annotation. Corrected to ParameterizedRobolectricTestRunner.Parameters, per Robolectric's documented annotation API. No production feature edits applied.

Baseline run 2:
bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest' --tests 'org.justinvisser.wolfskin.design.LibraryCaptureTest'
Result: 67 tests, 13 failed; the existing two capture classes passed. New failures include the absent Sending copy, popped sheet exit, and changed Discover return pixels, plus harness issues: Movies also exists in the nav, a merged full-screen scrim node was used instead of unmerged receipt Text bounds, and synchronous semantics scrolling re-entered Home layout. Corrected scoping, sampling and asynchronous list scrolling. Added explicit intermediate-colour assertions after observing the old Library toolbar jumping from RGB (33,33,35) at 0ms to (244,244,246) at 16ms.
Native XML records preserved in baseline-2-results/. Before strips preserved under ../ui-polish-build/lane-b/<ID>/before/.

Baseline run 3 (corrected harness; sort fixture retains row-leading identities while reordering titles):
bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest'
Result: 20 tests, 16 failures, 0 errors on base production code. Missing motion/copy assertions remained red; Home's layout reentry repeated. Stopped that attempt and obtained firstmate's explicit one-attempt queued-dispatch authorization before baseline run 4.

Baseline run 4 (authorized queued-dispatch attempt):
bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest.backFromTitleKeepsRowsAtRest*'
Result: 4 tests, 4 failures. Home used Compose v2 plus requestScrollToItem and successfully captured actual scroll-out/scroll-back in both motion modes; only the expected old replay assertion failed. Library exposed an unflushed state-write issue: its node remained composed during the requested disposal. Adopted the existing MotionSurfaceTest Snapshot.sendApplyNotifications pattern and the queued dispatcher for all three new classes. Home needs no fallback.

Intermediate run 5 (row-memory files still at base):
bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest'
Result: 18 tests, 7 failures. Library Back and Discover scroll-back now reproducibly replay (four expected failures), and their complete native before strips are preserved. P01, P03, and P04 pass in both motion modes. Remaining three failures were pixel-probe artifacts: the normal Library probe crossed a rising fallback glyph, and the nearly opaque dark panel rounded one RGB level upward. An unobstructed Library probe and a high-contrast interior heading pixel show monotonic native samples; the revised tests record those coordinates in samples.csv without relaxing tolerance.

All production changes are now applied, including saveable row reveal memory.

Final app neighbours:
bash docker/gradle.sh debug :wolfskin-design:cacheRobolectricSdk :app:testDefaultDebugUnitTest --tests 'org.justinvisser.wolfskin.tv.TitleRequestSafetyTest' --tests 'org.justinvisser.wolfskin.tv.LibraryProgressiveSurfaceTest' --tests 'org.justinvisser.wolfskin.tv.DiscoverRefreshMotionTest' -x :wolfskin-design:testDebugUnitTest
Result: BUILD SUCCESSFUL; 5 tests, 0 failures, 0 errors, 0 skipped. XML reports archived in final-app-results/. The wrapper held the shared Gradle lock; no APK build or device access.

Final design validation:
bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' --tests 'org.justinvisser.wolfskin.design.DiscoverKeysTest' --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest' --tests 'org.justinvisser.wolfskin.design.DiscoverDetailsFocusTest' --tests 'org.justinvisser.wolfskin.design.LibraryKeysTest' --tests 'org.justinvisser.wolfskin.design.LibraryCaptureTest' --tests 'org.justinvisser.wolfskin.design.LibrarySpacingRegressionTest' --tests 'org.justinvisser.wolfskin.design.HomeRowEntryTest' --tests 'org.justinvisser.wolfskin.design.MotionSurfaceTest' --tests 'org.justinvisser.wolfskin.design.ScreenEntryNavigationTest'
Result: BUILD SUCCESSFUL; 114 tests across 12 classes, 0 failures, 0 errors, 0 skipped. This includes all 20 new normal/reduced-motion cases. XML reports archived in final-design-results/.

Native visual inspection: outgoing and incoming chip labels remain readable at 96 ms; reopened Sending has no glyph and the resting button width; the outcome fades as one block with stationary header/ratings; sheet exits expose the background; restored Library, Home, and Discover rows are already visible on the first return frame; changed Library rows fade together.
Settled pixel comparisons: st-120, focus-toolbar-chip, st-074, st-021, and st-022 are bit-for-bit identical. The animated receipt's final panel is also identical to st-074. st-072 and st-071 exposed a one-native-pixel glyph vertical offset caused by nested wrap-content centering. Made the nested resting row fill the existing button height to preserve the original single centering operation.

Pixel-preservation follow-up:
bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest'
Result: BUILD SUCCESSFUL; 49 tests, 0 failures, 0 errors, 0 skipped. Reports archived in final-alignment-results/. All seven settled reference frames (st-120, focus-toolbar-chip, st-072, st-074, st-071, st-021, st-022) are now bit-for-bit identical to their before frames. All seven idea directories have normal/reduced before and after native strips and samples.csv. The final Sending panel was visually inspected again after normalization.

## Outcome Polish Discover requests, filter chips, and Library rows without changing their logical focus or submission timing. | Idea | Change | Design files | Native regression | |---|---|---|---| | P01 — filter chip colours | Fade fill, text/glyph tint, and the constant-width border over `focusMove`; keep existing scale and OK behaviour | `DiscoverScreen.kt`, `LibraryScreen.kt` | `DiscoverPolishTest.chipColoursCrossfadeOverFocusMove`, `LibraryPolishTest.toolbarChipColoursCrossfadeOverFocusMove` | | P03 — sending feedback | Keep the request button width and show **Sending…** until the service answers; ignore repeated OK as before | `DiscoverScreen.kt`, `DiscoverOverlay.kt` | `DiscoverPolishTest.requestButtonSaysSendingUntilTheServerAnswers` | | P04 — receipt entrance | Fade the complete outcome block once after Sending; keep the title and ratings stationary; reopen existing outcomes at rest | `DiscoverOverlay.kt` | `DiscoverPolishTest.receiptFadesInOnceAfterSending`, `reopenedUnconfirmedOutcomeRestsImmediately` | | P05 / E03 — no row-entry replay | Save revealed row identities in each screen visit; retain them across lazy disposal and Back, not fresh entries or people | `ScreenEntry.kt`, `Motion.kt` | `LibraryPolishTest.backFromTitleKeepsRowsAtRest`, `HomePolishRowsTest.scrollBackShelfDoesNotReplay`, `DiscoverPolishTest.scrollBackLaneDoesNotReplay` | | P06 — Discover panel fades | Fade Request, Hidden receipt, and Show again with one scrim; retain inert exit copies and return logical focus immediately | `DiscoverOverlay.kt`, `DiscoverScreen.kt` | `DiscoverPolishTest.requestSheetFadesInAndOutWithoutClickThrough` | | P11 — changed Library results | Give genuinely changed membership/order a new reveal identity; reveal visible rows together and leave same-result commits at rest | `LibraryGridState.kt`, `LibraryScreen.kt` | `LibraryPolishTest.sortChangeRevealsVisibleRowsTogether` | | P02 — Discover toast call site | Use the shared fading toast host; leave the existing dismissal timer unchanged | `DiscoverOverlay.kt` | Shared toast motion belongs to Lane E; Discover neighbours cover this caller | Files above are under `wolfskin-design/src/main/java/org/justinvisser/wolfskin/design/`. The three new regression files are in the matching `src/test` package. Every new motion regression also runs with `LocalReducedMotion provides true`. ## Approved decisions - P01: “the mock shows only the Discover chips. The Library toolbar chips are the same component family and are named in P01's "Where", so both are built.” Title-page season chips remain with E07's owner. - P03: “During Sending, OK is ignored and Back closes (unchanged). Reopening a sheet that is still sending shows "Sending…" at once, with no fade.” The copy uses single-character U+2026; no glyph is shown while Sending. - P04: “A sheet that opens, or reopens, already in an outcome phase renders at rest with no fade. Only the Sending → outcome transition fades.” Done/Close owns logical focus from the first frame. - P05 / E03: “A fresh visit (tab switch through `navigation.replace`, or a person switch) starts with an empty memory. The approved tab entrance and every first appearance are unchanged.” Skeletons are recorded only when enabled; one saved-visit rule covers Library, Home, and Discover. - P06: “Focus ownership returns on the close frame exactly as today.” “Only one scrim is ever drawn.” Every sheet in the Discover container fades, including Hidden receipt and Show again. Retained exits reject focus, keys, and pointer actions; non-null content replacement does not restart the panel fade. - P11: “A toggle that leaves the same result does nothing.” Ordered library IDs, or `catalogueKey` for catalogues, control the revision. Focus stays on the toolbar and the index still resets to zero. - P02: “The timers that clear the toast (`ShellSurface.kt:68–74`, `DiscoverScreen.kt:60`, `TitleNotice`) stay as they are.” Only the Discover call site changes; shared host motion and toast frame strips belong to Lane E. ## Base and ownership Target: `fm/tv-round2`. Rebased onto the published shared base `74b737fb52bfbb2cc7afa0b0288ae59e67232320` without rewriting it. The base commit is included until Lane E lands, as required by the lane protocol. Only Lane B's assigned files are edited. The combined revision-7 written spec is owned by Lane C, so no spec, token, or other lane-owned file is changed here. ## Verification App neighbours: **5 passed, 0 failed, 0 skipped** across `TitleRequestSafetyTest`, `LibraryProgressiveSurfaceTest`, and `DiscoverRefreshMotionTest`. ```sh bash docker/gradle.sh debug :wolfskin-design:cacheRobolectricSdk :app:testDefaultDebugUnitTest \ --tests 'org.justinvisser.wolfskin.tv.TitleRequestSafetyTest' \ --tests 'org.justinvisser.wolfskin.tv.LibraryProgressiveSurfaceTest' \ --tests 'org.justinvisser.wolfskin.tv.DiscoverRefreshMotionTest' \ -x :wolfskin-design:testDebugUnitTest ``` Design scope: **114 passed, 0 failed, 0 skipped** across the 12 required classes, including all 20 new normal/reduced-motion cases. ```sh bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest \ --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' \ --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' \ --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' \ --tests 'org.justinvisser.wolfskin.design.DiscoverKeysTest' \ --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest' \ --tests 'org.justinvisser.wolfskin.design.DiscoverDetailsFocusTest' \ --tests 'org.justinvisser.wolfskin.design.LibraryKeysTest' \ --tests 'org.justinvisser.wolfskin.design.LibraryCaptureTest' \ --tests 'org.justinvisser.wolfskin.design.LibrarySpacingRegressionTest' \ --tests 'org.justinvisser.wolfskin.design.HomeRowEntryTest' \ --tests 'org.justinvisser.wolfskin.design.MotionSurfaceTest' \ --tests 'org.justinvisser.wolfskin.design.ScreenEntryNavigationTest' ``` ## Native frame proof Published native 1920×1080 captures and `samples.csv` indexes: `/root/.treehouse/firstmate-7bab20/2/firstmate/data/ui-polish-build/lane-b/<idea>/{before,after}/` | Idea | Strips, both normal and reduced motion | |---|---| | P01 | `discover-chips`, `library-toolbar`: 16 frames each, including readable incoming/outgoing labels at 96 ms | | P03 | `sending`: 12 frames; after also includes reopening while the server is still pending | | P04 | `receipt`: 15 frames; settled/reopened unconfirmed outcome pair | | P05 | `library-back`: 15 return frames and 15 genuinely fresh-entry frames | | P06 | `request-sheet`: 12 open frames and 8 close frames, with scrim and high-contrast panel probes | | P11 | `sort-rating`: 15 frames plus unchanged-result before/after pair | | E03 | `home-scroll-back`, `discover-scroll-back`: 15 return frames; Home also records a genuinely new shelf's first appearance | The Home proof uses actual native lazy-list scroll-out and scroll-back with the queued Compose dispatcher and `requestScrollToItem`; the authorized scripted fallback was **not used**. Frame zero on return is already settled; genuinely new entries still reveal. The inline `rowReveal` documentation records this saved-visit contract. Only native Robolectric surfaces were exercised. No TV box, ADB, emulator, full suite, APK build, or deployment was used. All Gradle commands went through `docker/gradle.sh` and its shared lock. CSV `timeMs` is relative to each strip's first captured frame; captures advance the manual Compose clock in 16 ms steps. The matching PNGs preserve the complete surface, while the CSV records the sampled coordinates and channels. ## Final pixel-preservation check After native image comparison found a one-pixel resting glyph offset, the busy button's inner resting row was constrained to the existing button height. The focused and unfocused glyphs now use the original centering geometry. **49 passed, 0 failed, 0 skipped** after that normalization: ```sh bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest \ --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' \ --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' \ --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' \ --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest' ``` All seven settled references are **pixel-identical before/after**: `st-120`, `focus-toolbar-chip`, `st-072`, `st-074`, `st-071`, `st-021`, and `st-022`. The animated receipt's final panel also matches `st-074` exactly. Native sample choice: the proposed near-black P06 panel probe differed by one channel level near settling. The regression instead samples a high-contrast interior Request-heading pixel and the scrim, records those coordinates, and keeps the same monotonicity tolerance. The complete native frames remain available for inspecting every pixel. <details> <summary>All baseline, intermediate, and final commands with results</summary> ```text Base commit: 74b737fb52bfbb2cc7afa0b0288ae59e67232320 (rebased before feature edits). Branch: fm/polish-lane-b. Target: fm/tv-round2. Baseline run 1: bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' Result: compiled, but all three runners rejected JUnit's Parameters annotation. Corrected to ParameterizedRobolectricTestRunner.Parameters, per Robolectric's documented annotation API. No production feature edits applied. Baseline run 2: bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest' --tests 'org.justinvisser.wolfskin.design.LibraryCaptureTest' Result: 67 tests, 13 failed; the existing two capture classes passed. New failures include the absent Sending copy, popped sheet exit, and changed Discover return pixels, plus harness issues: Movies also exists in the nav, a merged full-screen scrim node was used instead of unmerged receipt Text bounds, and synchronous semantics scrolling re-entered Home layout. Corrected scoping, sampling and asynchronous list scrolling. Added explicit intermediate-colour assertions after observing the old Library toolbar jumping from RGB (33,33,35) at 0ms to (244,244,246) at 16ms. Native XML records preserved in baseline-2-results/. Before strips preserved under ../ui-polish-build/lane-b/<ID>/before/. Baseline run 3 (corrected harness; sort fixture retains row-leading identities while reordering titles): bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' Result: 20 tests, 16 failures, 0 errors on base production code. Missing motion/copy assertions remained red; Home's layout reentry repeated. Stopped that attempt and obtained firstmate's explicit one-attempt queued-dispatch authorization before baseline run 4. Baseline run 4 (authorized queued-dispatch attempt): bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest.backFromTitleKeepsRowsAtRest*' Result: 4 tests, 4 failures. Home used Compose v2 plus requestScrollToItem and successfully captured actual scroll-out/scroll-back in both motion modes; only the expected old replay assertion failed. Library exposed an unflushed state-write issue: its node remained composed during the requested disposal. Adopted the existing MotionSurfaceTest Snapshot.sendApplyNotifications pattern and the queued dispatcher for all three new classes. Home needs no fallback. Intermediate run 5 (row-memory files still at base): bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' Result: 18 tests, 7 failures. Library Back and Discover scroll-back now reproducibly replay (four expected failures), and their complete native before strips are preserved. P01, P03, and P04 pass in both motion modes. Remaining three failures were pixel-probe artifacts: the normal Library probe crossed a rising fallback glyph, and the nearly opaque dark panel rounded one RGB level upward. An unobstructed Library probe and a high-contrast interior heading pixel show monotonic native samples; the revised tests record those coordinates in samples.csv without relaxing tolerance. All production changes are now applied, including saveable row reveal memory. Final app neighbours: bash docker/gradle.sh debug :wolfskin-design:cacheRobolectricSdk :app:testDefaultDebugUnitTest --tests 'org.justinvisser.wolfskin.tv.TitleRequestSafetyTest' --tests 'org.justinvisser.wolfskin.tv.LibraryProgressiveSurfaceTest' --tests 'org.justinvisser.wolfskin.tv.DiscoverRefreshMotionTest' -x :wolfskin-design:testDebugUnitTest Result: BUILD SUCCESSFUL; 5 tests, 0 failures, 0 errors, 0 skipped. XML reports archived in final-app-results/. The wrapper held the shared Gradle lock; no APK build or device access. Final design validation: bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' --tests 'org.justinvisser.wolfskin.design.DiscoverKeysTest' --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest' --tests 'org.justinvisser.wolfskin.design.DiscoverDetailsFocusTest' --tests 'org.justinvisser.wolfskin.design.LibraryKeysTest' --tests 'org.justinvisser.wolfskin.design.LibraryCaptureTest' --tests 'org.justinvisser.wolfskin.design.LibrarySpacingRegressionTest' --tests 'org.justinvisser.wolfskin.design.HomeRowEntryTest' --tests 'org.justinvisser.wolfskin.design.MotionSurfaceTest' --tests 'org.justinvisser.wolfskin.design.ScreenEntryNavigationTest' Result: BUILD SUCCESSFUL; 114 tests across 12 classes, 0 failures, 0 errors, 0 skipped. This includes all 20 new normal/reduced-motion cases. XML reports archived in final-design-results/. Native visual inspection: outgoing and incoming chip labels remain readable at 96 ms; reopened Sending has no glyph and the resting button width; the outcome fades as one block with stationary header/ratings; sheet exits expose the background; restored Library, Home, and Discover rows are already visible on the first return frame; changed Library rows fade together. Settled pixel comparisons: st-120, focus-toolbar-chip, st-074, st-021, and st-022 are bit-for-bit identical. The animated receipt's final panel is also identical to st-074. st-072 and st-071 exposed a one-native-pixel glyph vertical offset caused by nested wrap-content centering. Made the nested resting row fill the existing button height to preserve the original single centering operation. Pixel-preservation follow-up: bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.DiscoverPolishTest' --tests 'org.justinvisser.wolfskin.design.LibraryPolishTest' --tests 'org.justinvisser.wolfskin.design.HomePolishRowsTest' --tests 'org.justinvisser.wolfskin.design.DiscoverCaptureTest' Result: BUILD SUCCESSFUL; 49 tests, 0 failures, 0 errors, 0 skipped. Reports archived in final-alignment-results/. All seven settled reference frames (st-120, focus-toolbar-chip, st-072, st-074, st-071, st-021, st-022) are now bit-for-bit identical to their before frames. All seven idea directories have normal/reduced before and after native strips and samples.csv. The final Sending panel was visually inspected again after normalization. ``` </details>
justinzeus added 2 commits 2026-11-08 03:03:41 +01:00
Author
Owner

Landed through the round 2 candidate #82 (merged into fm/tv-round2 as c21d17df). Closing as superseded; nothing from this branch is lost.

Landed through the round 2 candidate https://git.justinvisser.org/justinzeus/wolfskin/pulls/82 (merged into fm/tv-round2 as c21d17df). Closing as superseded; nothing from this branch is lost.
justinzeus closed this pull request 2026-11-08 13:59:34 +01:00

Pull request closed

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#77
No description provided.