Part of the Detour Kotlin guidelines. Section numbers are stable across files — a reference like §8.4 always means §8.4, wherever it lives.
| Rule | Detour form |
|---|---|
| File name | PascalCase, named for its main type: SpeedLimitTracker.kt |
| One top-level type per file | kept, except for a state file’s row types next to its state class |
| Package is the namespace | no barrels, no re-export files |
| Public surface | internal controls it; module-scoped, and :shared is a real module boundary |
| Mappers | extension or xStateFrom(...) free function, never mapXToY(x) |
| DTOs | plain names — SendMessageRequest, not …Input |
| State | XState / XUiState suffix; all fields defaulted |
| Constants | SCREAMING_SNAKE_CASE, named, never an inline literal if a second surface has the same number |
| Implementations | Impl suffix only for the single obvious implementation |
| Packages | com.jellemax.detour.{data,drive,presentation} in shared, com.jellemax.detour.{ui,car,tracking,…} in app |
:app:detekt and :shared:detekt are a CI gate (config/detekt/detekt.yml, detekt’s defaults
plus the io.nlopez.compose.rules ruleset). Of the table above it catches only
the mechanical rows, through detekt’s default naming rules: a file named for its
type (MatchingDeclarationName) and SCREAMING_SNAKE_CASE for top-level
const vals (TopLevelPropertyNaming) — a constant inside an object or
companion may still be camelCase (ObjectPropertyNaming). What it
mostly enforces is size and Compose shape — the complexity thresholds
(LongParameterList at 7, the §8.4 gate), MaxLineLength at 120, and the
Compose rules (ModifierMissing, ViewModelForwarding,
CompositionLocalAllowlist, ComposableNaming, …). It runs on :app and on
:shared’s commonMain/androidMain/iosMain, and fails on new violations
only; existing ones sit in config/detekt/baseline-{app,shared}.xml, whose entry
counts ArchitectureTest pins so a baseline can only shrink. There is no ktlint or formatter, and
WildcardImport and MagicNumber are off, so formatting and the rest of the
table are by hand and by review, which is why they are worth stating.
Why-not-what (CONTRIBUTING.md § “Code style”). The house style is a KDoc that
explains a decision — why this shape, why not the obvious one, which bug it
prevents. A comment that says “same fix as X” or “identical to the Android
service” is a promise, not an enforcement mechanism; when you write one,
you are recording a known divergence risk, and it belongs in
docs/refactor/mapscreen/15-divergence-register.md too.