# Code Quality

> Code quality guidelines for this project. Covers ktlint configuration and commands, architecture/Kotlin/Compose/error/testing review checklists, git branch naming and commit message conventions, and module dependency enforcement rules. Automatically applied during code review.

- Skill: `thetruong1099/code-quality` (Agent Skill)
- Install (CLI): `npx skillmds@latest add thetruong1099/code-quality`
- Raw SKILL.md: https://api.skillmd.com/api/skills/thetruong1099/code-quality/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: thetruong1099 (https://skillmd.com/u/thetruong1099)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/thetruong1099/code-quality

---


# Code Quality

## Ktlint

Configured via `org.jlleitschuh.gradle.ktlint` in root `build.gradle.kts`.

```bash
./gradlew ktlintCheck                         # Check all
./gradlew ktlintFormat                        # Auto-format all
./gradlew :feature:sample:ktlintCheck         # Check single module
```

`.editorconfig` rules:

```ini
[*.{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 (use `requireNotNull` or safe calls)
- [ ] Exhaustive `when` for sealed classes
- [ ] `data class` for State, `sealed interface` for Event/Effect
- [ ] Extension functions are focused and reusable

### Compose

- [ ] `collectAsStateWithLifecycle()` for state collection
- [ ] `LaunchedEffect` or `onEffect` callback for effects
- [ ] `MaterialTheme.spacing` instead of hardcoded dp
- [ ] Preview uses `FakeBaseViewModel` + `TemplateThemePreview`
- [ ] Stable keys for LazyList items

### Error Handling

- [ ] Errors go through `AppError` sealed class
- [ ] `showErrorToast(error)` in ViewModel
- [ ] No swallowed exceptions
- [ ] New error types added to both `ExceptionMapper` and `ErrorHandler`

### Testing

- [ ] ViewModel tests for `onTriggerEvent()` and state changes
- [ ] UseCase tests for business logic
- [ ] `MainDispatcherRule` used 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:

1. Feature modules NEVER depend on `data:*`
2. Domain modules NEVER import `android.*`
3. Feature modules don't depend on other feature modules (only `feature:core`)
4. New modules use convention plugins from `build_logic/`

