RIPDPI's own Compose conventions: ViewModel pattern, Route/Screen split, DataStore->StateFlow, RipDpiThemeTokens. Use for how this app does Compose, not generic Compose API questions (see compose).
日本語の概要は準備中です。原文の説明を表示しています。
Author the narrowest R8/ProGuard keep rule for a JNI binding, serializable nav route, or proto-lite class. Use when adding one of those or triaging missing_rules.txt after a release build.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Release builds minify the app via R8. Four failure modes are common:
System.loadLibrary can't resolve the JNI signature → runtime UnsatisfiedLinkError.kotlinx.serialization @Serializable class loses its generated $$serializer or companion, and Navigation Compose type-safe route encode/decode fails → runtime SerializationException on nav transition.call_method (not the reverse -- no external fun involved) loses its name because nothing in Kotlin calls it, and the native runtime's callback silently no-ops or crashes at the JNI boundary.The project keeps keep-rules narrow on purpose. Read the hard rule first:
If a future minified build fails, add the smallest rule that names the exact compatibility boundary. Do not paste missing_rules.txt suggestions verbatim and do not add blanket -dontwarn or -keep rules. —
app/proguard-rules.pro:8-10
| File | Scope | Contains |
|---|---|---|
core/engine/consumer-rules.pro | JNI boundary for the native engine | -keepclasseswithmembernames + native <methods>; blocks for each native-binding class (read the file for the current list), plus interface keep-blocks for Kotlin callbacks native code invokes by name (see below) |
core/data/consumer-rules.pro | Proto-lite compatibility surface | com.poyka.ripdpi.proto.** keep |
app/proguard-rules.pro | App-level shims (intentionally tiny) | Only Guava j2objc -dontwarn today |
Rule: Engine/Data compatibility boundaries belong in module-level consumer rules, not in app/proguard-rules.pro. Reviewers reject app-level rules that could have lived in a consumer rule file.
When you add a class with external fun members called from Rust:
core/engine/consumer-rules.pro following the exact pattern of the existing entries.-keepclasseswithmembernames + native <methods>; only. Do not add -keep class (full class preservation) — only the native method names need to survive shrinking, the higher-level Kotlin wrapper does not.Anchor example:
-keepclasseswithmembernames class com.poyka.ripdpi.core.RipDpiProxyNativeBindings {
native <methods>;
}
A fourth boundary shape, distinct from the JNI-native-method binding above: a Kotlin interface method that native code invokes by name via JNI call_method -- no external fun is involved, and nothing in Kotlin itself calls the method, so R8 has no reachability evidence and will strip or rename it.
-keep interface com.poyka.ripdpi.core.YourCallback {
void yourMethod();
}
-keepclassmembers class * implements com.poyka.ripdpi.core.YourCallback {
void yourMethod();
}
implements wildcard form covers every implementor, including a SAM-lambda registration, not just a named class.Anchor example (core/engine/consumer-rules.pro): RuntimeReadinessListener -- the native runtime invokes onRuntimeReady() by name via JNI call_method; it is never called from Kotlin, so R8 would otherwise strip or rename it. SshProbeSocketController's protectSocket(int) follows the same pattern.
@Serializable navigation routeNavigation Compose type-safe routes use kotlinx.serialization at runtime. Read the active Navigation Compose version from gradle/libs.versions.toml, and locate ConfigGraph / SettingsGraph by symbol in app/src/main/kotlin/com/poyka/ripdpi/ui/navigation/RipDpiNavHost.kt. R8 can strip a generated $$serializer companion.
Current state: the project has no app-level -keep rule for serializable routes today. It works because the routes are data objects (stateless) and the Compose/Kotlin serialization Gradle plugin emits a consumer rule. Verify this remains true when adding a @Serializable data class route with fields.
If a future release build crashes with kotlinx.serialization.SerializationException: Serializer for class 'X' is not found:
-keepclassmembers class com.poyka.ripdpi.ui.navigation.<RouteName> {
kotlinx.serialization.KSerializer serializer(...);
<fields>;
}
-keep class com.poyka.ripdpi.ui.navigation.** { *; } — that defeats minification for the entire navigation graph.The existing rule -keep class com.poyka.ripdpi.proto.** { *; } covers everything under that package. If a new schema lands under a different package (e.g. a core/diagnostics-data proto), add a module-scoped consumer rule in that module's consumer-rules.pro, not a line in app/proguard-rules.pro.
missing_rules.txt after a failed release buildFor assembleGithubFullRelease, R8 emits app/build/outputs/mapping/githubFullRelease/missing_rules.txt with suggestions. These are mechanical — they don't know what's a genuine compatibility boundary vs. a false positive.
Review protocol:
consumer-rules.pro.Class.forName strings) rather than suppress.missing_rules.txt as-is, and never cat missing_rules.txt >> app/proguard-rules.pro.After any change to a .pro file:
assemble*Release task must complete without R8 warnings escalating to errors../gradlew staticAnalysis — lint must not regress.missing_rules.txt appears with new suggestions after your change, treat the appearance itself as a review signal: something in your diff created a new boundary that R8 can't analyze. Surface this in PR review, don't paper over it.-consumerProguardFiles from each library. Don't re-declare their rules.AndroidManifest.xml.-dontwarn com.google.j2objc.annotations.** in app/proguard-rules.pro.Run android skills r8 for Google's generic R8 skill; use it alongside this RIPDPI-specific skill for background on new R8 features, obfuscation dictionaries, or full-mode vs compat-mode semantics. This skill is the project-specific authority for what to keep and where; Google's skill explains why R8 behaves the way it does.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
RIPDPI's own Compose conventions: ViewModel pattern, Route/Screen split, DataStore->StateFlow, RipDpiThemeTokens. Use for how this app does Compose, not generic Compose API questions (see compose).
日本語の概要は準備中です。原文の説明を表示しています。
ADB-based RIPDPI device/emulator debugging: build/install/launch, logcat filtering, fixture port-forwarding, instrumented tests, crash/ANR triage. Use when debugging on a real device or emulator.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium launch-contract reference: start routes and permission/service/data presets. Use when a test launches to the wrong screen or a new automation route is added. General flakiness: appium-test-debug.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium test authoring: page objects, resource-id locators, assertions, wait tiers. Use when writing a new Appium test or page object, or adding coverage for a new screen.
日本語の概要は準備中です。原文の説明を表示しています。
RIPDPI Appium failure triage: flaky tests, locator/session/wait issues, screenshot and element-tree debugging. Use when an Appium test fails or is flaky.
日本語の概要は準備中です。原文の説明を表示しています。
Add or modify a GitHub Actions job. Use when editing a file under .github/workflows/. Not for running a workflow locally (local-ci-act) or release signing (release-signing).
日本語の概要は準備中です。原文の説明を表示しています。