[PR #5380] feat(android): add optional DroidASC class discovery backend #6912

Open
opened 2026-11-01 21:44:00 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/5380
Author: @namename333
Created: 10/20/2026
Status: 🔄 Open

Base: main ← Head: feat/asc-android-backend


📝 Commits (4)

  • 8b85ef7 feat(android): add opt-in DroidASC class discovery backend
  • 2ba2a61 fix(android): preserve backend-owned cleanup failures
  • 51f03b4 test(android): benchmark and document optional ASC discovery
  • 13f132c docs(android): present ASC backend for normal review

📊 Changes

32 files changed (+5781 additions, -58 deletions)

View changed files

📝 README.md (+1 -1)
➕ bridge/android/rea_asc.py (+317 -0)
➕ bridge/android/test_rea_asc.py (+251 -0)
📝 docs/android-analysis.md (+77 -3)
📝 docs/architecture.mermaid (+1 -1)
➕ experiments/droidasc/README.md (+154 -0)
➕ experiments/droidasc/benchmark-oracle.mjs (+253 -0)
➕ experiments/droidasc/benchmark-profile.mjs (+198 -0)
➕ experiments/droidasc/benchmark.mjs (+497 -0)
➕ experiments/droidasc/measurements/apidemos.json (+752 -0)
➕ experiments/droidasc/measurements/raw-evidence-manifest.json (+101 -0)
➕ experiments/droidasc/measurements/signal.json (+861 -0)
📝 package.json (+3 -1)
📝 scripts/verify-packed-bridge.mjs (+8 -5)
➕ scripts/verify/android/asc.mjs (+125 -0)
➕ src/android/AscConfiguration.ts (+133 -0)
➕ src/android/AscDoctor.ts (+100 -0)
➕ src/android/AscProtocol.ts (+377 -0)
➕ src/android/AscProvider.ts (+502 -0)
📝 src/application/DoctorProviderIds.ts (+1 -0)

...and 12 more files

📄 Description

Summary

Add opt-in DroidASC class discovery through REA's existing Android CLI/MCP workflow, without changing the default JADX backend.

Problem and expected behavior

For a large APK, finding a known class should not require initializing a full decompiler when raw DEX definitions answer the question. Select --backend asc / backend: "asc" explicitly; keep JADX for decompilation and the other existing Android operations.

Change and scope

  • Optional caller-supplied Python/DroidASC environment, discovery via rea doctor --provider asc; no engine installation or dependency changes.
  • Shared search_android_classes contract, CLI/MCP routing and artifact-bound Evidence. Unsupported ASC operations fail explicitly, without fallback or starting JADX.
  • Structured bridge, checked APK/DEX identity/coverage, byte budgets, owned subprocess supervision, cancellation/timeouts and retryable cleanup ownership.
  • No persistent index, target execution, device access, decompiler replacement, or extra public tool family.
  • Reproducible public-APK harness with independent ZIP/DEX class-definition oracle and complete per-round metric observations.

Contract and boundary impact

  • Semantic owner and earliest changed stage: Android request selects a backend; provider owns engine interpretation; the shared application workflow owns Evidence.
  • Contribution scope fit and linked maintainer decision: read-only static APK analysis alongside JADX. The integration follows REA's contribution boundaries.
  • CLI and MCP/tool-catalog contract: additive optional backend: "jadx" | "asc"; omission and shared session readiness remain JADX; ASC has its own Doctor check. Example: rea search-android-classes Example.apk MainActivity --backend asc --format json.
  • Provider/format/platform: first slice supports class discovery on standalone APK root DEX 035/037/038/039/040. DEX 041, split merging and raw DEX are unavailable. Linux/macOS enabled; real verification is macOS arm64 only. Windows returns unavailable.
  • Evidence: APK SHA-256, DEX entry/digest, raw descriptor, Python/imported-module fingerprints. Raw definitions include inner/synthetic classes and are explicitly marked inventory_kind: "dex_definitions", not equated with JADX aliases. Unknown engine version/revision remain unknown.
  • Authority and cleanup: interpreter/dependency code executes locally, APK code does not. One owned worker per ASC request, no network/persistent index. Budgets are not an OS sandbox/RSS cap. Identity checks are not an immutable snapshot.
  • Generated/package impact: existing schema/catalog generation reused; package includes REA's Python bridge only, not ASC, samples or binaries.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code. (REA's bridge and caller-supplied interpreter, not target code.)
  • Change process memory, registers, files, or configuration. (Owned process/runtime workspace, not target APK or persistent configuration.)
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

