Code review and quality
Skill GuillemRoca/agent-skills-android/skills/code-review-and-quality
Use when reviewing Android code (own or others'). Five-axis review framework: Correctness, Readability, Architecture, Security, Performance. Categorized findings with Kotlin/Compose-specific checks.From its SKILL.md
npx -y skills add GuillemRoca/agent-skills-android --skill code-review-and-qualityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 4 commands, including `./gradlew test` and 3 more.
SKILL.md
6.4 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it
Code Review and Quality
Overview
Review code across five axes: Correctness, Readability, Architecture, Security, and Performance. The approval standard: "Approve when it definitely improves overall code health of the system." Every finding is categorized and actionable.
When to Use
- Reviewing a pull request (own or teammate's)
- Self-review before creating a PR
- Requested code quality check on a specific file or module
- After completing a feature (final quality gate)
Skip when: Not reviewing code (this is a review skill, not a writing skill).
Core Process
Step 1: Understand Context
- Read the PR description — what problem does it solve?
- Read the spec or ticket — does the PR match the stated goal?
- Check the diff size — target ~100 lines, flag >1000 lines for splitting
Step 2: Review Tests First
- Start with test files — they reveal the intended behavior
- Check for:
- Are critical paths tested?
- Are edge cases covered (null, empty, error, boundary values)?
- Do test names describe behavior?
- Are tests independent (no shared mutable state)?
Step 3: Five-Axis Review
Axis 1: Correctness
- Verify behavior matches intent:
- Does the code handle all states? (loading, success, error, empty)
- Are nulls handled safely? (no
!!, proper?.chains) - Are coroutines structured correctly? (proper scope, cancellation)
- Are lifecycle-aware collections used? (
collectAsStateWithLifecycle) - Do Room queries match the schema?
- Are migrations correct and tested?
Axis 2: Readability
- Kotlin-specific readability:
// GOOD: idiomatic Kotlin
val activeTask = tasks.firstOrNull { !it.completed }
?: return TaskListUiState.Empty
// BAD: Java-style
var activeTask: Task? = null
for (task in tasks) {
if (!task.completed) {
activeTask = task
break
}
}
if (activeTask == null) return TaskListUiState.Empty
- Check for:
- Clear naming (functions describe actions, variables describe content)
- Appropriate use of
whenexpressions,let/also/apply, extension functions - Functions under ~40 lines
- Sealed classes/interfaces for exhaustive state handling
- No nested callbacks (use coroutines)
Axis 3: Architecture
-
Verify layer boundaries:
- UI layer only calls ViewModel (never Repository/DAO directly)
- Domain layer has no Android dependencies
- Data layer implements domain interfaces
- Feature modules don't depend on each other
- No business logic in Composables
-
Check for:
- Proper use of
@Inject constructor(not field injection) StateFlowexposed from ViewModel (notMutableStateFlow)- Repository pattern for data access
- Single source of truth (local DB for offline-first)
- Proper use of
Axis 4: Security
- Check for:
- No hardcoded secrets, API keys, or passwords
- Input validation for user-provided data
- Proper intent validation (exported components)
- No logging of sensitive data (
Log.dwith tokens, passwords) - Secure storage (EncryptedSharedPreferences for sensitive data)
- See
security-and-hardeningfor comprehensive checklist
Axis 5: Performance
- Check for:
- N+1 query patterns in Room
- Unbounded data loading (should use Paging3 for large datasets)
- Unnecessary recompositions in Compose (unstable parameters, lambda allocations)
- Heavy work on main thread (use
withContext(Dispatchers.IO)) - Memory leaks (Activity/Context references in singletons)
- See
performance-optimizationfor comprehensive checklist
Step 4: Categorize Findings
- Use severity categories:
| Category | Description | Action Required |
|---|---|---|
| Critical | Security vulnerability, data loss, crash | Must fix before merge |
| Important | Missing tests, architecture violation, bug risk | Should fix before merge |
| Suggestion | Better Kotlin idiom, readability improvement | Optional, author's discretion |
| Nit | Formatting, naming preference | Optional |
| FYI | Context or explanation, no action needed | Informational |
- Format findings:
**[Critical]** `TaskRepository.kt:45` — API key hardcoded in source.
Move to `local.properties` and access via `BuildConfig`.
**[Important]** `TaskListViewModel.kt:23` — Uses `GlobalScope.launch`.
Use `viewModelScope.launch` for proper lifecycle management.
**[Suggestion]** `TaskMapper.kt:12` — Could use `copy()` instead
of manual field mapping for partial updates.
Step 5: Verify Build and Tests
- Before approving:
./gradlew testpasses./gradlew assembleDebugbuilds./gradlew linthas no new warnings./gradlew detektpasses (if configured)
Common Rationalizations
| Shortcut | Why It Fails |
|---|---|
| "LGTM" without reading the code | Rubber-stamp reviews miss bugs. They also train teammates to skip reviews. |
| "I'll clean it up later" | Later never comes. Fix it now or create a tracked issue. |
| "It works, so it's fine" | Working code with poor architecture becomes non-working code during the next change. |
| "The author knows best" | Fresh eyes catch blind spots. That's the point of review. |
| "It's just a small change" | Small changes in the wrong layer create architectural debt. |
Red Flags
- PR over 1000 lines without justification
- No tests in the PR
- Tests that only cover happy path
!!(non-null assertion) without justificationGlobalScopeusage- Mutable state exposed from ViewModel
- Business logic in Composables
- Feature module depending on another feature module
- Secrets or API keys in source code
@Suppressannotations without explanatory comments
Verification
- All five axes reviewed (Correctness, Readability, Architecture, Security, Performance)
- Tests reviewed first (coverage, edge cases, naming)
- Findings categorized (Critical, Important, Suggestion, Nit, FYI)
- Critical findings resolved before approval
-
./gradlew testpasses -
./gradlew assembleDebugbuilds -
./gradlew lintclean - PR size reasonable (~100 lines, flagged if >1000)
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.