Polish picker identity changes, navigation cuts and Home playback #80

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

Picker, identity, navigation and Home playback polish

Lane C: P07 picker loading, P08 committed person switching, E01 navigation cuts, E04 Home Play/Resume, revision-7 spec and capture notes. Base: 74b737fb52bfbb2cc7afa0b0288ae59e67232320; target fm/tv-round2. This lane merges last because it changes person identity and navigation.

Behaviour and owned files

  • P07: WhosWatching.kt applies the shared skeleton pulse only to placeholders. Recovery buttons stay static; Ready removes the pulse. PickerPolishTest observes native pixels and recomposer idleness.
  • P08: PersonCommit.kt, WhosWatching.kt, WolfskinApp.kt freeze the approved picker, fade the other people, then cover the whole picker; hold opaque background until the authenticated replacement is ready. Keys, pointer and system Back are ignored during the commit. PIN/requireLogin checks remain before changeUser; failed/protected switches reveal setup only after the timeline completes. Session-owned frame origin survives app replacement. Phase-one masks paint last so the opaque background does not acquire one-channel alpha-rounding noise in phase two.
  • E01: WolfskinApp.kt, MainContent.kt disable enter/pop/predictive whole-screen transitions. Delete update/UpdateNavigation.kt and its redundant per-route metadata. Existing saveable-state/ViewModel decorators and active-entry Back ownership remain.
  • E04 Home: HomeHeader.kt, WhosWatching.kt, HomeDestination.kt, WolfskinApp.kt show exactly Starting… at the original button width, ignore repeat starts, fade black before the actual fullscreen playback destination and retain item/position. Cancellation and stale identity/results cannot launch or toast later.
  • Docs: data/tv-spec/spec.md contains the exact approved revision-7 block; docker/README.md lists the named native capture tests and paths.

The real-NavDisplay probe reproduced a full old-Home flash one frame after the veil reached black (normal: black at 192 ms, Home at 208 ms; reduced: black at 112 ms, Home at 128 ms). WolfskinApp now keeps opaque black through incoming-player entry composition and uncovers it on the following composition. Input stays blocked across the same gap. The player entry also owns its black background: upstream error/external-player loading components can be transparent. Both regression variants now remain black through a deliberately delayed renderer, then uncover only the incoming scene; no old Home frame.

The optional fullscreen renderer follows the existing Home/title injection pattern. Production defaults to the real DestinationContent; the native test uses a controlled opaque-blue player surface after a transparent loading phase. This proves the real NavDisplay/veil boundary, not video decoding.

Decisions and observation criteria

  • P08 phase two begins at 160 ms, not the mock's 250 ms: the 90 ms hold has no motion token. Normal choreography is 160 + 160 ms; reduced motion has only the capped 80 ms full veil. Continue-as recovery and gear get no choreography. No recipient skeleton or sign-in placeholder is introduced during the commit.
  • P07 buttons never pulse. Existing picker foreground/focus colours are unchanged.
  • E01 final interpretation (steering 005–006): the spec's literal “one frame / exactly one wolfskin-shell node at every frame” was measured against Android Navigation3 (Nav3) 1.1.7 and explicitly reinterpreted: native paint must remain one opaque screen (no whole-screen alpha or ghosting; avatar/identity pixels unchanged). Forward open/tab and setup paint incoming content by 32 ms; Back may paint by 64 ms; outgoing semantics retire by 64 ms. A single public ContentTransform.targetContentZIndex = 1f trial did not reduce Back's 64 ms paint latency in either motion mode, so it was reverted as authorized. Every frame from 0 through 320 ms is captured in 16 ms steps without warming the clock. The combined reviewer should check this interpretation against the strips. No Nav3 fork, reflection, entry-decorator replacement or lifecycle workaround.
  • E04 contract: lane-C.md:241-249 / spec.md:671-679. Failure crossfades the label back; return from the player has no veil and the normal reset label. The Home test first paints the completed handoff and verifies Home was disposed, then tests the first native Home frame after Back. It does not pop an unrendered player in the same turn or change the motion token.
  • All motion uses shared tokens and respects reduced motion. No full-screen alpha graphics layer is added.

Existing tests edited

ConductarrHomeSurfaceTest, HomeRecoveryTest, HomeSeeAllNavigationTest, PersonSwitchThreadingTest, WatchReadTest, WatchReturnTest: supply the new session dependency; existing behavioural assertions retained.

