| name | post-edit-verification |
| description | Use this skill after every working session where Kotlin or Android code was created or modified, and ALWAYS before committing, opening a PR, or reporting work as done. Runs the same three quality gates CI runs — ktlint, detekt, and Android lint — so failures are caught locally instead of by GitHub Actions. |
Post-Edit Verification Skill
When to Use
Run these checks after every working session that touches Kotlin, Android, or shared module code — before committing, before opening a PR, before reporting work as done. CI fails on any of the three checks below; run them locally to avoid the round-trip.
CI Reference
.github/workflows/build.yaml (job linter) runs exactly two commands. Both must succeed:
./gradlew ktlintCheck detekt
./gradlew lintDebug
Mirror these locally — do not skip Android lint just because ktlint and detekt passed. They catch different classes of issues (Android lint covers MissingPermission, UnusedResources, manifest checks, etc. that ktlint and detekt don't).
Compilation Check
Compile the modules you modified. Target specific Gradle tasks for faster feedback:
./gradlew :<module-path>:compileDebugKotlinAndroid
./gradlew :<module-path>:compileKotlinIosArm64
./gradlew :composeApp:assembleDebug
Examples for common modules:
./gradlew :features:schedules:schedules-panes:compileDebugKotlinAndroid
./gradlew :features:navigation:compileDebugKotlinAndroid
./gradlew :shared:core:compileKotlinIosArm64
Quality Gates
All three must pass with zero violations.
1. ktlint + detekt
./gradlew ktlintCheck detekt
See the kotlin-linting skill for rules and thresholds. Auto-fix ktlint issues with ./gradlew ktlintFormat. Detekt cannot auto-fix — review build/reports/detekt/.
2. Android lint
./gradlew lintDebug
Android lint runs on all Android-targeting modules. Fail-fast scope: :androidApp:lintDebug is enough if you only touched the app module, but the top-level lintDebug matches CI exactly. Reports land in androidApp/build/reports/lint-results-debug.html.
Android lint catches issues the Kotlin tools don't:
MissingPermission — calls that need a runtime permission check
UnusedResources, IconMissingDensityFolder, etc. — resource hygiene
- Manifest issues —
exported flags, intent filters, deprecated APIs
- API-level usage — calls to APIs above
minSdk without a Build.VERSION.SDK_INT guard
When suppression is genuinely warranted, use @SuppressLint("RuleId") at the smallest possible scope and add a one-line comment explaining why the static check is wrong (e.g., the runtime check is stronger but lint can't see it).
Common Issues
| Issue | Tool | Fix |
|---|
| Import ordering | ktlint | Imports must be lexicographically sorted with no blank lines between them. java, javax, kotlin and aliases go last. |
| Wildcard imports | ktlint | Always use explicit imports. Never use *. |
| Duplicate imports | ktlint | When adding a new import, check it isn't already present elsewhere in the import block. Place it in the correct alphabetical position. |
ReturnCount (>2) | detekt | Collapse early returns into a single guard, or extract a helper function. |
ComplexCondition (>3 boolean ops) | detekt | Break the condition apart, or extract validation into a helper. |
MissingPermission on notify(), location calls, etc. | Android lint | Call ContextCompat.checkSelfPermission (or an equivalent gate like NotificationManagerCompat.areNotificationsEnabled()); if the gate is semantically stronger but lint can't see it, suppress at the function with a justifying comment. |
| Missing private helper functions | compile | If you reference a function in a composable, make sure it exists in the same file or is imported. |
Checklist
- Compile modified modules —
BUILD SUCCESSFUL
./gradlew ktlintCheck detekt — BUILD SUCCESSFUL
./gradlew lintDebug — BUILD SUCCESSFUL
- Fix any errors and re-run until all three are clean
- Then commit / open the PR