Code Quality
Ktlint
Configured via org.jlleitschuh.gradle.ktlint in root build.gradle.kts.
./gradlew ktlintCheck # Check all
./gradlew ktlintFormat # Auto-format all
./gradlew :feature:sample:ktlintCheck # Check single module
.editorconfig rules:
[*.{kt,kts}]
ktlint_code_style = android_studio
ktlint_standard_no-wildcard-imports = disabled
ktlint_standard_package-name = disabled
Code Review Checklist
Architecture
- Follows MVI pattern (State/Event/Effect)
- Domain layer has no Android imports
- UseCase follows Interface + Impl pattern
- Screen has Stateful + Stateless split
- Proper use of BaseScreenComponent
Kotlin
- No
!!operator (userequireNotNullor safe calls) - Exhaustive
whenfor sealed classes -
data classfor State,sealed interfacefor Event/Effect - Extension functions are focused and reusable
Compose
-
collectAsStateWithLifecycle()for state collection -
LaunchedEffectoronEffectcallback for effects -
MaterialTheme.spacinginstead of hardcoded dp - Preview uses
FakeBaseViewModel+TemplateThemePreview - Stable keys for LazyList items
Error Handling
- Errors go through
AppErrorsealed class -
showErrorToast(error)in ViewModel - No swallowed exceptions
- New error types added to both
ExceptionMapperandErrorHandler
Testing
- ViewModel tests for
onTriggerEvent()and state changes - UseCase tests for business logic
-
MainDispatcherRuleused in coroutine tests
Git Conventions
Branch Naming
feature/add-profile-feature
fix/data-loading-crash
refactor/extract-base-screen
chore/update-dependencies
Commit Messages
feat: add profile functionality
fix: resolve data loading crash on slow network
refactor: extract BaseScreenComponent
chore: upgrade Gradle, AGP, Kotlin versions
test: add SampleViewModel unit tests
docs: update agent skills documentation
Module Dependency Enforcement
When adding new dependencies, verify:
- Feature modules NEVER depend on
data:* - Domain modules NEVER import
android.* - Feature modules don't depend on other feature modules (only
feature:core) - New modules use convention plugins from
build_logic/