PlayerHandoffTest: supply the session and compose Home plus the handoff veil; verify navigation stays Home before the fade completes, then preserve the real item/position/fullscreen/Back assertions. These seven additional files were authorized in steering 002.

Exercised neighbouring verification

Final result: 88 app cases passed, 0 failures/errors/skips, including all 70 named auth/Back/identity/playback neighbours and all 18 new native cases. 20 design cases passed across PickerPolishTest, PickerNavigationTest, ShellCaptureTest and ScreenEntryNavigationTest. App run: 4m36s. XML evidence: data/polish-lane-c/validation/{final-app,final-design}/.

Design command:

bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.PickerPolishTest' --tests 'org.justinvisser.wolfskin.design.PickerNavigationTest' --tests 'org.justinvisser.wolfskin.design.ShellCaptureTest' --tests 'org.justinvisser.wolfskin.design.ScreenEntryNavigationTest'

New native regression command:

bash docker/gradle.sh debug :wolfskin-design:cacheRobolectricSdk :app:testDefaultDebugUnitTest --tests 'org.justinvisser.wolfskin.tv.PersonCommitTest' --tests 'org.justinvisser.wolfskin.tv.NavigationCutTest' --tests 'org.justinvisser.wolfskin.tv.HomeHeroStartingTest' -x :wolfskin-design:testDebugUnitTest

Development run history (the command blocks here identify the exact selected classes):

Command Observed results before the final pass
Picker-only design command below 2 Ready-synchronization failures; fixed snapshot delivery before assertions
Design command One compile-only attempt used an unavailable clock-idleness API; corrected to the recomposer-idleness check, then 20/20 passed
Native regression command Baseline capture-only versions: 3/3 passed. Later iterations: 8/16, 11/16, 12/16, 14/18 and 16/18 passed while correcting observation/preconditions and reproducing the full-root flash
Full targeted app command 75/86 passed initially (all 70 neighbours green); 84/86 with only Back paint limits failing; 88/88 after the bridge fix; final 88/88 with transparent/delayed player loading exercised
bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.PickerPolishTest'

Compile-only app attempts corrected a required DTO type, unsupported inline-value-class varargs, an unsupported named key-duration argument and a missing test-tag import. One baseline attempt timed out waiting/building before an app result; its queued retry produced the baseline captures. The first full-root fixture used a relaxed generic backdrop flow and failed with Object → BackdropResult; it now supplies a typed BackdropResult.NONE flow. No production exception was suppressed. Native flash reproduction XML and frames are retained under data/polish-lane-c/validation/handoff-before/; the discarded z-order trial is under validation/z-order-attempt/.

Full targeted app command (new cases plus every named neighbour; no other test classes):

bash docker/gradle.sh debug :wolfskin-design:cacheRobolectricSdk :app:testDefaultDebugUnitTest \
  --tests 'org.justinvisser.wolfskin.tv.PersonCommitTest' \
  --tests 'org.justinvisser.wolfskin.tv.NavigationCutTest' \
  --tests 'org.justinvisser.wolfskin.tv.HomeHeroStartingTest' \
  --tests 'org.justinvisser.wolfskin.tv.PersonPickerSessionTest' \
  --tests 'org.justinvisser.wolfskin.tv.PersonSwitchThreadingTest' \
  --tests 'org.justinvisser.wolfskin.tv.SavedPeoplePickerTest' \
  --tests 'org.justinvisser.wolfskin.tv.UpstreamContentFocusTest' \
  --tests 'org.justinvisser.wolfskin.tv.FirstSignInNavigationTest' \
  --tests 'org.justinvisser.wolfskin.tv.WolfskinBackStackTest' \
  --tests 'org.justinvisser.wolfskin.tv.TitleEntryBackTest' \
  --tests 'org.justinvisser.wolfskin.tv.WolfskinRootExitTest' \
  --tests 'org.justinvisser.wolfskin.tv.update.UpdatesKeysTest' \
  --tests 'org.justinvisser.wolfskin.tv.HomeSeeAllNavigationTest' \
  --tests 'org.justinvisser.wolfskin.tv.NavBandOcclusionTest' \
  --tests 'org.justinvisser.wolfskin.tv.HomeRecoveryTest' \
  --tests 'org.justinvisser.wolfskin.tv.ConductarrHomeSurfaceTest' \
  --tests 'org.justinvisser.wolfskin.tv.TitlePlaybackNavigationTest' \
  --tests 'org.justinvisser.wolfskin.tv.WatchReturnTest' \
  --tests 'org.justinvisser.wolfskin.tv.PlayerHandoffTest' \
  --tests 'org.justinvisser.wolfskin.tv.WatchReadTest' \
  -x :wolfskin-design:testDebugUnitTest

