## SHARED SCREEN CONTRACT — fixed by the orchestrator, IDENTICAL in both wave-3 ## prompts. Do NOT change these signatures. E1 writes BookshelfNavHost against them; ## E2 writes the screens to match. If you deviate, the other worker's code stops ## compiling and the wave fails. Routes (string constants live in ui/nav/Routes.kt, owned by E1): "setup" | "library" | "library?shelfId={shelfId}" | "detail/{bookId}" | "scan" | "locations" | "settings" Screen composable signatures: // E2 owns @Composable fun LibraryScreen( shelfIdFilter: String?, onBookClick: (String) -> Unit, onScanClick: () -> Unit, onLocationsClick: () -> Unit, onSettingsClick: () -> Unit, container: AppContainer, ) @Composable fun DetailScreen( bookId: String, onBack: () -> Unit, container: AppContainer, ) @Composable fun ScanScreen( onBack: () -> Unit, container: AppContainer, ) // E1 owns @Composable fun SetupScreen(onSetupComplete: () -> Unit, container: AppContainer) @Composable fun LocationsScreen( onBack: () -> Unit, onShelfClick: (String) -> Unit, // navigates to library?shelfId=... container: AppContainer, ) @Composable fun SettingsScreen( onBack: () -> Unit, onSignedOut: () -> Unit, // navigates back to "setup" container: AppContainer, ) All screens take `container: AppContainer` and construct their own ViewModel from it (manual DI per SPEC — NO Hilt). Package = ui., e.g. ui.library.LibraryScreen.