Final-runtime measurements on Signal 8.30.3 (114,097,843 bytes; three alternating fresh runs and two repeats per run):

Median ASC JADX
First class-discovery query 5432.4 ms 10714.6 ms
Repeat query 2997.7 ms 170.1 ms
Three queries plus close 10471.0 ms 12621.0 ms
Sampled process-family RSS 277.8 MiB 1919.0 MiB

This is about 2.0× faster first discovery / 6.9× lower sampled RSS, but 17.6× slower repeat queries, not general superiority. A smaller ApiDemos control is included; all 36 queries and independent oracle checks succeeded. Both batches bind the measured entrypoints to source 2ba2a61a; later documentation commits do not change that runtime. macOS arm64, Node 24.18.0, Python 3.14.6, JDK 21.0.11, pinned ASC 60033d1c, JADX MCP 0.7.1 with 2048 MiB heap. Full hashes and every round are committed.

The comparable task is substring discovery followed by exact selection of the same oracle-confirmed top-level class, not equal whole inventories. Fresh process does not mean cold disk cache. RSS is sampled process-family RSS, not kernel peak; CPU is a sampled lower-bound estimate. No token, isolated engine-startup, method, string or cross-reference performance claim is made. See commands, every round, sample hashes and limits.

Selected fields from actual Signal Evidence (not the complete envelope):

{"provider":{"id":"asc","name":"DroidASC","version":null},"normalized_result":{"query":"org.thoughtcrime.securesms.ApplicationContext","total_classes":40773,"coverage":"complete","inventory_kind":"dex_definitions"}}

Added regressions cover malformed protocol/DEX/ZIP data, literal query transport (including option-like/NUL/surrogate input), no-match/capacity outcomes, target drift, deadlines, queued/active/final-cleanup cancellation, exact failed cleanup owners/retry, Doctor classification and packed bridge presence/syntax. Existing JADX assertions were not loosened or removed.

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • Focused Android/Doctor/router/JADX projection/schema/packed-bridge suite — 123 passed, 9 files on final runtime.
  • npm run test:python — 132 passed: 51 bridge tests (including 16 ASC regressions) and 81 analysis-efficiency tests.
  • npm run verify:test-discovery — all 1717 test files discovered exactly once.
  • npm run verify:asc — PASS actual CLI/MCP selection, Evidence, no-match, unsupported operation and unchanged fixture, with Java/JADX unavailable.
  • npm run verify:android — PASS all five existing operations through actual CLI/MCP, metadata/overloads/direct-invoke identity, cancellation/owned cleanup and failure recovery.
  • Pre-push npm run check:fast — PASS typecheck/lint.
  • npm_config_registry=https://registry.npmjs.org npm run verify:package — PASS full package installation/update, bridge archive, MCP/CLI/schema/Evidence, setup/uninstall and cleanup checks. The first attempt using the ambient corporate npm mirror timed out after its Skills fetch returned HTTP 502; rerunning with the public registry succeeded without changing source or global npm configuration.
  • npm run check:ci — PASS typecheck, lint, format, knip, metadata, duplication/TODO checks and architecture/module guards (existing repository lint warnings remain reported, not suppressed).
  • npm run docs:check — PASS, including 5 README consistency tests.
  • node experiments/droidasc/benchmark.mjs --self-test — PASS; final built runtime/harness SHA-256 values still match both measured batches after all packaging/check commands.