New auth, identity and Back regressions

PersonCommitTest:

failedCredentialSwitchRevealsSetupOnlyAfterThePickerIsCovered
reducedMotionUsesOnlyTheShortFullPickerFade
requireLoginPersonReturnsToSetupWithoutChangingCredentials
pinProtectedPersonReturnsToSetupWithoutChangingCredentials
choosingMindelCoversTheSwitchUntilTheirHomeCanPaint
samePersonRunsTheChoreographyWithoutSwitchingCredentials

NavigationCutTest:

playbackVeilIgnoresKeysAndBackThenReturnsBackOwnershipToHome
backBeforeTheBlackVeilCancelsThePendingStartWithoutExitingHome
titleAndTabPaintWithinTwoFramesBackWithinFour
reducedMotionKeepsOpaqueCutsAndRetiresOutgoingByFourFrames
setupHostKeepsOpaquePaintAndRetiresOutgoingWithinFourFrames
reducedMotionSetupHostKeepsTheSameCutDeadlines
fullRootPlaybackHandoffNeverRepaintsHome
reducedMotionFullRootHandoffNeverRepaintsHome

HomeHeroStartingTest:

leavingHomeCancelsPreparationAndCannotLaunchALateResult
failedPreparationRestoresResumeAndShowsTheExistingRecoveryToast
reducedMotionCapsBothFadesAndStillStartsOnce
playSaysStartingThenFadesToBlackBeforeThePlayer

Native proof locations

Root: /root/.treehouse/firstmate-7bab20/2/firstmate/data/ui-polish-build/lane-c/.

  • P07: P07/{before,after}/{normal,reduced}/ (0–1400 ms / 100 ms).
  • P08: P08/before/normal/ and P08/after/{normal,reduced}/ (0–480 ms / 16 ms; picked Home and reduced-motion toggle hold included).
  • E01 and E04 baseline: E01/before/normal/, E04/before/normal/.
  • E01 after: E01/after/{normal,reduced,setup-normal,setup-reduced}/; open-title, Back and tab each run 0–320 ms / 16 ms.
  • E04: E04/after/{normal,reduced}/ includes preparation, black fade and the first Home frame after returning; it excludes the empty test-harness player surface.
  • Full-root E04 boundary probe: E04/{before,after}/{root-normal,root-reduced}/. The incoming solid-blue scene is a test renderer, not a screenshot of a decoded player; before captures stop at the demonstrated old-Home flash.

Only Docker-targeted unit/native scenarios were run. No full suite, APK build, emulator, m3 walk, TV, ADB, install or device launch. Player decoding/playback itself was not exercised by the native Home-to-destination harness.

Exact auth, Back, identity and playback neighbour cases exercised

The following 70 cases all passed; suffixed names are retained exactly from the XML.

ConductarrHomeSurfaceTest

currentIdentityFeedsRealHomeAndSavedRequestsWithoutInventingJellyfinPlayback

FirstSignInNavigationTest

firstContinueThenMoviesRendersMindelsGridWithoutReenteringThePicker

HomeRecoveryTest

renamedHouseholdProfileKeepsItsOwnJellyfinLibraryWithoutAConductarrIdentity
personBSeesNeitherPersonAsSavedHomeNorTheirLateRefreshResult
readableJellyfinDoesNotBecomeAnOutageWhenLocalCacheCannotBeWritten
savedHomePaintsBeforeRefreshAndStaysAfterFailedRetry

HomeSeeAllNavigationTest

personalMovieContinuationReachesTheEighteenthTitleAndReturnsToHome
horizontallyScrolledContinuationRestoresTheExactHomeViewport

NavBandOcclusionTest

scrolledRowsNeverShowThroughTheNavBand

PersonPickerSessionTest

launchRightThenOneOkKeepsPickerClosed
initialPersonNeedsOnlyOneOk
fastLeftLeftOkKeepsPickerClosed
avatarRightThenOneOkKeepsPickerClosed
gearAndBackThenOneOkKeepsPickerClosed
launchLeftThenOneOkKeepsPickerClosed
avatarLeftThenOneOkKeepsPickerClosed

PersonSwitchThreadingTest

pickerSwitchesKeepPersonDataAndDisposeEveryClientOffMainWithoutWaiting
rapidPickerChoicesIgnoreLateSignInAndCanReturnToTheOriginalPerson
homeAndTitleRetriesReplaceSignedOutClientsWithoutMainThreadDisposal

