@mmerterden/multi-agent-pipeline 20.1.0 → 20.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/docs/facts.json +6 -6
  3. package/manifest.json +55 -34
  4. package/package.json +1 -1
  5. package/pipeline/multi-agent-refs/features/usage-reporting.md +7 -3
  6. package/pipeline/schemas/prefs.schema.json +4 -0
  7. package/pipeline/scripts/usage-register.mjs +2 -0
  8. package/pipeline/skills/.skill-manifest.json +36 -20
  9. package/pipeline/skills/.skills-index.json +75 -9
  10. package/pipeline/skills/shared/README.md +13 -7
  11. package/pipeline/skills/shared/external/android-architecture/SKILL.md +71 -0
  12. package/pipeline/skills/shared/external/android-architecture/references/patterns.md +142 -0
  13. package/pipeline/skills/shared/external/android-build-quality-gates/SKILL.md +314 -0
  14. package/pipeline/skills/shared/external/android-build-quality-gates/references/patterns.md +432 -0
  15. package/pipeline/skills/shared/external/android-datastore/SKILL.md +236 -0
  16. package/pipeline/skills/shared/external/android-datastore/references/patterns.md +297 -0
  17. package/pipeline/skills/shared/external/android-design-tokens-codegen/SKILL.md +249 -0
  18. package/pipeline/skills/shared/external/android-design-tokens-codegen/references/patterns.md +270 -0
  19. package/pipeline/skills/shared/external/android-jetpack-compose-expert/SKILL.md +62 -0
  20. package/pipeline/skills/shared/external/android-mvi-viewmodel/SKILL.md +255 -0
  21. package/pipeline/skills/shared/external/android-mvi-viewmodel/references/patterns.md +257 -0
  22. package/pipeline/skills/shared/external/android-performance/SKILL.md +86 -602
  23. package/pipeline/skills/shared/external/android-performance/references/patterns.md +659 -0
  24. package/pipeline/skills/shared/external/android-security/SKILL.md +117 -430
  25. package/pipeline/skills/shared/external/android-security/references/patterns.md +690 -0
  26. package/pipeline/skills/shared/external/{android_ui_verification → android-ui-verification}/SKILL.md +1 -1
  27. package/pipeline/skills/shared/external/api-security-best-practices/SKILL.md +35 -733
  28. package/pipeline/skills/shared/external/api-security-best-practices/references/auth.md +299 -0
  29. package/pipeline/skills/shared/external/api-security-best-practices/references/input-validation.md +255 -0
  30. package/pipeline/skills/shared/external/api-security-best-practices/references/rate-limiting.md +167 -0
  31. package/pipeline/skills/shared/external/app-intents/SKILL.md +39 -174
  32. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +178 -0
  33. package/pipeline/skills/shared/external/compose-components/SKILL.md +48 -0
  34. package/pipeline/skills/shared/external/compose-components/references/patterns.md +200 -0
  35. package/pipeline/skills/shared/external/compose-navigation/SKILL.md +66 -3
  36. package/pipeline/skills/shared/external/compose-navigation/references/patterns.md +191 -0
  37. package/pipeline/skills/shared/external/compose-testing/SKILL.md +107 -397
  38. package/pipeline/skills/shared/external/compose-testing/references/patterns.md +631 -0
  39. package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +121 -449
  40. package/pipeline/skills/shared/external/gradle-kotlin-dsl/references/patterns.md +715 -0
  41. package/pipeline/skills/shared/external/kotlin-coroutines-expert/SKILL.md +143 -0
  42. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +27 -102
  43. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +42 -0
  44. package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +94 -383
  45. package/pipeline/skills/shared/external/retrofit-networking/references/patterns.md +640 -0
  46. package/pipeline/skills/shared/external/room-database/SKILL.md +101 -440
  47. package/pipeline/skills/shared/external/room-database/references/patterns.md +614 -0
  48. package/pipeline/skills/shared/external/storekit/SKILL.md +69 -343
  49. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +371 -0
  50. package/pipeline/skills/shared/external/widgetkit/SKILL.md +25 -101
  51. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +107 -0
  52. package/pipeline/skills/skills-index.md +8 -2