Not an all-green local suite: the combined JADX/MCP/router regression run had 57/61 pass and four timing failures (1 s launch/cleanup polls and a 1500 ms deadline lacking an expected status reply). The three launch/deadline failures also reproduce when the factory is restored to the original direct-JADX composition. The MCP disconnect test passes individually with both original and new composition; real CLI cancellation/cleanup also passes. The integration's three earlier cleanup-error-identity regressions were fixed at the router owner; their original assertions now pass. No timeouts, assertions or tests were weakened. Linux CI and real Linux/Windows engine coverage remain separate evidence.

Upstream CI is awaiting maintainer workflow approval (action_required, zero jobs executed), not passed or a diagnosed code failure.

Compatibility, safety, and release

  • No intended breaking change; default JADX calls remain unchanged. Explicit ASC names are raw DEX identities, not necessarily interchangeable with JADX display aliases.
  • Real ASC and JADX CLI/MCP verification: macOS arm64 only. No real Linux/Windows qualification, no APK runtime behavior or APK authenticity claim.
  • Optional external ASC is Apache-2.0; no upstream implementation/APK/JAR is redistributed. Existing package dependency lockfile is unchanged.
  • This is a first-slice proposal, not full Android-provider equivalence. Repeated ASC requests reparse the APK and can be slower than a retained JADX JVM. Additional operations/caching require their own correctness and lifecycle evidence.

Author readiness

