[PR #7456] [MERGED] feat(android): apply caller-selected R8 mapping evidence #7850

Closed
opened 2026-11-05 01:48:06 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/7456
Author: @gensokyo-dev
Created: 10/27/2026
Status: ✅ Merged
Merged: 10/27/2026
Merged by: @gensokyo-dev

Base: main ← Head: feat/android-r8-mapping


📝 Commits (7)

  • 5ecc6cc feat(android): apply caller-selected R8 mapping annotations
  • 73c525b perf(android): bound mapping claims and reuse verified indexes
  • 406d5be perf(android): retain raw calls behind symbol summaries
  • 764f6e6 docs(android): record real mapping workflow correctness and costs
  • 7158bf2 refactor(android): keep verification under maintained test paths
  • 160573c fix(android): bound mapping expansion and drain retained cleanup
  • ff574b6 perf(android): index mapping aliases and residual signatures

📊 Changes

49 files changed (+6431 additions, -120 deletions)

View changed files

📝 .agents/skills/reverse-engineer-anything/references/android-applications.md (+10 -0)
📝 bridge/android/ReaJadxBridge.java (+9 -4)
📝 docs/android-analysis.md (+90 -0)
📝 docs/testing.md (+3 -3)
➕ docs/verification/android-r8-mapping-2026-10-27.md (+366 -0)
📝 scripts/verify/android/metadata.mjs (+4 -0)
➕ src/android/AndroidMappingFile.ts (+216 -0)
📝 src/android/JadxAnalysis.ts (+75 -5)
📝 src/android/JadxProtocol.ts (+8 -2)
📝 src/android/JadxProvider.ts (+90 -9)
📝 src/android/JadxRelease.ts (+1 -1)
📝 src/android/JadxSession.ts (+17 -3)
➕ src/application/android/AndroidSymbolInspection.ts (+42 -0)
📝 src/cli/androidCommands.ts (+63 -20)
📝 src/contracts/android/androidToolContracts.ts (+28 -6)
📝 src/domain/analysisView/analysisView.ts (+25 -0)
➕ src/domain/analysisView/androidSymbolView.test.ts (+313 -0)
➕ src/domain/analysisView/androidSymbolView.ts (+137 -0)
📝 src/domain/android/androidAnalysis.ts (+27 -9)
➕ src/domain/android/androidMapping.test.ts (+88 -0)

...and 29 more files

📄 Description

Summary

Fixes #6329. Apply a caller-selected local R8/ProGuard mapping to Android class/method inspection, including field and inner-class annotations. Observed raw DEX identities remain primary; mapped claims, exact descriptor/type checks, ambiguity, malformed records, coverage and mapping SHA-256 are separate structured facts.

Integrates 555aaditya's #7137 at 505b95eb6097e0d1fd8a12710e0f020936e166d1, preserving co-author credit and the shared manifest/default-package work from #7379. Adds explicit retained summaries so selected method replies do not repeat complete raw class metadata.

Contract and boundary impact

  • One domain parser/report owner supports both CLI and MCP. Optional absolute mapping_path / --mapping-path is accepted on class/method inspection; selectors remain observed names. Mapping/build association is caller-selected, never verified by a reported map ID. Search/reference selectors keep their existing contracts.
  • detail: summary preserves normalized symbols or the selected body, retaining complete parent Evidence and returning its identity/digest. CLI uses the existing non-overwriting --evidence_output bundle flow. Omitted/complete detail remains compatible. Named SDK-converted output schemas include both forms.
  • The serialized provider re-reads and hashes mapping bytes every call; identical SHA/length reuses one parsed index with fixed options. Same-size/mtime changes invalidate it; missing/cancelled files cannot fall back to cache. Idle/close release it. Old/new indices can briefly coexist during replacement.
  • Parsing admits retained representation and parameter/metadata expansion before allocation. Ambiguity counts all candidates but samples eight; conflicting residual metadata remains ambiguous. Combined claim overflow across outer/inner classes becomes explicit unknown, preserving raw identities. The separate 1 MiB whole-summary limit refuses oversized selections with a complete-source recovery path.
  • Fixes mapping-read cancellation precedence: a later deadline during descriptor finalization cannot replace an earlier caller cause. Existing owned cleanup and session semantics remain shared.
  • Static inspection within the existing JADX boundary. Maintainer scope decision: not applicable; no target execution, injection, mutation, protection recovery or new provider. Internal bridge identity advances to 8; the supplied JADX 0.7.1 JAR is unchanged. Only owned analysis JVM/temp files and explicit Evidence outputs are used. Generated catalogs/packaged skill remain ignored outputs; no binaries, credentials or dependencies are committed.

Executed evidence

  • Type/lint/build, named SDK schema/profile checks, docs:check, format:check and docs:build pass. Expanded 12-file Android run: 219/220 pass, including all 52 session/idle/cleanup cases. One existing package-summary SDK case hits 30 seconds under combined load; its unchanged four-case file passes with one worker (SDK case 11.479 s), without relaxing assertions or timeout. This limitation is recorded, not reported as an all-green combined run.
  • Parser/reader/provider cases cover classes, fields, methods/overloads, malformed/partial mappings, inline ranges, raw aliases, preallocation bounds, stable candidate samples, same-size/mtime invalidation, selected paths, deleted inputs, cancellation and retained ownership. The unchanged optimization control reproduces the caller-first timeout bug while its deadline-first case passes; fixed code passes both.
  • Actual R8 8.0.40 source fixture: four classes/eight fields/fifteen DEX methods checked against source/javap and an independent raw DEX reader. Real stdio MCP summary/proof/negative qualification passes 43 calls, including malformed/partial, duplicate and conflicting mappings. Actual complete and summary CLI class/method commands preserve exact normalized facts and both hashes; portable bundles retain full parents.
  • Real Conscrypt Android 2.8.0 shipped class files transformed by R8: all 28 NativeCrypto fields/390 methods plus inner identities match the separate unminified D8 oracle; five selected bodies and complete parent exports pass. These are static DEX-only containers, not runnable APKs. A missing platform-adapter dependency warning is recorded.
  • Actual JDK21/JADX0.7.1 metadata and downstream CLI/MCP body/direct-invoke parity pass, including reserved raw names, default packages, frozen overload metadata, constants, native absence and classes.dex/classes2.dex identity. Summary parents/views remain readable after deleting the selected APK and mapping, without another provider launch.

Reproduction, pinned artifacts, all costs and failed attempts. Equivalent Conscrypt investigations include catalog discovery, six inspections and full proof export: text token estimates fall from ~178–180k to ~70k (about 61%); normalized fact digests match exactly. Four warm task samples per implementation have medians 0.905 → 0.783 s. Whole-task time/CPU/RSS samples and the small-case summary overhead are reported; no actual model billing, universal startup or memory improvement is claimed. Local expensive checks use two CPUs and a guarded process family.

Gaps: Linux x86-64/JDK21/JADX0.7.1/R8 mapping-format 2.1 only; no device/emulator, runtime linkage, source/line recovery, Windows/macOS, real mapping-format 2.2 producer or model-usage trial. Full inventories still cost more context than a known-method summary.

Review follow-up

All five Greptile findings are fixed at their producing boundaries: bounded incremental descriptor/type matching, shared request/idle retry of retained mapping descriptors (including mixed cleanup outcomes), deadline classification before cleanup composition, pre-resolved type aliases and direct residual-signature indexing. Related parser string ownership was measured through the real immutable Evidence ledger: four small facts retained ~40 MiB of source string backing; admission-owned UTF-16 strings eliminate that external retention in the same Node/V8 experiment while preserving code units. Post-review type/lint/build and 126 relevant parser/reader/cancellation/cleanup/session/MCP cases pass. The latest index follow-up additionally passes 60 parser, two report and seven MCP mapping cases. The admitted stress cases improve 20k-alias lookup from 5.17 s to 23 ms and 40k-signature parsing from 8.03 s to 322 ms, preserving answers.

Main archived the experiments tree during this PR. Fixtures/harness now use maintained tests paths and the report is under docs/verification; the branch is rebased onto main e99b6c2c3. Post-review real R8 qualification passes 43 calls; Conscrypt passes 21 calls with the same fact digest and ~61% lower estimated text tokens. All 90 observed CI failures at head 160573cb3 reproduce on its pristine actual main parent 0676ad254, including the two newline-bearing ZCode cases. Cancelled cases without completed reports remain unverified by CI. Final head ff574b620: Greptile, static checks, build, docs, APK-signature and native-package baselines pass. All eight failed/cancelled shard logs plus source tests were audited: 86 observed failures (69 shard + 17 source), no new identity versus the earlier run, all reproduced at actual pristine main parent 98422997c (90-case control: 151.037 s, CPU 179.041 s, peak family 2481.4 MiB). Twenty-six cases expose diagnostics (24 identical, two differing only in generated temporary paths); the other 60 CI causes are hidden by cancellation, and unreported cancelled cases remain unknown. All five review threads are resolved. User-authorized admin merge bypasses these baseline failures and the unchecked human declarations; no human-review attestation is made.

Author readiness

Human owner: @gensokyo-dev

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • Concrete enhancement, static contribution scope and authority are resolved.
  • Conventional title, linked issue, shared owners/contracts/docs and bounded execution.
  • Observations, mapped derivations, provenance, failed attempts and unknowns remain distinct.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/7456 **Author:** [@gensokyo-dev](https://github.com/gensokyo-dev) **Created:** 10/27/2026 **Status:** ✅ Merged **Merged:** 10/27/2026 **Merged by:** [@gensokyo-dev](https://github.com/gensokyo-dev) **Base:** `main` ← **Head:** `feat/android-r8-mapping` --- ### 📝 Commits (7) - [`5ecc6cc`](https://github.com/morluto/rea/commit/5ecc6ccc662678c00a45bd171f40798634774155) feat(android): apply caller-selected R8 mapping annotations - [`73c525b`](https://github.com/morluto/rea/commit/73c525b39cf2de0a7c3d261902cf42f81ddb73e5) perf(android): bound mapping claims and reuse verified indexes - [`406d5be`](https://github.com/morluto/rea/commit/406d5be22fc2798196083b7749c1470d5bc44566) perf(android): retain raw calls behind symbol summaries - [`764f6e6`](https://github.com/morluto/rea/commit/764f6e6973f633d7a335364714f2f04aa9b269a3) docs(android): record real mapping workflow correctness and costs - [`7158bf2`](https://github.com/morluto/rea/commit/7158bf2341c423995542719d60607eefc9dce35f) refactor(android): keep verification under maintained test paths - [`160573c`](https://github.com/morluto/rea/commit/160573cb36f478a088b8a5284fa571cd97dc9a86) fix(android): bound mapping expansion and drain retained cleanup - [`ff574b6`](https://github.com/morluto/rea/commit/ff574b620566139c83e0dadb012d92ef0b65c05f) perf(android): index mapping aliases and residual signatures ### 📊 Changes **49 files changed** (+6431 additions, -120 deletions) <details> <summary>View changed files</summary> 📝 `.agents/skills/reverse-engineer-anything/references/android-applications.md` (+10 -0) 📝 `bridge/android/ReaJadxBridge.java` (+9 -4) 📝 `docs/android-analysis.md` (+90 -0) 📝 `docs/testing.md` (+3 -3) ➕ `docs/verification/android-r8-mapping-2026-10-27.md` (+366 -0) 📝 `scripts/verify/android/metadata.mjs` (+4 -0) ➕ `src/android/AndroidMappingFile.ts` (+216 -0) 📝 `src/android/JadxAnalysis.ts` (+75 -5) 📝 `src/android/JadxProtocol.ts` (+8 -2) 📝 `src/android/JadxProvider.ts` (+90 -9) 📝 `src/android/JadxRelease.ts` (+1 -1) 📝 `src/android/JadxSession.ts` (+17 -3) ➕ `src/application/android/AndroidSymbolInspection.ts` (+42 -0) 📝 `src/cli/androidCommands.ts` (+63 -20) 📝 `src/contracts/android/androidToolContracts.ts` (+28 -6) 📝 `src/domain/analysisView/analysisView.ts` (+25 -0) ➕ `src/domain/analysisView/androidSymbolView.test.ts` (+313 -0) ➕ `src/domain/analysisView/androidSymbolView.ts` (+137 -0) 📝 `src/domain/android/androidAnalysis.ts` (+27 -9) ➕ `src/domain/android/androidMapping.test.ts` (+88 -0) _...and 29 more files_ </details> ### 📄 Description ## Summary Fixes #6329. Apply a caller-selected local R8/ProGuard mapping to Android class/method inspection, including field and inner-class annotations. Observed raw DEX identities remain primary; mapped claims, exact descriptor/type checks, ambiguity, malformed records, coverage and mapping SHA-256 are separate structured facts. Integrates 555aaditya's #7137 at `505b95eb6097e0d1fd8a12710e0f020936e166d1`, preserving co-author credit and the shared manifest/default-package work from #7379. Adds explicit retained summaries so selected method replies do not repeat complete raw class metadata. ## Contract and boundary impact - One domain parser/report owner supports both CLI and MCP. Optional absolute `mapping_path` / `--mapping-path` is accepted on class/method inspection; selectors remain observed names. Mapping/build association is caller-selected, never verified by a reported map ID. Search/reference selectors keep their existing contracts. - `detail: summary` preserves normalized symbols or the selected body, retaining complete parent Evidence and returning its identity/digest. CLI uses the existing non-overwriting `--evidence_output` bundle flow. Omitted/complete detail remains compatible. Named SDK-converted output schemas include both forms. - The serialized provider re-reads and hashes mapping bytes every call; identical SHA/length reuses one parsed index with fixed options. Same-size/mtime changes invalidate it; missing/cancelled files cannot fall back to cache. Idle/close release it. Old/new indices can briefly coexist during replacement. - Parsing admits retained representation and parameter/metadata expansion before allocation. Ambiguity counts all candidates but samples eight; conflicting residual metadata remains ambiguous. Combined claim overflow across outer/inner classes becomes explicit `unknown`, preserving raw identities. The separate 1 MiB whole-summary limit refuses oversized selections with a complete-source recovery path. - Fixes mapping-read cancellation precedence: a later deadline during descriptor finalization cannot replace an earlier caller cause. Existing owned cleanup and session semantics remain shared. - Static inspection within the existing JADX boundary. Maintainer scope decision: not applicable; no target execution, injection, mutation, protection recovery or new provider. Internal bridge identity advances to 8; the supplied JADX 0.7.1 JAR is unchanged. Only owned analysis JVM/temp files and explicit Evidence outputs are used. Generated catalogs/packaged skill remain ignored outputs; no binaries, credentials or dependencies are committed. ## Executed evidence - Type/lint/build, named SDK schema/profile checks, `docs:check`, `format:check` and `docs:build` pass. Expanded 12-file Android run: 219/220 pass, including all 52 session/idle/cleanup cases. One existing package-summary SDK case hits 30 seconds under combined load; its unchanged four-case file passes with one worker (SDK case 11.479 s), without relaxing assertions or timeout. This limitation is recorded, not reported as an all-green combined run. - Parser/reader/provider cases cover classes, fields, methods/overloads, malformed/partial mappings, inline ranges, raw aliases, preallocation bounds, stable candidate samples, same-size/mtime invalidation, selected paths, deleted inputs, cancellation and retained ownership. The unchanged optimization control reproduces the caller-first timeout bug while its deadline-first case passes; fixed code passes both. - Actual R8 8.0.40 source fixture: four classes/eight fields/fifteen DEX methods checked against source/javap and an independent raw DEX reader. Real stdio MCP summary/proof/negative qualification passes 43 calls, including malformed/partial, duplicate and conflicting mappings. Actual complete and summary CLI class/method commands preserve exact normalized facts and both hashes; portable bundles retain full parents. - Real Conscrypt Android 2.8.0 shipped class files transformed by R8: all 28 NativeCrypto fields/390 methods plus inner identities match the separate unminified D8 oracle; five selected bodies and complete parent exports pass. These are static DEX-only containers, not runnable APKs. A missing platform-adapter dependency warning is recorded. - Actual JDK21/JADX0.7.1 metadata and downstream CLI/MCP body/direct-invoke parity pass, including reserved raw names, default packages, frozen overload metadata, constants, native absence and classes.dex/classes2.dex identity. Summary parents/views remain readable after deleting the selected APK and mapping, without another provider launch. [Reproduction, pinned artifacts, all costs and failed attempts](docs/verification/android-r8-mapping-2026-10-27.md). Equivalent Conscrypt investigations include catalog discovery, six inspections and full proof export: text token estimates fall from ~178–180k to ~70k (about 61%); normalized fact digests match exactly. Four warm task samples per implementation have medians 0.905 → 0.783 s. Whole-task time/CPU/RSS samples and the small-case summary overhead are reported; no actual model billing, universal startup or memory improvement is claimed. Local expensive checks use two CPUs and a guarded process family. Gaps: Linux x86-64/JDK21/JADX0.7.1/R8 mapping-format 2.1 only; no device/emulator, runtime linkage, source/line recovery, Windows/macOS, real mapping-format 2.2 producer or model-usage trial. Full inventories still cost more context than a known-method summary. ## Review follow-up All five Greptile findings are fixed at their producing boundaries: bounded incremental descriptor/type matching, shared request/idle retry of retained mapping descriptors (including mixed cleanup outcomes), deadline classification before cleanup composition, pre-resolved type aliases and direct residual-signature indexing. Related parser string ownership was measured through the real immutable Evidence ledger: four small facts retained ~40 MiB of source string backing; admission-owned UTF-16 strings eliminate that external retention in the same Node/V8 experiment while preserving code units. Post-review type/lint/build and 126 relevant parser/reader/cancellation/cleanup/session/MCP cases pass. The latest index follow-up additionally passes 60 parser, two report and seven MCP mapping cases. The admitted stress cases improve 20k-alias lookup from 5.17 s to 23 ms and 40k-signature parsing from 8.03 s to 322 ms, preserving answers. Main archived the experiments tree during this PR. Fixtures/harness now use maintained tests paths and the report is under docs/verification; the branch is rebased onto main e99b6c2c3. Post-review real R8 qualification passes 43 calls; Conscrypt passes 21 calls with the same fact digest and ~61% lower estimated text tokens. All 90 observed CI failures at head 160573cb3 reproduce on its pristine actual main parent 0676ad254, including the two newline-bearing ZCode cases. Cancelled cases without completed reports remain unverified by CI. Final head ff574b620: Greptile, static checks, build, docs, APK-signature and native-package baselines pass. All eight failed/cancelled shard logs plus source tests were audited: 86 observed failures (69 shard + 17 source), no new identity versus the earlier run, all reproduced at actual pristine main parent 98422997c (90-case control: 151.037 s, CPU 179.041 s, peak family 2481.4 MiB). Twenty-six cases expose diagnostics (24 identical, two differing only in generated temporary paths); the other 60 CI causes are hidden by cancellation, and unreported cancelled cases remain unknown. All five review threads are resolved. User-authorized admin merge bypasses these baseline failures and the unchecked human declarations; no human-review attestation is made. ## Author readiness Human owner: @gensokyo-dev - [ ] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [ ] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [ ] I declare this PR ready for initial maintainer review. ## Before merge - [x] Concrete enhancement, static contribution scope and authority are resolved. - [x] Conventional title, linked issue, shared owners/contracts/docs and bounded execution. - [x] Observations, mapped derivations, provenance, failed attempts and unknowns remain distinct. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-05 01:48:06 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#7850
No description provided.