@@ -8,10 +8,19 @@ description: "Configure Android builds with Gradle Kotlin DSL, version catalogs
8
8
  Modern Gradle build configuration for Android projects using Kotlin DSL,
9
9
  version catalogs, and convention plugins. Targets AGP 8.x+ and Gradle 8.x+.
10
10
 
11
+ Full, copy-ready configuration for every section below lives in
12
+ [references/patterns.md](references/patterns.md). Load that file when you need a
13
+ complete example to adapt (catalog, convention plugin, module build file,
14
+ ProGuard rules, or `gradle.properties`). Each heading there mirrors a section
15
+ here.
16
+
11
17
  ## Contents
12
18
 
13
19
  - [Version Catalog](#version-catalog)
14
20
  - [Convention Plugins](#convention-plugins)
21
+ - [Convention Plugin Composition](#convention-plugin-composition)
22
+ - [Typed BuildConfig Injection](#typed-buildconfig-injection)
23
+ - [Typed Module Paths and Flavors](#typed-module-paths-and-flavors)
15
24
  - [App Module Configuration](#app-module-configuration)
16
25
  - [Library Module Configuration](#library-module-configuration)
17
26
  - [Compose Configuration](#compose-configuration)
@@ -19,490 +28,148 @@ version catalogs, and convention plugins. Targets AGP 8.x+ and Gradle 8.x+.
19
28
  - [Signing Config](#signing-config)
20
29
  - [R8 and ProGuard](#r8-and-proguard)
21
30
  - [Build Performance](#build-performance)
31
+ - [Fast-Feedback Tasks](#fast-feedback-tasks)
22
32
  - [Do's and Don'ts](#dos-and-donts)
23
33
  - [Troubleshooting](#troubleshooting)
24
34
  - [Review Checklist](#review-checklist)
25
35
 
26
36
  ## Version Catalog
27
37
 
28
- Define all versions, libraries, and plugins in `gradle/libs.versions.toml`:
29
-
30
- ```toml
31
- [versions]
32
- agp = "8.7.3"
33
- kotlin = "2.1.0"
34
- ksp = "2.1.0-1.0.29"
35
- compose-bom = "2024.12.01"
36
- hilt = "2.53.1"
37
- room = "2.6.1"
38
- retrofit = "2.11.0"
39
- okhttp = "4.12.0"
40
- coroutines = "1.9.0"
41
- lifecycle = "2.8.7"
42
- navigation = "2.8.5"
43
- serialization = "1.7.3"
44
- coil = "2.7.0"
45
- turbine = "1.2.0"
46
- roborazzi = "1.32.2"
47
-
48
- [libraries]
49
- # Compose
50
- compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
51
- compose-ui = { group = "androidx.compose.ui", name = "ui" }
52
- compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
53
- compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
54
- compose-material3 = { group = "androidx.compose.material3", name = "material3" }
55
- compose-runtime = { group = "androidx.compose.runtime", name = "runtime" }
56
-
57
- # Lifecycle
58
- lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" }
59
- lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" }
60
-
61
- # Navigation
62
- navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
63
-
64
- # Hilt
65
- hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
66
- hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
67
- hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version = "1.2.0" }
68
-
69
- # Room
70
- room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
71
- room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
72
- room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
73
- room-testing = { group = "androidx.room", name = "room-testing", version.ref = "room" }
74
-
75
- # Network
76
- retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
77
- okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
78
- okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
79
- serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "serialization" }
80
- retrofit-serialization = { group = "com.squareup.retrofit2", name = "converter-kotlinx-serialization", version = "2.11.0" }
81
-
82
- # Coroutines
83
- coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" }
84
- coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" }
85
- coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "coroutines" }
86
-
87
- # Image loading
88
- coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" }
89
-
90
- # Testing
91
- junit = { group = "junit", name = "junit", version = "4.13.2" }
92
- turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" }
93
- truth = { group = "com.google.truth", name = "truth", version = "1.4.4" }
94
- compose-ui-test = { group = "androidx.compose.ui", name = "ui-test-junit4" }
95
- compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
96
- roborazzi = { group = "io.github.takahirom.roborazzi", name = "roborazzi", version.ref = "roborazzi" }
97
- roborazzi-compose = { group = "io.github.takahirom.roborazzi", name = "roborazzi-compose", version.ref = "roborazzi" }
98
-
99
- [bundles]
100
- compose = ["compose-ui", "compose-ui-tooling-preview", "compose-material3", "compose-runtime"]
101
- compose-debug = ["compose-ui-tooling", "compose-ui-test-manifest"]
102
- lifecycle = ["lifecycle-runtime-compose", "lifecycle-viewmodel-compose"]
103
- room = ["room-runtime", "room-ktx"]
104
- network = ["retrofit", "okhttp", "okhttp-logging", "serialization-json", "retrofit-serialization"]
105
-
106
- [plugins]
107
- android-application = { id = "com.android.application", version.ref = "agp" }
108
- android-library = { id = "com.android.library", version.ref = "agp" }
109
- kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
110
- kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
111
- compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
112
- ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
113
- hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
114
- room = { id = "androidx.room", version.ref = "room" }
115
- ```
38
+ Declare every version, library, and plugin in `gradle/libs.versions.toml` under
39
+ `[versions]`, `[libraries]`, `[bundles]`, and `[plugins]`. Reference them with
40
+ `libs.xxx`, `libs.bundles.xxx`, and `alias(libs.plugins.xxx)`; never hardcode a
41
+ version in a `build.gradle.kts`.
42
+
43
+ Full catalog (Compose BOM, Hilt, Room, Retrofit, coroutines, testing, bundles,
44
+ plugins): [references/patterns.md#version-catalog](references/patterns.md#version-catalog).
116
45
 
117
46
  ## Convention Plugins
118
47
 
119
- Create a `build-logic` module to share common configurations:
120
-
121
- ### settings.gradle.kts (root)
122
-
123
- ```kotlin
124
- pluginManagement {
125
- includeBuild("build-logic")
126
- repositories {
127
- google()
128
- mavenCentral()
129
- gradlePluginPortal()
130
- }
131
- }
132
- ```
133
-
134
- ### build-logic/settings.gradle.kts
135
-
136
- ```kotlin
137
- dependencyResolutionManagement {
138
- repositories {
139
- google()
140
- mavenCentral()
141
- }
142
- versionCatalogs {
143
- create("libs") {
144
- from(files("../gradle/libs.versions.toml"))
145
- }
146
- }
147
- }
148
-
149
- include(":convention")
150
- ```
151
-
152
- ### build-logic/convention/build.gradle.kts
153
-
154
- ```kotlin
155
- plugins {
156
- `kotlin-dsl`
157
- }
158
-
159
- dependencies {
160
- compileOnly(libs.android.gradlePlugin)
161
- compileOnly(libs.kotlin.gradlePlugin)
162
- compileOnly(libs.compose.gradlePlugin)
163
- }
164
- ```
165
-
166
- ### Android Library Convention Plugin
167
-
168
- ```kotlin
169
- // build-logic/convention/src/main/kotlin/AndroidLibraryConventionPlugin.kt
170
- import com.android.build.gradle.LibraryExtension
171
- import org.gradle.api.Plugin
172
- import org.gradle.api.Project
173
- import org.gradle.kotlin.dsl.configure
174
-
175
- class AndroidLibraryConventionPlugin : Plugin<Project> {
176
- override fun apply(target: Project) {
177
- with(target) {
178
- with(pluginManager) {
179
- apply("com.android.library")
180
- apply("org.jetbrains.kotlin.android")
181
- }
182
-
183
- extensions.configure<LibraryExtension> {
184
- compileSdk = 35
185
- defaultConfig {
186
- minSdk = 26
187
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
188
- }
189
- compileOptions {
190
- sourceCompatibility = JavaVersion.VERSION_17
191
- targetCompatibility = JavaVersion.VERSION_17
192
- }
193
- }
194
- }
195
- }
196
- }
197
- ```
198
-
199
- ### Register in build-logic/convention/build.gradle.kts
200
-
201
- ```kotlin
202
- gradlePlugin {
203
- plugins {
204
- register("androidLibrary") {
205
- id = "app.android.library"
206
- implementationClass = "AndroidLibraryConventionPlugin"
207
- }
208
- register("androidCompose") {
209
- id = "app.android.compose"
210
- implementationClass = "AndroidComposeConventionPlugin"
211
- }
212
- register("androidHilt") {
213
- id = "app.android.hilt"
214
- implementationClass = "AndroidHiltConventionPlugin"
215
- }
216
- }
217
- }
218
- ```
219
-
220
- ### Usage in Feature Module
221
-
222
- ```kotlin
223
- // feature/home/build.gradle.kts
224
- plugins {
225
- id("app.android.library")
226
- id("app.android.compose")
227
- id("app.android.hilt")
228
- }
229
-
230
- dependencies {
231
- implementation(project(":core:model"))
232
- implementation(project(":core:data"))
233
- implementation(project(":core:ui"))
234
- }
235
- ```
48
+ Share Android/Compose/Hilt configuration through a `build-logic` included build
49
+ instead of copying blocks between modules. Root `settings.gradle.kts` does
50
+ `includeBuild("build-logic")`; the convention module implements
51
+ `Plugin<Project>` classes and registers them with stable ids
52
+ (`app.android.library`, `app.android.compose`, `app.android.hilt`) that feature
53
+ modules then apply.
54
+
55
+ Full wiring (settings files, `Plugin<Project>` class, `gradlePlugin` registration,
56
+ feature-module usage):
57
+ [references/patterns.md#convention-plugins](references/patterns.md#convention-plugins).
58
+
59
+ ## Convention Plugin Composition
60
+
61
+ Compose plugins into a ladder: a higher-level plugin applies the lower ones. A
62
+ single `feature-impl` plugin applies library + hilt + compose + test and wires
63
+ the standard dependency set, so a feature module's `plugins {}` block is one
64
+ line. Put shared toolchain and compiler flags (`jvmTarget`, strict explicit-api,
65
+ `compileSdk`/`minSdk`, Java 17) in one `configureKotlinAndroid()` extension that
66
+ every Android convention plugin calls, so no value is duplicated across plugins.
67
+
68
+ Alias your own convention plugins in the version catalog
69
+ (`app-android-feature = { id = "app.android.feature", version = "unspecified" }`)
70
+ so modules apply `alias(libs.plugins.app.android.feature)` rather than a raw id
71
+ string.
72
+
73
+ For build-FAILING quality-gate tasks (module-layer checks, coverage floor,
74
+ Compose stability gate), see the `android-build-quality-gates` skill; those
75
+ tasks are not reproduced here.
76
+
77
+ Full ladder plugin, `configureKotlinAndroid()`, and catalog aliases:
78
+ [references/patterns.md#convention-plugin-composition](references/patterns.md#convention-plugin-composition).
79
+
80
+ ## Typed BuildConfig Injection
81
+
82
+ Replace scattered `buildConfigField("String", "KEY", "\"...\"")` strings with a
83
+ typed key `enum` (each key carries its Java type), per-module `contributor`
84
+ objects, and a central `resolver` that filters contributions by module scope and
85
+ de-dupes by key. The convention plugin materializes the resolved entries once per
86
+ flavor, so the type is always right and no module hand-writes a `buildConfigField`.
87
+
88
+ Full key enum, contributor interface, and resolver:
89
+ [references/patterns.md#typed-buildconfig-injection](references/patterns.md#typed-buildconfig-injection).
90
+
91
+ ## Typed Module Paths and Flavors
92
+
93
+ Model module paths and flavors as `sealed`/`enum` types so builds reference
94
+ `Module.Core.Domain.toProject()` instead of the stringly-typed
95
+ `project(":core:domain")`, and `Flavor.PROD.baseUrl` instead of a repeated URL
96
+ literal. A typo becomes a compile error, and refactoring a path updates one
97
+ declaration.
98
+
99
+ Full sealed `Module` hierarchy, `toProject()`, and `Flavor` enum:
100
+ [references/patterns.md#typed-module-paths-and-flavors](references/patterns.md#typed-module-paths-and-flavors).
236
101
 
237
102
  ## App Module Configuration
238
103
 
239
- ```kotlin
240
- // app/build.gradle.kts
241
- plugins {
242
- alias(libs.plugins.android.application)
243
- alias(libs.plugins.kotlin.android)
244
- alias(libs.plugins.compose.compiler)
245
- alias(libs.plugins.hilt)
246
- alias(libs.plugins.ksp)
247
- }
248
-
249
- android {
250
- namespace = "com.example.app"
251
- compileSdk = 35
252
-
253
- defaultConfig {
254
- applicationId = "com.example.app"
255
- minSdk = 26
256
- targetSdk = 35
257
- versionCode = 1
258
- versionName = "1.0.0"
259
- testInstrumentationRunner = "com.example.app.HiltTestRunner"
260
- }
261
-
262
- buildTypes {
263
- release {
264
- isMinifyEnabled = true
265
- isShrinkResources = true
266
- proguardFiles(
267
- getDefaultProguardFile("proguard-android-optimize.txt"),
268
- "proguard-rules.pro",
269
- )
270
- }
271
- debug {
272
- isMinifyEnabled = false
273
- applicationIdSuffix = ".debug"
274
- }
275
- }
276
-
277
- compileOptions {
278
- sourceCompatibility = JavaVersion.VERSION_17
279
- targetCompatibility = JavaVersion.VERSION_17
280
- }
281
-
282
- kotlinOptions {
283
- jvmTarget = "17"
284
- }
285
- }
286
-
287
- dependencies {
288
- implementation(platform(libs.compose.bom))
289
- implementation(libs.bundles.compose)
290
- implementation(libs.bundles.lifecycle)
291
- implementation(libs.navigation.compose)
292
- implementation(libs.hilt.android)
293
- ksp(libs.hilt.compiler)
294
- implementation(libs.hilt.navigation.compose)
295
-
296
- debugImplementation(libs.bundles.compose.debug)
297
-
298
- testImplementation(libs.junit)
299
- testImplementation(libs.truth)
300
- testImplementation(libs.coroutines.test)
301
- testImplementation(libs.turbine)
302
-
303
- androidTestImplementation(platform(libs.compose.bom))
304
- androidTestImplementation(libs.compose.ui.test)
305
- }
306
- ```
104
+ Apply plugins via `alias(libs.plugins.xxx)`, set `namespace`/`compileSdk`/
105
+ `defaultConfig`, enable `isMinifyEnabled` + `isShrinkResources` on `release`,
106
+ target Java 17, and pull dependencies from the catalog (`platform(libs.compose.bom)`,
107
+ bundles, `ksp(libs.hilt.compiler)`).
108
+
109
+ Full `app/build.gradle.kts`:
110
+ [references/patterns.md#app-module-configuration](references/patterns.md#app-module-configuration).
307
111
 
308
112
  ## Library Module Configuration
309
113
 
310
- ```kotlin
311
- // core/data/build.gradle.kts
312
- plugins {
313
- alias(libs.plugins.android.library)
314
- alias(libs.plugins.kotlin.android)
315
- alias(libs.plugins.hilt)
316
- alias(libs.plugins.ksp)
317
- }
318
-
319
- android {
320
- namespace = "com.example.core.data"
321
- compileSdk = 35
322
-
323
- defaultConfig {
324
- minSdk = 26
325
- }
326
- }
327
-
328
- dependencies {
329
- implementation(project(":core:model"))
330
- implementation(project(":core:network"))
331
- implementation(project(":core:database"))
332
- implementation(libs.hilt.android)
333
- ksp(libs.hilt.compiler)
334
- implementation(libs.coroutines.core)
335
-
336
- testImplementation(libs.junit)
337
- testImplementation(libs.truth)
338
- testImplementation(libs.coroutines.test)
339
- }
340
- ```
114
+ A library module mirrors the app module but applies `libs.plugins.android.library`,
115
+ declares only its `namespace`/`minSdk`, and depends on sibling `project(...)`
116
+ modules. Full `core/data/build.gradle.kts`:
117
+ [references/patterns.md#library-module-configuration](references/patterns.md#library-module-configuration).
341
118
 
342
119
  ## Compose Configuration
343
120
 
344
- ```kotlin
345
- // Convention plugin or inline
346
- android {
347
- buildFeatures {
348
- compose = true
349
- }
350
- }
351
-
352
- // With Kotlin 2.0+, use the Compose Compiler plugin:
353
- plugins {
354
- alias(libs.plugins.compose.compiler)
355
- }
356
-
357
- // Optional: Compose compiler metrics for performance debugging
358
- // In gradle.properties or via command line:
359
- // composeCompiler.reportsDestination=build/compose-reports
360
- // composeCompiler.metricsDestination=build/compose-metrics
361
- ```
121
+ Enable `buildFeatures { compose = true }` and apply the Compose Compiler plugin
122
+ (`alias(libs.plugins.compose.compiler)`) on Kotlin 2.0+. Compiler metrics/reports
123
+ are opt-in via `composeCompiler.*Destination`.
124
+
125
+ Full snippet: [references/patterns.md#compose-configuration](references/patterns.md#compose-configuration).
362
126
 
363
127
  ## Build Variants and Flavors
364
128
 
365
- ```kotlin
366
- android {
367
- buildTypes {
368
- release {
369
- isMinifyEnabled = true
370
- isShrinkResources = true
371
- proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
372
- }
373
- debug {
374
- isMinifyEnabled = false
375
- applicationIdSuffix = ".debug"
376
- isDebuggable = true
377
- }
378
- create("staging") {
379
- initWith(getByName("release"))
380
- applicationIdSuffix = ".staging"
381
- isMinifyEnabled = true
382
- matchingFallbacks += "release"
383
- }
384
- }
385
-
386
- flavorDimensions += "environment"
387
- productFlavors {
388
- create("dev") {
389
- dimension = "environment"
390
- applicationIdSuffix = ".dev"
391
- buildConfigField("String", "BASE_URL", "\"https://dev-api.example.com/\"")
392
- }
393
- create("prod") {
394
- dimension = "environment"
395
- buildConfigField("String", "BASE_URL", "\"https://api.example.com/\"")
396
- }
397
- }
398
- }
399
- ```
129
+ Extend `buildTypes` (e.g. a `staging` type via `initWith(getByName("release"))`)
130
+ and declare `productFlavors` under a `flavorDimensions` axis, using
131
+ `buildConfigField` for per-environment values like the base URL.
132
+
133
+ Full variants + flavors block:
134
+ [references/patterns.md#build-variants-and-flavors](references/patterns.md#build-variants-and-flavors).
400
135
 
401
136
  ## Signing Config
402
137
 
403
- ```kotlin
404
- android {
405
- signingConfigs {
406
- create("release") {
407
- storeFile = file(System.getenv("KEYSTORE_PATH") ?: "release.keystore")
408
- storePassword = System.getenv("KEYSTORE_PASSWORD") ?: ""
409
- keyAlias = System.getenv("KEY_ALIAS") ?: ""
410
- keyPassword = System.getenv("KEY_PASSWORD") ?: ""
411
- }
412
- }
413
-
414
- buildTypes {
415
- release {
416
- signingConfig = signingConfigs.getByName("release")
417
- }
418
- }
419
- }
420
- ```
421
-
422
- Never commit keystore passwords. Use environment variables or `local.properties` (gitignored).
138
+ Read keystore path and credentials from environment variables (or gitignored
139
+ `local.properties`), never from committed source, and attach the config to the
140
+ `release` build type. Full `signingConfigs` block:
141
+ [references/patterns.md#signing-config](references/patterns.md#signing-config).
423
142
 
424
143
  ## R8 and ProGuard
425
144
 
426
- ### proguard-rules.pro
427
-
428
- ```proguard
429
- # Kotlin serialization
430
- -keepattributes *Annotation*, InnerClasses
431
- -dontnote kotlinx.serialization.AnnotationsKt
432
-
433
- -keepclassmembers class kotlinx.serialization.json.** {
434
- *** Companion;
435
- }
436
- -keepclasseswithmembers class kotlinx.serialization.json.** {
437
- kotlinx.serialization.KSerializer serializer(...);
438
- }
439
- -keep,includedescriptorclasses class com.example.app.data.dto.**$$serializer { *; }
440
- -keepclassmembers class com.example.app.data.dto.** {
441
- *** Companion;
442
- }
443
- -keepclasseswithmembers class com.example.app.data.dto.** {
444
- kotlinx.serialization.KSerializer serializer(...);
445
- }
446
-
447
- # Retrofit
448
- -keepattributes Signature
449
- -keepattributes Exceptions
450
- -keepclassmembers,allowshrinking,allowobfuscation interface * {
451
- @retrofit2.http.* <methods>;
452
- }
453
- -dontwarn javax.annotation.**
454
- -dontwarn kotlin.Unit
455
- -dontwarn retrofit2.KotlinExtensions
456
- -dontwarn retrofit2.KotlinExtensions$*
457
-
458
- # OkHttp
459
- -dontwarn okhttp3.internal.platform.**
460
- -dontwarn org.conscrypt.**
461
- -dontwarn org.bouncycastle.**
462
- -dontwarn org.openjsse.**
463
-
464
- # Hilt
465
- -keep class dagger.hilt.** { *; }
466
- ```
145
+ Keep rules are needed for reflection-driven libraries: kotlinx serialization
146
+ (`$$serializer` classes and `Companion`), Retrofit (`@retrofit2.http.*` methods,
147
+ signatures), OkHttp `-dontwarn`s, and Hilt. Never use a global `-dontwarn *`.
467
148
 
468
- ## Build Performance
149
+ Full `proguard-rules.pro`:
150
+ [references/patterns.md#r8-and-proguard](references/patterns.md#r8-and-proguard).
469
151
 
470
- ### gradle.properties
471
-
472
- ```properties
473
- # Parallel execution
474
- org.gradle.parallel=true
475
-
476
- # Configuration cache
477
- org.gradle.configuration-cache=true
478
-
479
- # Build cache
480
- org.gradle.caching=true
481
-
482
- # JVM memory
483
- org.gradle.jvmargs=-Xmx4g -XX:+UseG1GC -XX:MaxMetaspaceSize=1g
152
+ ## Build Performance
484
153
 
485
- # Kotlin daemon
486
- kotlin.daemon.jvmargs=-Xmx2g
154
+ Enable parallel execution, configuration cache, build cache, sized JVM/daemon
155
+ memory, and `android.nonTransitiveRClass=true` in `gradle.properties`; disable
156
+ unused `buildfeatures`. Optionally lock dependencies with `dependencyLocking`.
487
157
 
488
- # Non-transitive R classes (reduces rebuild scope)
489
- android.nonTransitiveRClass=true
158
+ Full `gradle.properties` and locking snippet:
159
+ [references/patterns.md#build-performance](references/patterns.md#build-performance).
490
160
 
491
- # Disable unused features
492
- android.defaults.buildfeatures.buildconfig=false
493
- android.defaults.buildfeatures.aidl=false
494
- android.defaults.buildfeatures.renderscript=false
495
- ```
161
+ Keep the build cache (`org.gradle.caching=true`) in this perf-flag set alongside
162
+ parallel execution and the configuration cache.
496
163
 
497
- ### Dependency Locking
164
+ ## Fast-Feedback Tasks
498
165
 
499
- ```kotlin
500
- dependencyLocking {
501
- lockAllConfigurations()
502
- }
166
+ Install git hooks through a Gradle task wired as a `preBuild` dependency, so a
167
+ fresh clone gets the hooks on its first build with no manual step. Resolve the
168
+ git directory correctly when `.git` is a worktree pointer file (contents
169
+ `gitdir: <path>`) rather than a directory, or the hooks land in the wrong place.
503
170
 
504
- // Generate lock files: ./gradlew dependencies --write-locks
505
- ```
171
+ Full `resolveGitDir` helper, `installGitHooks` task, and `preBuild` wiring:
172
+ [references/patterns.md#fast-feedback-tasks](references/patterns.md#fast-feedback-tasks).
506
173
 
507
174
  ## Do's and Don'ts
508
175
 
@@ -550,3 +217,8 @@ dependencyLocking {
550
217
  - [ ] `android.nonTransitiveRClass=true` enabled
551
218
  - [ ] Bundles used for related dependency groups
552
219
  - [ ] No `kapt` usage in new modules
220
+ - [ ] `BuildConfig` values injected via typed key/contributor/resolver, not scattered `buildConfigField` strings
221
+ - [ ] Module paths and flavors referenced through typed `Module`/`Flavor`, not raw `project(":...")` strings
222
+ - [ ] Convention plugins composed as a ladder with shared config in one `configureKotlinAndroid()` extension
223
+ - [ ] Own convention plugins aliased in the version catalog (`libs.plugins.*`)
224
+ - [ ] Git-hooks install task wired as a `preBuild` dependency, worktree `.git` file handled