Human owner: @namename333

  • 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

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 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/5380 **Author:** [@namename333](https://github.com/namename333) **Created:** 10/20/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/asc-android-backend` --- ### 📝 Commits (4) - [`8b85ef7`](https://github.com/morluto/rea/commit/8b85ef7193881aa5d802598da3054c5b9f660a86) feat(android): add opt-in DroidASC class discovery backend - [`2ba2a61`](https://github.com/morluto/rea/commit/2ba2a61a2bab7131e8d04507322d24642b7f480e) fix(android): preserve backend-owned cleanup failures - [`51f03b4`](https://github.com/morluto/rea/commit/51f03b4c602f69456bb36f41ec8ae5ff5d21dfc2) test(android): benchmark and document optional ASC discovery - [`13f132c`](https://github.com/morluto/rea/commit/13f132c6100665d10d2742c2a8f7f6a47623a497) docs(android): present ASC backend for normal review ### 📊 Changes **32 files changed** (+5781 additions, -58 deletions) <details> <summary>View changed files</summary> 📝 `README.md` (+1 -1) ➕ `bridge/android/rea_asc.py` (+317 -0) ➕ `bridge/android/test_rea_asc.py` (+251 -0) 📝 `docs/android-analysis.md` (+77 -3) 📝 `docs/architecture.mermaid` (+1 -1) ➕ `experiments/droidasc/README.md` (+154 -0) ➕ `experiments/droidasc/benchmark-oracle.mjs` (+253 -0) ➕ `experiments/droidasc/benchmark-profile.mjs` (+198 -0) ➕ `experiments/droidasc/benchmark.mjs` (+497 -0) ➕ `experiments/droidasc/measurements/apidemos.json` (+752 -0) ➕ `experiments/droidasc/measurements/raw-evidence-manifest.json` (+101 -0) ➕ `experiments/droidasc/measurements/signal.json` (+861 -0) 📝 `package.json` (+3 -1) 📝 `scripts/verify-packed-bridge.mjs` (+8 -5) ➕ `scripts/verify/android/asc.mjs` (+125 -0) ➕ `src/android/AscConfiguration.ts` (+133 -0) ➕ `src/android/AscDoctor.ts` (+100 -0) ➕ `src/android/AscProtocol.ts` (+377 -0) ➕ `src/android/AscProvider.ts` (+502 -0) 📝 `src/application/DoctorProviderIds.ts` (+1 -0) _...and 12 more files_ </details> ### 📄 Description ## Summary Add **opt-in DroidASC class discovery** through REA's existing Android CLI/MCP workflow, without changing the default JADX backend. ## Problem and expected behavior For a large APK, finding a known class should not require initializing a full decompiler when raw DEX definitions answer the question. Select `--backend asc` / `backend: "asc"` explicitly; keep JADX for decompilation and the other existing Android operations. ## Change and scope - Optional caller-supplied Python/DroidASC environment, discovery via `rea doctor --provider asc`; no engine installation or dependency changes. - Shared `search_android_classes` contract, CLI/MCP routing and artifact-bound Evidence. Unsupported ASC operations fail explicitly, without fallback or starting JADX. - Structured bridge, checked APK/DEX identity/coverage, byte budgets, owned subprocess supervision, cancellation/timeouts and retryable cleanup ownership. - No persistent index, target execution, device access, decompiler replacement, or extra public tool family. - Reproducible public-APK harness with independent ZIP/DEX class-definition oracle and complete per-round metric observations. ## Contract and boundary impact - Semantic owner and earliest changed stage: Android request selects a backend; provider owns engine interpretation; the shared application workflow owns Evidence. - Contribution scope fit and linked maintainer decision: read-only static APK analysis alongside JADX. The integration follows REA's contribution boundaries. - CLI and MCP/tool-catalog contract: additive optional `backend: "jadx" | "asc"`; omission and shared session readiness remain JADX; ASC has its own Doctor check. Example: `rea search-android-classes Example.apk MainActivity --backend asc --format json`. - Provider/format/platform: first slice supports class discovery on standalone APK root DEX 035/037/038/039/040. DEX 041, split merging and raw DEX are unavailable. Linux/macOS enabled; real verification is macOS arm64 only. Windows returns unavailable. - Evidence: APK SHA-256, DEX entry/digest, raw descriptor, Python/imported-module fingerprints. Raw definitions include inner/synthetic classes and are explicitly marked `inventory_kind: "dex_definitions"`, not equated with JADX aliases. Unknown engine version/revision remain unknown. - Authority and cleanup: interpreter/dependency code executes locally, APK code does not. One owned worker per ASC request, no network/persistent index. Budgets are not an OS sandbox/RSS cap. Identity checks are not an immutable snapshot. - Generated/package impact: existing schema/catalog generation reused; package includes REA's Python bridge only, not ASC, samples or binaries. Expected effects: - [x] Read existing files or captured data. - [x] Launch or attach to a process. - [x] Inject instrumentation or run scripts/code. (REA's bridge and caller-supplied interpreter, not target code.) - [x] Change process memory, registers, files, or configuration. (Owned process/runtime workspace, not target APK or persistent configuration.) - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage Final-runtime measurements on Signal 8.30.3 (114,097,843 bytes; three alternating fresh runs and two repeats per run): | Median | ASC | JADX | | --- | ---: | ---: | | First class-discovery query | 5432.4 ms | 10714.6 ms | | Repeat query | 2997.7 ms | 170.1 ms | | Three queries plus close | 10471.0 ms | 12621.0 ms | | Sampled process-family RSS | 277.8 MiB | 1919.0 MiB | This is about **2.0× faster first discovery / 6.9× lower sampled RSS**, but **17.6× slower repeat queries**, not general superiority. A smaller ApiDemos control is included; all 36 queries and independent oracle checks succeeded. Both batches bind the measured entrypoints to source `2ba2a61a`; later documentation commits do not change that runtime. macOS arm64, Node 24.18.0, Python 3.14.6, JDK 21.0.11, pinned ASC `60033d1c`, JADX MCP 0.7.1 with 2048 MiB heap. Full hashes and every round are committed. The comparable task is substring discovery followed by exact selection of the same oracle-confirmed top-level class, not equal whole inventories. Fresh process does not mean cold disk cache. RSS is sampled process-family RSS, not kernel peak; CPU is a sampled lower-bound estimate. No token, isolated engine-startup, method, string or cross-reference performance claim is made. See [commands, every round, sample hashes and limits](https://github.com/namename333/rea/blob/feat/asc-android-backend/experiments/droidasc/README.md). Selected fields from actual Signal Evidence (not the complete envelope): ```json {"provider":{"id":"asc","name":"DroidASC","version":null},"normalized_result":{"query":"org.thoughtcrime.securesms.ApplicationContext","total_classes":40773,"coverage":"complete","inventory_kind":"dex_definitions"}} ``` Added regressions cover malformed protocol/DEX/ZIP data, literal query transport (including option-like/NUL/surrogate input), no-match/capacity outcomes, target drift, deadlines, queued/active/final-cleanup cancellation, exact failed cleanup owners/retry, Doctor classification and packed bridge presence/syntax. Existing JADX assertions were not loosened or removed. - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - Focused Android/Doctor/router/JADX projection/schema/packed-bridge suite — **123 passed, 9 files** on final runtime. - `npm run test:python` — **132 passed**: 51 bridge tests (including 16 ASC regressions) and 81 analysis-efficiency tests. - `npm run verify:test-discovery` — all **1717** test files discovered exactly once. - `npm run verify:asc` — **PASS** actual CLI/MCP selection, Evidence, no-match, unsupported operation and unchanged fixture, with Java/JADX unavailable. - `npm run verify:android` — **PASS** all five existing operations through actual CLI/MCP, metadata/overloads/direct-invoke identity, cancellation/owned cleanup and failure recovery. - Pre-push `npm run check:fast` — **PASS** typecheck/lint. - `npm_config_registry=https://registry.npmjs.org npm run verify:package` — **PASS** full package installation/update, bridge archive, MCP/CLI/schema/Evidence, setup/uninstall and cleanup checks. The first attempt using the ambient corporate npm mirror timed out after its Skills fetch returned HTTP 502; rerunning with the public registry succeeded without changing source or global npm configuration. - `npm run check:ci` — **PASS** typecheck, lint, format, knip, metadata, duplication/TODO checks and architecture/module guards (existing repository lint warnings remain reported, not suppressed). - `npm run docs:check` — **PASS**, including 5 README consistency tests. - `node experiments/droidasc/benchmark.mjs --self-test` — **PASS**; final built runtime/harness SHA-256 values still match both measured batches after all packaging/check commands. **Not an all-green local suite:** the combined JADX/MCP/router regression run had 57/61 pass and four timing failures (1 s launch/cleanup polls and a 1500 ms deadline lacking an expected status reply). The three launch/deadline failures also reproduce when the factory is restored to the original direct-JADX composition. The MCP disconnect test passes individually with both original and new composition; real CLI cancellation/cleanup also passes. The integration's three earlier cleanup-error-identity regressions were fixed at the router owner; their original assertions now pass. No timeouts, assertions or tests were weakened. Linux CI and real Linux/Windows engine coverage remain separate evidence. Upstream [CI](https://github.com/morluto/rea/actions/runs/39388720766) is **awaiting maintainer workflow approval** (`action_required`, zero jobs executed), not passed or a diagnosed code failure. ## Compatibility, safety, and release - No intended breaking change; default JADX calls remain unchanged. Explicit ASC names are raw DEX identities, not necessarily interchangeable with JADX display aliases. - Real ASC and JADX CLI/MCP verification: macOS arm64 only. No real Linux/Windows qualification, no APK runtime behavior or APK authenticity claim. - Optional external ASC is Apache-2.0; no upstream implementation/APK/JAR is redistributed. Existing package dependency lockfile is unchanged. - This is a first-slice proposal, not full Android-provider equivalence. Repeated ASC requests reparse the APK and can be slower than a retained JADX JVM. Additional operations/caching require their own correctness and lifecycle evidence. ## Author readiness Human owner: @namename333 - [x] 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. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
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#6912
No description provided.