PlayerHandoffTest

anotherPersonsSessionCannotResolveOrStartPlayback
successfulPlaybackUsesTheRealFullscreenDestinationAndBackKeepsTheResumeCard
failedPlaybackReadLeavesSavedHomeFocusedAndDrawsTheExactOfflineToast

SavedPeoplePickerTest

savedPeopleAreVisibleBeforeTheFirstNetworkResponse

TitleEntryBackTest

outgoingLoadedTitleCannotConsumeTheNextHomeBack[34]
predictivePersonBackPopsOnlyOneEntry[34]
outgoingLoadedPersonCannotConsumeTheNextHomeBack[34]
nativeBackKeyWaitsForSystemCompletionBeforePoppingTheTitle[34]
predictiveTitleBackPopsOnlyOneEntry[34]
immediateSecondSystemBackUsesHomeBeforeExitRecomposition[34]
outgoingLoadedTitleCannotConsumeTheNextHomeBack
predictivePersonBackPopsOnlyOneEntry
outgoingLoadedPersonCannotConsumeTheNextHomeBack
nativeBackKeyWaitsForSystemCompletionBeforePoppingTheTitle
predictiveTitleBackPopsOnlyOneEntry
immediateSecondSystemBackUsesHomeBeforeExitRecomposition

TitlePlaybackNavigationTest

primarySeriesActionReResolvesNextUpButRestartAndExplicitEpisodesKeepTheirIdentity
repeatedEpisodeChoicesReplaceOnlyEpisodesAndBackPreservesTheirSeriesParent

UpstreamContentFocusTest

switchOffShowsRealUpstreamBackdropAndSwitchOnRestoresOwnedBackground
switchOffUpMovesBetweenContentRowsBeforeEnteringNav

WatchReadTest

freshResumeAndNextUpPaintBeforeSlowLibraryAndSurviveItsFailure
bothFacadesUseTheLiveCheckpointAndSeriesNextUpWhileExplicitEpisodeKeepsItsIdentity
mergedHomeUsesSeriesWatchActivityNotAnUnwatchedNextEpisodeDate

WatchReturnTest

acknowledgedStopRefreshesVisibleHeroWithoutRecreatingHomeOrLosingFocus

WolfskinBackStackTest

unsavedHomeSettingsPromptsBeforeDiscardCanExitTheTask
pushedUpdatesPopsSettingsThenPickerBeforeRootExit
singletonUpdatesBackFinishesInsteadOfBecomingADeadEnd

WolfskinRootExitTest

reopenedPickerBackDismissesToNavAndTheFollowingBackExits[34]
showsContentThenNavBackFinishesTheActivity[34]
moviesContentThenNavBackFinishesTheActivity[34]
coldPickerBackFinishesWithoutSelectingAnAvatarOrShowingUpstreamUi[34]
hardwareBackUsesTheSameContentNavExitLadder[34]
homeContentThenNavBackFinishesTheActivity[34]
animeContentThenNavBackFinishesTheActivity[34]
discoverContentThenNavBackFinishesTheActivity[34]
comingInSheetDismissesBeforeContentNavAndExit[34]
reopenedPickerBackDismissesToNavAndTheFollowingBackExits
showsContentThenNavBackFinishesTheActivity
moviesContentThenNavBackFinishesTheActivity
coldPickerBackFinishesWithoutSelectingAnAvatarOrShowingUpstreamUi
hardwareBackUsesTheSameContentNavExitLadder
homeContentThenNavBackFinishesTheActivity
animeContentThenNavBackFinishesTheActivity
discoverContentThenNavBackFinishesTheActivity
comingInSheetDismissesBeforeContentNavAndExit

update.UpdatesKeysTest

