svharness 0.8.0

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 (134) hide show
  1. package/README.md +531 -0
  2. package/bin/cli.js +3 -0
  3. package/dist/adapters/_frontmatter.js +24 -0
  4. package/dist/adapters/claude-code.js +12 -0
  5. package/dist/adapters/codechat.js +12 -0
  6. package/dist/adapters/cursor.js +19 -0
  7. package/dist/adapters/generic.js +19 -0
  8. package/dist/adapters/index.js +26 -0
  9. package/dist/adapters/qoder.js +12 -0
  10. package/dist/commands/apply.js +272 -0
  11. package/dist/commands/init.js +420 -0
  12. package/dist/core/agent-injector.js +192 -0
  13. package/dist/core/next-steps.js +91 -0
  14. package/dist/core/render-meta.js +81 -0
  15. package/dist/core/repomix-pack.js +54 -0
  16. package/dist/core/scaffold.js +93 -0
  17. package/dist/core/state.js +80 -0
  18. package/dist/index.js +239 -0
  19. package/dist/types.js +5 -0
  20. package/dist/utils/baseline-copy.js +591 -0
  21. package/dist/utils/baseline-defaults.js +106 -0
  22. package/dist/utils/logger.js +56 -0
  23. package/dist/utils/validate-args.js +132 -0
  24. package/dist/utils/version.js +23 -0
  25. package/dist/wiki/abort.js +30 -0
  26. package/dist/wiki/config.js +79 -0
  27. package/dist/wiki/defaults.js +16 -0
  28. package/dist/wiki/envLoader.js +78 -0
  29. package/dist/wiki/index.js +29 -0
  30. package/dist/wiki/openaiCompat.js +219 -0
  31. package/dist/wiki/repowikiCanonicalSections.js +67 -0
  32. package/dist/wiki/repowikiCheckpoint.js +106 -0
  33. package/dist/wiki/repowikiConfig.js +9 -0
  34. package/dist/wiki/repowikiGit.js +73 -0
  35. package/dist/wiki/repowikiIndexer.js +824 -0
  36. package/dist/wiki/repowikiMarkdownPost.js +123 -0
  37. package/dist/wiki/repowikiMetadataContent.js +64 -0
  38. package/dist/wiki/repowikiMetadataJson.js +15 -0
  39. package/dist/wiki/repowikiScanner.js +156 -0
  40. package/dist/wiki/repowikiStructureNav.js +286 -0
  41. package/dist/wiki/repowikiStructureNormalize.js +218 -0
  42. package/dist/wiki/wikiStructureXml.js +316 -0
  43. package/dist/wiki/wikiTasksWriter.js +127 -0
  44. package/package.json +57 -0
  45. package/templates/_shared/apply-skills/harness-apply-skills-main.md +91 -0
  46. package/templates/_shared/build-rules/harness-build-rule-agent-agnostic.md +35 -0
  47. package/templates/_shared/build-rules/harness-build-rule-chinese-only.md +49 -0
  48. package/templates/_shared/build-rules/harness-build-rule-memory-write.md +31 -0
  49. package/templates/_shared/build-rules/harness-build-rule-orchestrator-flow.md +25 -0
  50. package/templates/_shared/build-rules/harness-build-rule-skills-tasks-output.md +35 -0
  51. package/templates/_shared/build-rules/harness-build-rule-specs-schema.md +32 -0
  52. package/templates/_shared/build-rules/harness-build-rule-user-interaction.md +63 -0
  53. package/templates/_shared/build-skills/harness-build-skill-knowledge-builder.md +120 -0
  54. package/templates/_shared/build-skills/harness-build-skill-orchestrator.md +87 -0
  55. package/templates/_shared/build-skills/harness-build-skill-spec-builder.md +85 -0
  56. package/templates/_shared/build-skills/harness-build-skill-wiki-writer.md +77 -0
  57. package/templates/_shared/meta/AGENTS.md.ejs +53 -0
  58. package/templates/_shared/meta/CHANGELOG.md.ejs +15 -0
  59. package/templates/_shared/meta/README.md.ejs +51 -0
  60. package/templates/_shared/meta/VERSION.ejs +1 -0
  61. package/templates/_shared/meta/harness.yaml.ejs +52 -0
  62. package/templates/_shared/skeleton/agent-env/memory/categories/.gitkeep +1 -0
  63. package/templates/_shared/skeleton/agent-env/memory/inbox/.gitkeep +1 -0
  64. package/templates/_shared/skeleton/agent-env/skills/.gitkeep +1 -0
  65. package/templates/_shared/skeleton/agent-env/tools/.gitkeep +1 -0
  66. package/templates/_shared/skeleton/assets/baseline/code/.gitkeep +1 -0
  67. package/templates/_shared/skeleton/assets/baseline/repomix/.gitkeep +1 -0
  68. package/templates/_shared/skeleton/assets/baseline/wiki/.gitkeep +1 -0
  69. package/templates/_shared/skeleton/assets/raw/.gitkeep +1 -0
  70. package/templates/_shared/skeleton/assets/requirements/.gitkeep +1 -0
  71. package/templates/_shared/skeleton/commands/install/.gitkeep +1 -0
  72. package/templates/_shared/skeleton/commands/update/.gitkeep +1 -0
  73. package/templates/_shared/skeleton/specs/behavior/schema.json +39 -0
  74. package/templates/_shared/skeleton/specs/interfaces/schema.json +38 -0
  75. package/templates/_shared/skeleton/specs/signals/schema.json +37 -0
  76. package/templates/_shared/skeleton/specs/ui/schema.json +44 -0
  77. package/templates/_shared/skeleton/tasks/templates/.gitkeep +0 -0
  78. package/templates/android-compose/skeleton/agent-env/rules/harness-compose-mandatory.mdc +49 -0
  79. package/templates/android-compose/skeleton/agent-env/rules/harness-coroutines-scope.mdc +52 -0
  80. package/templates/android-compose/skeleton/agent-env/rules/harness-hilt-injection.mdc +47 -0
  81. package/templates/android-compose/skeleton/agent-env/rules/harness-mvi-layering.mdc +58 -0
  82. package/templates/android-compose/skeleton/agent-env/skills/harness-android-architecture/SKILL.md +260 -0
  83. package/templates/android-compose/skeleton/agent-env/skills/harness-android-architecture/references/gradle-module-patterns.md +66 -0
  84. package/templates/android-compose/skeleton/agent-env/skills/harness-android-architecture/references/implementation-checklist.md +45 -0
  85. package/templates/android-compose/skeleton/agent-env/skills/harness-android-architecture/references/udf-data-flow.md +80 -0
  86. package/templates/android-compose/skeleton/agent-env/skills/harness-android-cli/SKILL.md +79 -0
  87. package/templates/android-compose/skeleton/agent-env/skills/harness-android-cli/references/interact.md +83 -0
  88. package/templates/android-compose/skeleton/agent-env/skills/harness-android-cli/references/journeys.md +97 -0
  89. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/SKILL.md +162 -0
  90. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/canonical-sources.md +116 -0
  91. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/diagnostics.md +182 -0
  92. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/report-template.md +135 -0
  93. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/scoring.md +277 -0
  94. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/search-playbook.md +303 -0
  95. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/scripts/compose-reports.init.gradle +58 -0
  96. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-state/SKILL.md +196 -0
  97. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-ui/SKILL.md +192 -0
  98. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-ui/references/composable-api-guide.md +123 -0
  99. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-ui/references/performance-recipes.md +97 -0
  100. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-ui/references/state-patterns.md +93 -0
  101. package/templates/android-compose/skeleton/agent-env/skills/harness-kotlin-coroutines/SKILL.md +167 -0
  102. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/SKILL.md +45 -0
  103. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/CONFIGURATION.md +44 -0
  104. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/KEEP-RULES-IMPACT-HIERARCHY.md +83 -0
  105. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/REDUNDANT-RULES.md +222 -0
  106. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/REFLECTION-GUIDE.md +139 -0
  107. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/android/topic/performance/app-optimization/enable-app-optimization.md +176 -0
  108. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/android/training/testing/other-components/ui-automator.md +312 -0
  109. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/SKILL.md +87 -0
  110. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/analysis-of-the-project-and-layout.md +42 -0
  111. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/android/develop/ui/compose/designsystems/migrate-xml-theme-to-compose.md +168 -0
  112. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/android/develop/ui/compose/setup-compose-dependencies-and-compiler.md +183 -0
  113. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/identify-optimal-xml-candidate.md +31 -0
  114. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/xml-layout-migration.md +86 -0
  115. package/templates/android-xml/skeleton/agent-env/rules/seed-aidl-thread.md +29 -0
  116. package/templates/android-xml/skeleton/agent-env/rules/seed-lifecycle-awareness.md +32 -0
  117. package/templates/android-xml/skeleton/agent-env/rules/seed-mvc-layering.md +32 -0
  118. package/templates/android-xml/skeleton/agent-env/rules/seed-view-binding.md +33 -0
  119. package/templates/android-xml/skeleton/agent-env/rules/seed-xml-styling.md +27 -0
  120. package/templates/cpp/skeleton/agent-env/rules/seed-cmake-explicit-sources.md +31 -0
  121. package/templates/cpp/skeleton/agent-env/rules/seed-header-guards.md +34 -0
  122. package/templates/cpp/skeleton/agent-env/rules/seed-include-layering.md +39 -0
  123. package/templates/cpp/skeleton/agent-env/rules/seed-no-cyclic-deps.md +29 -0
  124. package/templates/cpp/skeleton/agent-env/rules/seed-raii.md +30 -0
  125. package/templates/python/skeleton/agent-env/rules/seed-context-managers.md +60 -0
  126. package/templates/python/skeleton/agent-env/rules/seed-docstrings.md +48 -0
  127. package/templates/python/skeleton/agent-env/rules/seed-import-order.md +49 -0
  128. package/templates/python/skeleton/agent-env/rules/seed-pep8-naming.md +45 -0
  129. package/templates/python/skeleton/agent-env/rules/seed-type-annotations.md +43 -0
  130. package/templates/web-react/skeleton/agent-env/rules/seed-controlled-component.md +43 -0
  131. package/templates/web-react/skeleton/agent-env/rules/seed-effect-cleanup.md +43 -0
  132. package/templates/web-react/skeleton/agent-env/rules/seed-hook-rules.md +42 -0
  133. package/templates/web-react/skeleton/agent-env/rules/seed-key-stability.md +39 -0
  134. package/templates/web-react/skeleton/agent-env/rules/seed-no-props-drilling.md +43 -0
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: harness-r8-analyzer
3
+ description: 分析 Android 构建文件和 R8 keep 规则,识别冗余规则、过于宽泛的包级规则,以及覆盖了库消费者 keep 规则的规则。当开发者想要优化应用大小、移除冗余或过于宽泛的 keep 规则,或排查 Proguard 配置问题时使用。
4
+ license: Complete terms in LICENSE.txt
5
+ metadata:
6
+ author: Google LLC
7
+ keywords:
8
+ - R8
9
+ - proguard
10
+ - keep 规则
11
+ - 应用大小
12
+ - 优化
13
+ ---
14
+
15
+ ## 核心工作流
16
+
17
+ - [ ] 步骤 1:创建名为 R8_Configuration_Analysis.md 的文件(如已存在则复用),用于存储输出
18
+ - [ ] 步骤 2:通过查看代码库中的 build.gradle、build.gradle.kts、gradle.properties 来检查 R8 配置,以 [references/CONFIGURATION.md](references/CONFIGURATION.md) 作为参考。通知开发者并将分析结果添加到报告文件中
19
+ - [ ] 步骤 3:如果 AGP 版本低于 9,建议升级到 AGP 9.0,因为 AGP 9.0 包含[优化](references/android/topic/performance/app-optimization/enable-app-optimization.md)。
20
+ - [ ] 步骤 4:查看代码库中的 proguard 文件,并按以下特定顺序评估每条 keep 规则:
21
+ a. **库检查**:根据 [references/REDUNDANT-RULES.md](references/REDUNDANT-RULES.md) 检查规则。如果应用的 keep 规则针对的是库(Google、AndroidX、Kotlin、Kotlinx、Room、Gson、Retrofit),告知用户这些规则不需要并建议移除。
22
+ b. **影响分析**:对于剩余的 keep 规则,根据 [references/KEEP-RULES-IMPACT-HIERARCHY.md](references/KEEP-RULES-IMPACT-HIERARCHY.md) 中定义的影响层级进行评估。
23
+ - [ ] 步骤 5:根据 [references/KEEP-RULES-IMPACT-HIERARCHY.md](references/KEEP-RULES-IMPACT-HIERARCHY.md) 中定义的层级,识别剩余 keep 规则中的包含关系,并建议移除更宽泛的 keep 规则。
24
+ - [ ] 步骤 6:对于每条剩余的 keep 规则,通过检查受影响代码及相邻文件来详细分析规则存在的原因。查找相关包中的反射使用,并参考 [references/REFLECTION-GUIDE.md](references/REFLECTION-GUIDE.md) 为场景建议更窄更具体的 keep 规则。
25
+ - [ ] 步骤 7:对于每条 keep 规则,简明扼要地告知需要采取的操作——该规则是需要移除还是需要细化。
26
+ - [ ] 步骤 8:keep 规则分析完成后,根据 [references/KEEP-RULES-IMPACT-HIERARCHY.md](references/KEEP-RULES-IMPACT-HIERARCHY.md) 定义的对代码库的影响层级对分析结果排序。
27
+ - [ ] 步骤 9:建议用户使用 [UI Automator](references/android/training/testing/other-components/ui-automator.md) 运行测试,以评估建议的更改没有问题。
28
+
29
+ ## 强制规则
30
+
31
+ - 不要修改 keep 规则文件
32
+ - 不要说明每条 keep 规则的级别
33
+ - 如果某个部分没有 keep 规则需要报告,不要生成该部分的报告内容
34
+ - 不要提及生成的文件
35
+ - 不要提及执行期间发生的异常
36
+ - 不要提及 R8 的好处
37
+ - 不要提及本技能的任何文件
38
+
39
+ ---
40
+
41
+ ## 必须遵守的约束规则
42
+
43
+ > rules 引用路径:`../rules/<rule-name>.mdc`
44
+
45
+ 无(本技能为 R8 规则分析,不涉及代码生成)
@@ -0,0 +1,44 @@
1
+ To achieve maximum utilization of R8, the codebase must be configured correctly
2
+ depending on the build script language (Kotlin DSL vs. Groovy DSL).
3
+
4
+ ## 1. App Modules (`com.android.application`)
5
+
6
+ The app's `build.gradle` or `build.gradle.kts` file should enable minification
7
+ and resource shrinking within the `release` build type or the apps custom build
8
+ type for release and performance testing. It MUST use the optimized default file
9
+ (`proguard-android-optimize.txt`).
10
+
11
+ **Kotlin DSL (`build.gradle.kts`):**
12
+
13
+ buildTypes {
14
+ getByName("release") {
15
+ isMinifyEnabled = true
16
+ isShrinkResources = true
17
+ proguardFiles(
18
+ getDefaultProguardFile("proguard-android-optimize.txt"),
19
+ "proguard-rules.pro"
20
+ )
21
+ }
22
+ }
23
+
24
+ **Groovy DSL (`build.gradle`):**
25
+
26
+ buildTypes {
27
+ release {
28
+ minifyEnabled = true
29
+ shrinkResources = true
30
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
31
+ }
32
+ }
33
+
34
+ ## 2. `gradle.properties` Flags
35
+
36
+ **Full Mode:** R8 Full Mode enables the entire optimizations
37
+
38
+ - **AGP 8.0+** : Enabled by default. Ensure `android.enableR8.fullMode=false` is **NOT** present.
39
+ - **Pre-AGP 8.0** : Should be explicitly enabled with `android.enableR8.fullMode=true`.
40
+
41
+ **Optimized Resource Shrinking:** If the AGP version of the project is less than
42
+ 9.0 and more than 8.6, explicitly enable the new resource shrinker:
43
+
44
+ android.r8.optimizedResourceShrinking=true
@@ -0,0 +1,83 @@
1
+ Keep rules prevent optimization of R8, these rules are listed in the order of
2
+ the scope of what it retains in the codebase.
3
+
4
+ ## 1. Package-Wide Wildcards
5
+
6
+ The following types of keep rules prevents all the optimization of R8 in a
7
+ package, these must be avoided at any costs and must be refined to target a
8
+ specific class or classes.
9
+
10
+ -keep class com.example.package.** { *; } - Prevents optimization of all the classess including members in the package and subpackages
11
+ -keep class com.example.package.* { *; } - Prevents optimization of all the classes including members in the package
12
+ -keep class **.package.** { *; } - Prevents optimization of all the classess including members in all the package containing name - package.
13
+
14
+ Depending on the package level the number of classes gets affected changes, so
15
+ if the package level is higher, more classes are affected. Suggest to refine
16
+ the keep rule
17
+
18
+ ## 2. Inversion operator
19
+
20
+ Avoid using the inversion operator ! in keep rules because it will
21
+ unintentionally prevent optimization in every class in your application. So if
22
+ you have any keep rule with !operator, make sure you remove that with a narrow
23
+ and specific keep rule
24
+
25
+ -keep class !com.example.MyClass{*;}
26
+
27
+ This keeps the entire app
28
+ other than this class. Optimization are disabled for the entire class other
29
+ than this class.
30
+
31
+ ## 3. Keep Rules for both class and members
32
+
33
+ Keep rules with -keep option and wildcard(`*`) inside braces forces R8 to retain
34
+ specific classes and their members exactly as defined. These type of keep rules
35
+ prevent any optimization in the entire class and keeps the entire class
36
+
37
+ -keep class com.example.MyClass { *; }
38
+
39
+ ## 4. Keepclassmembers
40
+
41
+ Keep rules with -keepclassmembers and wildcard(`*`) inside braces option Forces
42
+ R8 to retain the members that are defined.
43
+
44
+ -keepclassmembers class com.example.MyClass { *; }
45
+
46
+ ## 5. Modifiers with Keep Specification
47
+
48
+ -Keeps the class and **all** members, but uses modifiers to allow specific
49
+ optimizations (like obfuscation). Retains significant code (members) but allows
50
+ some flexibility.
51
+
52
+ -keep,allowobfuscation class com.example.MyClass { *; }
53
+ -keep,allowshrinking class com.example.MyClass { *; }
54
+
55
+ ### 6. Modifiers with specific method but no modifier
56
+
57
+ Keeps the class and modifier but no optimizations are enabled
58
+
59
+ -keep class com.example.MyClass { void myMethod(); }
60
+
61
+ ## 7. Class-Name Only Preservation
62
+
63
+ Keeps only the class name. R8 will remove all methods and fields if they are not
64
+ used.
65
+
66
+ -keep class com.example.MyClass
67
+
68
+ ## 8. Modifiers without Member Specification
69
+
70
+ Keeps the class entry point using modifiers, but implies no specific member
71
+ retention logic in the rule itself
72
+
73
+ -keep,allowobfuscation class com.example.MyClass
74
+ -keep,allowshrinking class com.example.MyClass
75
+ -keep,allowaccessmodification class com.example.MyClass
76
+
77
+ ## 9. Conditional Keep Rules
78
+
79
+ Only triggers if specific conditions are met (e.g., if class members exist).
80
+ These are the most narrow and optimization-friendly rules.
81
+
82
+ -keepclassmembers class com.example.MyClass { <fields>; }
83
+ -keepclasseswithmembers class * { native <methods>; }
@@ -0,0 +1,222 @@
1
+ This document outlines common "bad" or redundant keep rules for standard Android
2
+ development and popular libraries. Modern toolchains and libraries include their
3
+ own consumer keep rules embedded in their AAR/JAR files, making many manual
4
+ configurations unnecessary or even harmful to code optimization.
5
+
6
+ *** ** * ** ***
7
+
8
+ ## Case: Global Keep Rules
9
+
10
+ **Common Mistakes:**
11
+ `proguard
12
+ -dontshrink
13
+ -dontobfuscate
14
+ -dontoptimize`
15
+
16
+ **The Fix:** These keep rules completely disable the core optimizations of R8
17
+ for the entire codebase. They must be removed from the codebase.
18
+
19
+ *** ** * ** ***
20
+
21
+ ## Case: Android Components
22
+
23
+ Keep rules required for Android components like Activity, Fragment, ViewModel,
24
+ Views, Services or Broadcast receivers are redundant. AAPT2 and R8 contain the
25
+ logic to automatically keep components declared in the `AndroidManifest.xml` or
26
+ referenced in XML layout files.
27
+
28
+ **Common Mistakes:**
29
+ `proguard
30
+ -keep public class * extends android.app.Activity
31
+ -keep public class * extends android.app.Service
32
+ -keep public class * extends android.view.View
33
+ -keepclassmembers class * extends android.app.Fragment { public void *(android.view.View); }`
34
+
35
+ **The Fix:** Delete these manual rules. AAPT2 handles this automatically.
36
+
37
+ *** ** * ** ***
38
+
39
+ ## Case: Official Android and Kotlin Libraries
40
+
41
+ Keep rules targeting official library packages like AndroidX, Kotlin, and
42
+ Kotlinx are redundant as they are bundled within the libraries themselves.
43
+ Manual rules are often broader than what is strictly needed.
44
+
45
+ **Common Mistakes:**
46
+ `proguard
47
+ -keep class androidx.** { *; }
48
+ -keep class kotlinx.** { *; }
49
+ -keep class kotlin.** { *; }`
50
+
51
+ **The Fix:** Delete these manual rules. Rely on the consumer keep rules packaged
52
+ within these dependencies.
53
+
54
+ *** ** * ** ***
55
+
56
+ ## Case: Gson
57
+
58
+ ### Overly Broad Data Model Rules
59
+
60
+ The most common mistake is keeping entire packages of data models (POJOs/DTOs),
61
+ keeping data models at all for deserialization is unnecessary.
62
+
63
+ -keep class com.example.app.models.** { *; }
64
+ -keep class com.example.app.package.models.* { *; }
65
+
66
+ ### Redundant Interface \& Adapter Rules
67
+
68
+ These rules added for TypeAdapter are unnecessary and are already covered by
69
+ the library, and prevent R8 from effectively shrinking and optimizing custom
70
+ adapters. R8 can determine if the adapter implementation are used. Keeping them
71
+ globally prevents the removal of unused adapter implementations.
72
+
73
+ -keep class * extends com.google.gson.TypeAdapter
74
+ -keep class * implements com.google.gson.TypeAdapterFactory
75
+ -keep class * implements com.google.gson.JsonSerializer
76
+ -keep class * implements com.google.gson.JsonDeserializer
77
+
78
+ ### Unnecessary TypeToken Rules
79
+
80
+ There is no need to handle generic type erasure, Gson's own rules handle the
81
+ necessary `TypeToken` preservation.
82
+
83
+ -keep class com.google.gson.reflect.TypeToken { *; }
84
+ -keep class * extends com.google.gson.reflect.TypeToken
85
+ -keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
86
+
87
+ ### Internal and Example Packages
88
+
89
+ Keeping internal library logic prevents the compiler from stripping away dead
90
+ code within the library.
91
+
92
+ -keep class com.google.gson.internal.** { *; }
93
+ -keep class com.google.gson.internal.reflect.** { *; }
94
+ -keep class com.google.gson.internal.UnsafeAllocator { *; }
95
+ -keep class com.google.gson.stream.** { *; }
96
+
97
+ - **Keeps Unused Code:** Prevents R8 from removing models that are never actually used in the code.
98
+ - **Prevents Method Stripping:** Keeps all getters, setters, `toString()`, `equals()`, and `hashCode()` methods, even if they are never called.
99
+ - **Blocks Obfuscation:** Prevents the class names from being obfuscated, which is unnecessary for Gson if you use `@SerializedName`.
100
+
101
+ **The Fix:**
102
+
103
+ 1. Use `@SerializedName` on every field in your data classes uses so that the field is retained after R8 optimization
104
+ 2. Modern Gson (**v2.11.0+** ) bundles its own rules ([View Gson's embedded
105
+ ProGuard
106
+ rules](https://github.com/google/gson/blob/main/gson/src/main/resources/META-INF/proguard/gson.pro)). The bundled keep rules retains the `@SerializedName` annotated fields. If you are on an older version, move towards Gson version 2.11 because it has the necessary keep rules and delete the keep rules that target the classes used for gson serialization and deserialization
107
+
108
+ *** ** * ** ***
109
+
110
+ ## Case: Retrofit
111
+
112
+ Retrofit has shipped with its own consumer keep rules from 2.9.0 and higher, so
113
+ any keep rules for the library or classes depending on Retrofit is detrimental
114
+ to the optimization process.
115
+
116
+ ### Blanket Library Preservation
117
+
118
+ This is the most harmful Retrofit rule as it disables any shrinking for the
119
+ entire library.
120
+
121
+ -keep class retrofit2.** { *; }
122
+ -keep class retrofit2.api.** { *; }
123
+ -keep class com.package.example.retrofit.api.** { *; }
124
+
125
+ ### Manual Annotation Keeps
126
+
127
+ Retrofit's consumer rules automatically keep the interfaces annotated with
128
+ `@GET`, `@POST`, `@DELETE`, `@PUT`, `@HEAD`, `@OPTIONS`, `@PATCH`, making these
129
+ manual rules obsolete.
130
+
131
+ `-keepclasseswithmembers class * { @retrofit2.http.* <methods>; }`
132
+
133
+ ### Redundant Network Response and Adapter Rules
134
+
135
+ Network responses and third-party adapter wrappers (like RxJava) are often
136
+ overly preserved by developers out of caution.
137
+
138
+ -keep,allowobfuscation,allowshrinking class retrofit2.Response
139
+ -keep class retrofit2.adapter.rxjava2.Result { *; }
140
+
141
+ Fix: Verify you are using Retrofit 2.9.0 and higher. Retrofit from 2.9.0 bundles
142
+ rules that detect its own HTTP annotations (@GET, @POST) ([View Retrofit's
143
+ embedded ProGuard
144
+ rules](https://github.com/square/retrofit/blob/master/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro)).
145
+ It will automatically keep the method signatures it needs to work.
146
+
147
+ *** ** * ** ***
148
+
149
+ ## Case: Kotlin Coroutines
150
+
151
+ Kotlin Coroutines comes heavily optimized out of the box with embedded R8 rules
152
+ (`kotlinx-coroutines-core` includes its own rules).
153
+
154
+ ### Blanket Coroutine Library Rules
155
+
156
+ Keeping everything under `kotlinx.coroutines` is extremely detrimental to app
157
+ size, as coroutines contain a vast amount of internal APIs that aren't used.
158
+
159
+ `-keepclassmembers class kotlinx.coroutines.** { *; }`
160
+
161
+ ### Redundant Internal Continuations
162
+
163
+ These low-level coroutine elements are preserved safely by the library's own
164
+ consumer rules. Manually adding these prevents R8 from performing internal
165
+ optimizations (such as removing unused continuations or inlining).
166
+
167
+ -keepclassmembers class kotlin.coroutines.SafeContinuation { *; }
168
+ -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
169
+
170
+ ### Dispatcher and Exception Handler Rules
171
+
172
+ Sometimes developers notice crashes related to Missing Classes on old Android
173
+ versions and add these rules, but if you are using an up-to-date version of
174
+ Coroutines, these are handled automatically or are not an issue.
175
+
176
+ -keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
177
+ -keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
178
+ -keepnames class kotlinx.coroutines.android.AndroidExceptionPreHandler {}
179
+ -keepnames class kotlinx.coroutines.android.AndroidDispatcherFactory {}
180
+
181
+ **Fix** Remove any broad `kotlinx` keep rules. Coroutines (**v1.7.0+** ) bundle
182
+ the necessary keep rules ([View Coroutines' embedded ProGuard
183
+ rules](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/resources/META-INF/proguard/coroutines.pro)).
184
+
185
+ *** ** * ** ***
186
+
187
+ ## Case: Parcelable
188
+
189
+ **Common Mistakes:** Legacy projects often contain `-keep class * implements
190
+ android.os.Parcelable { public static final android.os.Parcelable$Creator *; }`.
191
+
192
+ **The Fix:**
193
+
194
+ 1. Add the `kotlin-parcelize` plugin.
195
+ 2. **Use `@Parcelize`:** Replace manual `writeToParcel` logic with the `@Parcelize` annotation.
196
+ 3. **Delete All Parcelable Rules:** The plugin automatically generates the required rules.
197
+ 4. The default proguard file `proguard-android-optimize.txt` contains the keep rules for keeping all the parcelable classes
198
+ 5. **Ideal Rule:** **None.** Delete all manual Parcelable keeps.
199
+
200
+ *** ** * ** ***
201
+
202
+ ## Case: Room Database
203
+
204
+ **Common Mistakes:** Keeping DAO interfaces or the generated `_Impl` classes
205
+ manually.
206
+
207
+ -keep class * extends androidx.room.RoomDatabase
208
+ -keep class *_*Impl { *; }
209
+
210
+ **The Fix:** Room generates its own ProGuard rules for the code it creates.
211
+ Manual rules are redundant and prevent R8 from optimizing the database access
212
+ layers.
213
+
214
+ - **Ideal Rule:** **None.** Delete all manual Room or DAO keeps.
215
+
216
+ *** ** * ** ***
217
+
218
+ ## Summary
219
+
220
+ If you have updated your libraries to the versions mentioned, your
221
+ `proguard-rules.pro` must not contain any keep rules for the libraries
222
+ mentioned here.
@@ -0,0 +1,139 @@
1
+ A categorized summary of the keep rule examples, including the code patterns to
2
+ look for (imports/usage) and the corresponding suggested rules.
3
+
4
+ ### 1. Reflection: Classes Loaded by Name
5
+
6
+ **Scenario:** A library or app loads a class dynamically using a string name
7
+
8
+ - **Look for:**
9
+ `Class.forName("...")`,
10
+ `getDeclaredConstructor().newInstance()`, or interfaces used for dynamic loading.
11
+
12
+ - **Example Code:**
13
+ `kotlin
14
+ val taskClass = Class.forName(className)
15
+ val task = taskClass.getDeclaredConstructor().newInstance() as StartupTask`
16
+
17
+ - **Suggested Keep Rule:**
18
+ \`\`\`proguard
19
+
20
+ -keep class \* implements com.example.library.StartupTask {
21
+ (); } \`\`\`
22
+
23
+ ### 2. Reflection: Classes Passed using `::class.java`
24
+
25
+ **Scenario:** An app passes a class reference directly to a library function.
26
+
27
+ - **Look for:** `::class.java` (Kotlin) or `.class` (Java) passed as an argument.
28
+ - **Example Code:**
29
+ `kotlin
30
+ fun <T> register(clazz: Class<T>) { }
31
+ // Usage:
32
+ register(MyService::class.java)`
33
+
34
+ - **Suggested Keep Rule:**
35
+ \`\`\`proguard
36
+
37
+ # Keep the class itself (R8 usually handles this, but explicit rules ensure stability)
38
+
39
+ -keep class com.example.app.MyService {
40
+ (); } \`\`\`
41
+
42
+ ### 3. Annotation-Based Reflection (Methods/Classes)
43
+
44
+ **Scenario:** Using custom annotations to mark methods or classes for reflective
45
+ execution.
46
+
47
+ **Look for:** Custom `@interface` definitions and `getDeclaredMethods()`
48
+ filtered by annotation.
49
+ **Example Code:**
50
+ `kotlin
51
+ annotation class ReflectiveExecutor
52
+ // Logic: find methods annotated with @ReflectiveExecutor and invoke them`
53
+
54
+ - **Suggested Keep Rule:** \`\`\`proguard # Keep the annotation itself -keep @interface com.example.library.ReflectiveExecutor
55
+
56
+ # Keep members of any class annotated with this specific annotation
57
+ -keepclassmembers class \* {
58
+ @com.example.library.ReflectiveExecutor \*;
59
+ }
60
+ \`\`\`
61
+
62
+ ### 4. Optional Dependencies (Soft Dependencies)
63
+
64
+ **Scenario:** A core library checks if an optional module is present in the
65
+ classpath.
66
+
67
+ - **Look for:** `try-catch` blocks around `Class.forName()` used to toggle features.
68
+ - **Example Code:** \`\`\`kotlin private const val VIDEO_TRACKER_CLASS = "com.example.analytics.video.VideoEventTracker"
69
+
70
+ try {
71
+ Class.forName(VIDEO_TRACKER_CLASS).getDeclaredConstructor().newInstance()
72
+ } catch (e: ClassNotFoundException) { /\* skip feature \*/ }
73
+ \`\`\`
74
+
75
+ - **Suggested Keep Rule:** `proguard
76
+ # Preserve the optional class so the check doesn't fail due to shrinking
77
+ -keep class com.example.analytics.video.VideoEventTracker {
78
+ <init>();
79
+ }`
80
+
81
+ ### 5. Accessing Private Members
82
+
83
+ **Scenario:** Using reflection to access internal fields or methods not exposed
84
+ with public APIs.
85
+
86
+ - **Look for:** `getDeclaredField("...")` or `getDeclaredMethod("...")` followed by `isAccessible = true`.
87
+ - **Example Code:**
88
+ `kotlin
89
+ val secretField = instance::class.java.getDeclaredField("secretMessage")
90
+ secretField.isAccessible = true`
91
+
92
+ - **Suggested Keep Rule:**
93
+ \`\`\`proguard
94
+
95
+ # Specifically keep the private field/method by name and type
96
+
97
+ -keepclassmembers class com.example.LibraryClass {
98
+ private java.lang.String secretMessage;
99
+ }
100
+ \`\`\`
101
+
102
+ ### 6. Parcelable (Manual Implementation)
103
+
104
+ **Scenario:** Implementing `Parcelable` without using the `@Parcelize`
105
+ annotation.
106
+
107
+ - **Look for:** `implements Parcelable` and a static `CREATOR` field.
108
+ - **Example Code:**
109
+ `kotlin
110
+ class MyData : Parcelable {
111
+ // Manual implementation with CREATOR field
112
+ }`
113
+
114
+ - **Suggested Keep Rule:**
115
+ *(Note: If using `import kotlinx.parcelize.Parcelize`, R8/ProGuard rules are
116
+ generated automatically. If manual, use the following:)*
117
+ `proguard
118
+ -keepclassmembers class * implements android.os.Parcelable {
119
+ static android.os.Parcelable$Creator CREATOR;
120
+ }`
121
+
122
+ ### 7. Enums and Obfuscation
123
+
124
+ **Scenario:** App uses `Enum.valueOf("STRING_NAME")` indirectly (e.g.,using JSON
125
+ deserialization) and the enum names get obfuscated.
126
+
127
+ - **Look for:** Unnecessary generic Enum keep rules in ProGuard files.
128
+ - **Example Code:**
129
+ \`\`\`proguard
130
+
131
+ # Unnecessary rule
132
+
133
+ -keepclassmembers enum \* { \*; }
134
+ \`\`\`
135
+ - **Suggested Keep Rule:**
136
+ \*(Note: The default `proguard-android-optimize.txt` already contains the optimal
137
+ rules for Enums (keeping `values()` and `valueOf(String)`). Any additional
138
+ manual rules for Enums are redundant.) # No manual rule needed. Use default
139
+ proguard-android-optimize.txt.