diff --git a/docs/superpowers/specs/2026-06-21-clone-app-re-subagent-design.md b/docs/superpowers/specs/2026-06-21-clone-app-re-subagent-design.md new file mode 100644 index 0000000..858fc80 --- /dev/null +++ b/docs/superpowers/specs/2026-06-21-clone-app-re-subagent-design.md @@ -0,0 +1,148 @@ +# Clone App — RE-via-Subagent + Payload Extraction Design Spec + +**Date:** 2026-06-21 +**Scope:** `plugins/clone-app/` only. `plugins/android-reverse-engineering/` stays byte-identical (upstream-untouched rule). +**Supersedes:** Phase 2 of the original `2026-06-21-clone-app-skill-design.md`. All other phases unchanged unless noted. + +## Problem + +Two gaps in the current clone-app skill: + +1. **The RE skill never runs.** clone-app Phase 2 calls the `android-reverse-engineering` plugin's bash *scripts* directly (via `resolve-re-scripts.sh`). The RE *skill's* prose workflow — fingerprint triage, two-tier API documentation, BuildConfig secret hunting, call-flow tracing, cross-platform `.ps1` handling — is bypassed. clone-app re-implements a thin, lossy version of it inline. The user never observes the RE skill triggering because it genuinely does not. + +2. **Payloads are not extracted.** Phase 2 assembles only an endpoint *list* (host/method/path/auth). Request bodies, response shapes, and headers — the RE skill's "Tier 2" detail — are never produced and never persisted. Nothing reaches memory or the feasibility report. + +## Decisions (locked during brainstorming) + +- **Q1 → C (hybrid w/ fallback):** Invoke the `android-reverse-engineering` **skill** for the heavy RE workflow when it is installed; **fall back to direct scripts** when it is not. Full workflow when available, graceful degradation otherwise. +- **Q2 → A (subagent isolation):** RE runs inside a dispatched subagent, in its own context. The orchestrator never ingests raw decompiled sources — only a concise summary plus on-demand file reads. +- **Q3 → B (targeted payloads):** Tier-2 payloads (request body, response shape, headers, params) for **auth, payment/checkout, and the 1–2 core feature endpoints**. Tier-1 flat inventory for everything else. Matches the RE skill's own "Tier-1 always, Tier-2 for ~10 high-value" guidance. +- **Memory → 1 (durable files):** Full detail written to files in `$WORK/`, off-context, re-readable. Only a ≤40-line summary enters orchestrator context. + +## Architecture — Phase 2 rewrite (probe → dispatch → consume) + +``` +Phase 2a PROBE resolve-re-scripts.sh → are RE scripts on disk? (exit code) + orchestrator's skill list → is the RE skill registered? +Phase 2b DISPATCH dispatch a subagent (Agent tool, general-purpose) that runs RE + in isolation: + ├─ RE skill registered → subagent invokes the + │ android-reverse-engineering skill + └─ skill absent, scripts present → subagent runs direct scripts + Subagent writes digest files to $WORK/, returns the summary text. +Phase 2c CONSUME orchestrator reads $WORK/re-summary.txt only; pulls + re-digest.md / payloads.json on demand in later phases. +``` + +**Invariant:** both branches write the **same digest files**, so Phases 3–7 are branch-agnostic — one consume path regardless of how RE ran. + +### Branch decision table + +| RE skill registered | RE scripts on disk | Action | +|---|---|---| +| ✓ | — | subagent runs **RE skill** (preferred) | +| ✗ | ✓ | subagent runs **direct scripts** (fallback) | +| ✓ | ✓ | subagent runs **RE skill** (skill wins) | +| ✗ | ✗ | **stop** — show `resolve-re-scripts.sh` error | + +Two independent facts drive it: skill availability (orchestrator reads its own available-skills list) and script availability (`resolve-re-scripts.sh` exit code). `resolve-re-scripts.sh` is unchanged — it remains both the probe and the fallback locator. + +**Why the subagent wraps the script-fallback branch too** (not only the skill branch): keeps decompile noise out of the orchestrator either way, and keeps Phases 3–7 on a single branch-agnostic consume path. + +## Digest contract (subagent output) + +Single source of truth: a new reference file `references/re-digest-contract.md`. The Phase-2 subagent prompt points at it. The subagent MUST write three files to `$WORK/` and return the summary. + +### `$WORK/re-digest.md` — human-readable main artifact + +``` +# RE Digest — +## Framework & Stack framework, HTTP lib, DI, serialization, obfuscation level +## Hosts first-party vs third-party (table) +## Endpoint Inventory Tier-1: host | method | path | auth | source file +## Key Flow Payloads Tier-2: auth, payment/checkout, 1-2 core + — request body / response shape / headers / params +## BuildConfig Secrets base URLs, API keys, feature flags, flavors +## Feature Signals screen count, SDKs, permissions, components +## RE Method "re-skill" | "direct-scripts" | "limited: " +``` + +### `$WORK/payloads.json` — machine-readable (memory requirement) + +```json +{ + "package": "com.example.app", + "re_method": "re-skill", + "endpoints": [ + { + "host": "api.example.com", + "method": "POST", + "path": "/v1/auth/login", + "auth": "none", + "source": "com/example/api/AuthApi.java", + "request_body": { "email": "string", "password": "string" }, + "response": { "token": "string", "user": {} }, + "headers": { "Content-Type": "application/json" } + } + ], + "buildconfig": { "BASE_URL": "https://api.example.com/v1" } +} +``` + +`request_body` / `response` are `null` for Tier-1-only endpoints. Populated only for auth/payment/core (Tier-2). + +### `$WORK/re-summary.txt` — ≤40 lines, the only RE text entering orchestrator context + +Contains: framework, host count, endpoint count, key-flow names, secrets-found count, RE method, blockers/warnings. The subagent's return value = contents of `re-summary.txt` + the two file paths. **The subagent must not dump raw decompiled sources into its return.** + +### Contract rules + +- **Tier-2 only for auth / payment / core** (decision Q3=B). All other endpoints → Tier-1 row, `null` payloads. +- **Framework guard:** if fingerprint reports Flutter / React Native / Cordova / Xamarin, the subagent writes a partial digest, sets `RE Method: limited: `, and payloads may be empty. Downstream widens the uncertainty band. + +## Subagent dispatch + +clone-app dispatches via the **Agent tool** (`general-purpose` type — can both invoke skills and run bash). The single prompt carries: `$PKG`, `$APK`, `$WORK`, the chosen branch, and the digest contract verbatim (or a pointer to `re-digest-contract.md`). Subagent steps: + +1. Run RE — the skill or the direct scripts, per branch. +2. Extract Tier-1 inventory + Tier-2 payloads for auth/payment/core. +3. Write `re-digest.md`, `payloads.json`, `re-summary.txt`. +4. Return `re-summary.txt` contents + the two file paths. No raw sources. + +## Downstream changes (Phases 3–7) + +- **Phase 2c:** orchestrator reads `re-summary.txt` only; reads `re-digest.md` / `payloads.json` on demand if a later phase needs detail. +- **Phase 5 (effort/cost):** read `payloads.json`; endpoint count + payload complexity feed the AI-Sprint estimate (backend surface = real work) instead of a loose guess. +- **Phase 6 (report):** new optional report section **"Backend API Surface"** — Tier-1 table summary + key-flow payloads from the digest. +- **Error table additions:** + - RE subagent fails → retry once, then fall back to direct-scripts branch (if scripts present); else stop. + - Both branches unavailable → stop with the resolver error. + +## Files changed (all under `plugins/clone-app/`) + +| File | Change | +|---|---| +| `skills/clone-app/SKILL.md` | Rewrite Phase 2 (probe/dispatch/consume); tweak Phases 5 & 6; extend error table | +| `skills/clone-app/references/re-digest-contract.md` | **New** — digest schema, single source of truth for the subagent | +| `skills/clone-app/scripts/resolve-re-scripts.sh` | Unchanged (remains probe + fallback locator) | +| `tests/fixtures/re-digest.sample.md` | **New** — schema fixture | +| `tests/fixtures/payloads.sample.json` | **New** — schema fixture | +| `tests/test-re-digest-contract.sh` | **New** — structural assertions | +| `tests/smoke-structure.sh` | Add new reference file to present-files check | + +`plugins/android-reverse-engineering/` is **untouched** — the subagent *invokes* it, never edits it. `git status --porcelain plugins/android-reverse-engineering/` must stay empty. + +## Tests (offline, fixture-based — matches existing pattern) + +- `test-re-digest-contract.sh` asserts: + - `re-digest-contract.md` lists every required `re-digest.md` section and every required `payloads.json` key. + - `SKILL.md` Phase 2 references the contract, names both branches, and dispatches a subagent. + - Sample fixtures parse (JSON valid; digest has all sections). +- `smoke-structure.sh` gains the new reference file in its existence check. +- **No live RE run in tests** — decompilation is too heavy and non-deterministic. Contract + wiring asserted structurally, same philosophy as the offline Python scraper tests. + +## Non-goals + +- Exhaustive Tier-2 payloads for every endpoint (Q3=C rejected — token-expensive, RE skill itself warns against it). +- Modifying any upstream RE file. +- Live decompilation inside the test suite.