longNotesScrollWithoutEscapingToNavOrAutoCheck
progressKeepsAutoCheckFocusAcrossByteAndReducedMotionChanges
navAndAutoCheckReturnToTheRememberedActionWithoutToggling
refreshingInstalledIdentityCannotMaskAnOngoingCheck
notesTrapRealKeysAndBackPreservesSettingsRowAndScroller
classicRequiresEveryRetainedRowAndTheRealScroller
## Picker, identity, navigation and Home playback polish Lane C: P07 picker loading, P08 committed person switching, E01 navigation cuts, E04 Home Play/Resume, revision-7 spec and capture notes. Base: `74b737fb52bfbb2cc7afa0b0288ae59e67232320`; target `fm/tv-round2`. This lane merges last because it changes person identity and navigation. ### Behaviour and owned files - **P07:** `WhosWatching.kt` applies the shared skeleton pulse only to placeholders. Recovery buttons stay static; Ready removes the pulse. `PickerPolishTest` observes native pixels and recomposer idleness. - **P08:** `PersonCommit.kt`, `WhosWatching.kt`, `WolfskinApp.kt` freeze the approved picker, fade the other people, then cover the whole picker; hold opaque background until the authenticated replacement is ready. Keys, pointer and system Back are ignored during the commit. PIN/requireLogin checks remain before `changeUser`; failed/protected switches reveal setup only after the timeline completes. Session-owned frame origin survives app replacement. Phase-one masks paint last so the opaque background does not acquire one-channel alpha-rounding noise in phase two. - **E01:** `WolfskinApp.kt`, `MainContent.kt` disable enter/pop/predictive whole-screen transitions. Delete `update/UpdateNavigation.kt` and its redundant per-route metadata. Existing saveable-state/ViewModel decorators and active-entry Back ownership remain. - **E04 Home:** `HomeHeader.kt`, `WhosWatching.kt`, `HomeDestination.kt`, `WolfskinApp.kt` show exactly `Starting…` at the original button width, ignore repeat starts, fade black before the actual fullscreen playback destination and retain item/position. Cancellation and stale identity/results cannot launch or toast later. - **Docs:** `data/tv-spec/spec.md` contains the exact approved revision-7 block; `docker/README.md` lists the named native capture tests and paths. The real-NavDisplay probe reproduced a full old-Home flash one frame after the veil reached black (normal: black at 192 ms, Home at 208 ms; reduced: black at 112 ms, Home at 128 ms). `WolfskinApp` now keeps opaque black through incoming-player entry composition and uncovers it on the following composition. Input stays blocked across the same gap. The player entry also owns its black background: upstream error/external-player loading components can be transparent. Both regression variants now remain black through a deliberately delayed renderer, then uncover only the incoming scene; no old Home frame. The optional fullscreen renderer follows the existing Home/title injection pattern. Production defaults to the real `DestinationContent`; the native test uses a controlled opaque-blue player surface after a transparent loading phase. This proves the real NavDisplay/veil boundary, not video decoding. ### Decisions and observation criteria - P08 phase two begins at 160 ms, not the mock's 250 ms: the 90 ms hold has no motion token. Normal choreography is 160 + 160 ms; reduced motion has only the capped 80 ms full veil. Continue-as recovery and gear get no choreography. No recipient skeleton or sign-in placeholder is introduced during the commit. - P07 buttons never pulse. Existing picker foreground/focus colours are unchanged. - **E01 final interpretation (steering 005–006):** the spec's literal “one frame / exactly one wolfskin-shell node at every frame” was measured against Android Navigation3 (Nav3) 1.1.7 and explicitly reinterpreted: native paint must remain one opaque screen (no whole-screen alpha or ghosting; avatar/identity pixels unchanged). Forward open/tab and setup paint incoming content by 32 ms; Back may paint by 64 ms; outgoing semantics retire by 64 ms. A single public `ContentTransform.targetContentZIndex = 1f` trial did not reduce Back's 64 ms paint latency in either motion mode, so it was reverted as authorized. Every frame from 0 through 320 ms is captured in 16 ms steps without warming the clock. The combined reviewer should check this interpretation against the strips. No Nav3 fork, reflection, entry-decorator replacement or lifecycle workaround. - E04 contract: `lane-C.md:241-249` / `spec.md:671-679`. Failure crossfades the label back; return from the player has no veil and the normal reset label. The Home test first paints the completed handoff and verifies Home was disposed, then tests the first native Home frame after Back. It does not pop an unrendered player in the same turn or change the motion token. - All motion uses shared tokens and respects reduced motion. No full-screen alpha graphics layer is added. ### Existing tests edited `ConductarrHomeSurfaceTest`, `HomeRecoveryTest`, `HomeSeeAllNavigationTest`, `PersonSwitchThreadingTest`, `WatchReadTest`, `WatchReturnTest`: supply the new session dependency; existing behavioural assertions retained. `PlayerHandoffTest`: supply the session and compose Home plus the handoff veil; verify navigation stays Home before the fade completes, then preserve the real item/position/fullscreen/Back assertions. These seven additional files were authorized in steering 002. ### Exercised neighbouring verification Final result: **88 app cases passed, 0 failures/errors/skips**, including all 70 named auth/Back/identity/playback neighbours and all 18 new native cases. **20 design cases passed** across `PickerPolishTest`, `PickerNavigationTest`, `ShellCaptureTest` and `ScreenEntryNavigationTest`. App run: 4m36s. XML evidence: `data/polish-lane-c/validation/{final-app,final-design}/`. Design command: ```sh bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.PickerPolishTest' --tests 'org.justinvisser.wolfskin.design.PickerNavigationTest' --tests 'org.justinvisser.wolfskin.design.ShellCaptureTest' --tests 'org.justinvisser.wolfskin.design.ScreenEntryNavigationTest' ``` New native regression command: ```sh bash docker/gradle.sh debug :wolfskin-design:cacheRobolectricSdk :app:testDefaultDebugUnitTest --tests 'org.justinvisser.wolfskin.tv.PersonCommitTest' --tests 'org.justinvisser.wolfskin.tv.NavigationCutTest' --tests 'org.justinvisser.wolfskin.tv.HomeHeroStartingTest' -x :wolfskin-design:testDebugUnitTest ``` Development run history (the command blocks here identify the exact selected classes): | Command | Observed results before the final pass | | --- | --- | | Picker-only design command below | 2 Ready-synchronization failures; fixed snapshot delivery before assertions | | Design command | One compile-only attempt used an unavailable clock-idleness API; corrected to the recomposer-idleness check, then 20/20 passed | | Native regression command | Baseline capture-only versions: 3/3 passed. Later iterations: 8/16, 11/16, 12/16, 14/18 and 16/18 passed while correcting observation/preconditions and reproducing the full-root flash | | Full targeted app command | 75/86 passed initially (all 70 neighbours green); 84/86 with only Back paint limits failing; 88/88 after the bridge fix; final 88/88 with transparent/delayed player loading exercised | ```sh bash docker/gradle.sh debug :wolfskin-design:testDebugUnitTest --tests 'org.justinvisser.wolfskin.design.PickerPolishTest' ``` Compile-only app attempts corrected a required DTO type, unsupported inline-value-class varargs, an unsupported named key-duration argument and a missing test-tag import. One baseline attempt timed out waiting/building before an app result; its queued retry produced the baseline captures. The first full-root fixture used a relaxed generic backdrop flow and failed with `Object` → `BackdropResult`; it now supplies a typed `BackdropResult.NONE` flow. No production exception was suppressed. Native flash reproduction XML and frames are retained under `data/polish-lane-c/validation/handoff-before/`; the discarded z-order trial is under `validation/z-order-attempt/`. Full targeted app command (new cases plus every named neighbour; no other test classes): ```sh bash docker/gradle.sh debug :wolfskin-design:cacheRobolectricSdk :app:testDefaultDebugUnitTest \ --tests 'org.justinvisser.wolfskin.tv.PersonCommitTest' \ --tests 'org.justinvisser.wolfskin.tv.NavigationCutTest' \ --tests 'org.justinvisser.wolfskin.tv.HomeHeroStartingTest' \ --tests 'org.justinvisser.wolfskin.tv.PersonPickerSessionTest' \ --tests 'org.justinvisser.wolfskin.tv.PersonSwitchThreadingTest' \ --tests 'org.justinvisser.wolfskin.tv.SavedPeoplePickerTest' \ --tests 'org.justinvisser.wolfskin.tv.UpstreamContentFocusTest' \ --tests 'org.justinvisser.wolfskin.tv.FirstSignInNavigationTest' \ --tests 'org.justinvisser.wolfskin.tv.WolfskinBackStackTest' \ --tests 'org.justinvisser.wolfskin.tv.TitleEntryBackTest' \ --tests 'org.justinvisser.wolfskin.tv.WolfskinRootExitTest' \ --tests 'org.justinvisser.wolfskin.tv.update.UpdatesKeysTest' \ --tests 'org.justinvisser.wolfskin.tv.HomeSeeAllNavigationTest' \ --tests 'org.justinvisser.wolfskin.tv.NavBandOcclusionTest' \ --tests 'org.justinvisser.wolfskin.tv.HomeRecoveryTest' \ --tests 'org.justinvisser.wolfskin.tv.ConductarrHomeSurfaceTest' \ --tests 'org.justinvisser.wolfskin.tv.TitlePlaybackNavigationTest' \ --tests 'org.justinvisser.wolfskin.tv.WatchReturnTest' \ --tests 'org.justinvisser.wolfskin.tv.PlayerHandoffTest' \ --tests 'org.justinvisser.wolfskin.tv.WatchReadTest' \ -x :wolfskin-design:testDebugUnitTest ``` ### New auth, identity and Back regressions `PersonCommitTest`: ```text failedCredentialSwitchRevealsSetupOnlyAfterThePickerIsCovered reducedMotionUsesOnlyTheShortFullPickerFade requireLoginPersonReturnsToSetupWithoutChangingCredentials pinProtectedPersonReturnsToSetupWithoutChangingCredentials choosingMindelCoversTheSwitchUntilTheirHomeCanPaint samePersonRunsTheChoreographyWithoutSwitchingCredentials ``` `NavigationCutTest`: ```text playbackVeilIgnoresKeysAndBackThenReturnsBackOwnershipToHome backBeforeTheBlackVeilCancelsThePendingStartWithoutExitingHome titleAndTabPaintWithinTwoFramesBackWithinFour reducedMotionKeepsOpaqueCutsAndRetiresOutgoingByFourFrames setupHostKeepsOpaquePaintAndRetiresOutgoingWithinFourFrames reducedMotionSetupHostKeepsTheSameCutDeadlines fullRootPlaybackHandoffNeverRepaintsHome reducedMotionFullRootHandoffNeverRepaintsHome ``` `HomeHeroStartingTest`: ```text leavingHomeCancelsPreparationAndCannotLaunchALateResult failedPreparationRestoresResumeAndShowsTheExistingRecoveryToast reducedMotionCapsBothFadesAndStillStartsOnce playSaysStartingThenFadesToBlackBeforeThePlayer ``` ### Native proof locations Root: `/root/.treehouse/firstmate-7bab20/2/firstmate/data/ui-polish-build/lane-c/`. - P07: `P07/{before,after}/{normal,reduced}/` (0–1400 ms / 100 ms). - P08: `P08/before/normal/` and `P08/after/{normal,reduced}/` (0–480 ms / 16 ms; picked Home and reduced-motion toggle hold included). - E01 and E04 baseline: `E01/before/normal/`, `E04/before/normal/`. - E01 after: `E01/after/{normal,reduced,setup-normal,setup-reduced}/`; open-title, Back and tab each run 0–320 ms / 16 ms. - E04: `E04/after/{normal,reduced}/` includes preparation, black fade and the first Home frame after returning; it excludes the empty test-harness player surface. - Full-root E04 boundary probe: `E04/{before,after}/{root-normal,root-reduced}/`. The incoming solid-blue scene is a **test renderer**, not a screenshot of a decoded player; before captures stop at the demonstrated old-Home flash. Only Docker-targeted unit/native scenarios were run. No full suite, APK build, emulator, m3 walk, TV, ADB, install or device launch. Player decoding/playback itself was not exercised by the native Home-to-destination harness. ## Exact auth, Back, identity and playback neighbour cases exercised The following 70 cases all passed; suffixed names are retained exactly from the XML. ### ConductarrHomeSurfaceTest ```text currentIdentityFeedsRealHomeAndSavedRequestsWithoutInventingJellyfinPlayback ``` ### FirstSignInNavigationTest ```text firstContinueThenMoviesRendersMindelsGridWithoutReenteringThePicker ``` ### HomeRecoveryTest ```text renamedHouseholdProfileKeepsItsOwnJellyfinLibraryWithoutAConductarrIdentity personBSeesNeitherPersonAsSavedHomeNorTheirLateRefreshResult readableJellyfinDoesNotBecomeAnOutageWhenLocalCacheCannotBeWritten savedHomePaintsBeforeRefreshAndStaysAfterFailedRetry ``` ### HomeSeeAllNavigationTest ```text personalMovieContinuationReachesTheEighteenthTitleAndReturnsToHome horizontallyScrolledContinuationRestoresTheExactHomeViewport ``` ### NavBandOcclusionTest ```text scrolledRowsNeverShowThroughTheNavBand ``` ### PersonPickerSessionTest ```text launchRightThenOneOkKeepsPickerClosed initialPersonNeedsOnlyOneOk fastLeftLeftOkKeepsPickerClosed avatarRightThenOneOkKeepsPickerClosed gearAndBackThenOneOkKeepsPickerClosed launchLeftThenOneOkKeepsPickerClosed avatarLeftThenOneOkKeepsPickerClosed ``` ### PersonSwitchThreadingTest ```text pickerSwitchesKeepPersonDataAndDisposeEveryClientOffMainWithoutWaiting rapidPickerChoicesIgnoreLateSignInAndCanReturnToTheOriginalPerson homeAndTitleRetriesReplaceSignedOutClientsWithoutMainThreadDisposal ``` ### PlayerHandoffTest ```text anotherPersonsSessionCannotResolveOrStartPlayback successfulPlaybackUsesTheRealFullscreenDestinationAndBackKeepsTheResumeCard failedPlaybackReadLeavesSavedHomeFocusedAndDrawsTheExactOfflineToast ``` ### SavedPeoplePickerTest ```text savedPeopleAreVisibleBeforeTheFirstNetworkResponse ``` ### TitleEntryBackTest ```text outgoingLoadedTitleCannotConsumeTheNextHomeBack[34] predictivePersonBackPopsOnlyOneEntry[34] outgoingLoadedPersonCannotConsumeTheNextHomeBack[34] nativeBackKeyWaitsForSystemCompletionBeforePoppingTheTitle[34] predictiveTitleBackPopsOnlyOneEntry[34] immediateSecondSystemBackUsesHomeBeforeExitRecomposition[34] outgoingLoadedTitleCannotConsumeTheNextHomeBack predictivePersonBackPopsOnlyOneEntry outgoingLoadedPersonCannotConsumeTheNextHomeBack nativeBackKeyWaitsForSystemCompletionBeforePoppingTheTitle predictiveTitleBackPopsOnlyOneEntry immediateSecondSystemBackUsesHomeBeforeExitRecomposition ``` ### TitlePlaybackNavigationTest ```text primarySeriesActionReResolvesNextUpButRestartAndExplicitEpisodesKeepTheirIdentity repeatedEpisodeChoicesReplaceOnlyEpisodesAndBackPreservesTheirSeriesParent ``` ### UpstreamContentFocusTest ```text switchOffShowsRealUpstreamBackdropAndSwitchOnRestoresOwnedBackground switchOffUpMovesBetweenContentRowsBeforeEnteringNav ``` ### WatchReadTest ```text freshResumeAndNextUpPaintBeforeSlowLibraryAndSurviveItsFailure bothFacadesUseTheLiveCheckpointAndSeriesNextUpWhileExplicitEpisodeKeepsItsIdentity mergedHomeUsesSeriesWatchActivityNotAnUnwatchedNextEpisodeDate ``` ### WatchReturnTest ```text acknowledgedStopRefreshesVisibleHeroWithoutRecreatingHomeOrLosingFocus ``` ### WolfskinBackStackTest ```text unsavedHomeSettingsPromptsBeforeDiscardCanExitTheTask pushedUpdatesPopsSettingsThenPickerBeforeRootExit singletonUpdatesBackFinishesInsteadOfBecomingADeadEnd ``` ### WolfskinRootExitTest ```text reopenedPickerBackDismissesToNavAndTheFollowingBackExits[34] showsContentThenNavBackFinishesTheActivity[34] moviesContentThenNavBackFinishesTheActivity[34] coldPickerBackFinishesWithoutSelectingAnAvatarOrShowingUpstreamUi[34] hardwareBackUsesTheSameContentNavExitLadder[34] homeContentThenNavBackFinishesTheActivity[34] animeContentThenNavBackFinishesTheActivity[34] discoverContentThenNavBackFinishesTheActivity[34] comingInSheetDismissesBeforeContentNavAndExit[34] reopenedPickerBackDismissesToNavAndTheFollowingBackExits showsContentThenNavBackFinishesTheActivity moviesContentThenNavBackFinishesTheActivity coldPickerBackFinishesWithoutSelectingAnAvatarOrShowingUpstreamUi hardwareBackUsesTheSameContentNavExitLadder homeContentThenNavBackFinishesTheActivity animeContentThenNavBackFinishesTheActivity discoverContentThenNavBackFinishesTheActivity comingInSheetDismissesBeforeContentNavAndExit ``` ### update.UpdatesKeysTest ```text longNotesScrollWithoutEscapingToNavOrAutoCheck progressKeepsAutoCheckFocusAcrossByteAndReducedMotionChanges navAndAutoCheckReturnToTheRememberedActionWithoutToggling refreshingInstalledIdentityCannotMaskAnOngoingCheck notesTrapRealKeysAndBackPreservesSettingsRowAndScroller classicRequiresEveryRetainedRowAndTheRealScroller ```
justinzeus added 6 commits 2026-11-08 05:36:56 +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:35 +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#80
No description provided.