# HTML-Inspired Shell Migration Notes

Captured from the Unspooled HTML-inspired Compose TV shell migration.

## Clean-shell creation is not migration
Creating a new package such as `ui/html/` with design tokens, glass sidebar, poster card, catalog row, home screen, settings shell, and scaffold is only a safe staging step. It is not user-visible until NavHost and parent screens call it.

Required wording:
- OK: “new shell is built and ready to wire”
- OK: “root focus migration pass is complete”
- Not OK: “entire shell migration is complete” while old call sites still render active screens

## First migration pass that paid off
- Root `TvFocusController` provided from `MainActivity`
- scaffold/player/source/detail surfaces read `LocalTvFocusController.current`
- remove isolated local focus controllers inside scaffold/player/source panels
- remove competing/circular navigation rail paths when converging on one shell model
- force settings to a single navigation model instead of keeping user-selectable legacy rails during migration

## Verification pattern
Run all three before reporting completion:
```bash
JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 ./gradlew :app:compileDebugKotlin
JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 ./gradlew :app:testDebugUnitTest
JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 ./gradlew :app:assembleDebug
```

Also verify active wiring:
```bash
rg -n 'HtmlInspiredTvScaffold|HtmlHomeScreen|HtmlCatalogRow|rememberTvFocusController|NavigationRailWrapper|CircularRailNavigation|NetflixMediaCard|MediaCard' app/src/main/java --glob '*.kt'
```
Interpretation:
- new HTML components found only in their own package = staged, not wired
- old card/scaffold calls still active = partial migration
- multiple `rememberTvFocusController()` calls outside root = split-brain focus bug

## Extra pitfall found during verification
`SourceRanker` regex/parsing must tolerate invalid user-configured patterns. If ranking preferences allow arbitrary regex-like input, invalid patterns should fail closed or be ignored, not crash ranking/playback.
