From ed75876cc14d3ce62f2958a80fd7735f71723963 Mon Sep 17 00:00:00 2001 From: "fatih.bulut" Date: Sun, 21 Jun 2026 13:56:36 +0300 Subject: [PATCH 1/6] docs(clone-app): spec RE-via-subagent + payload extraction Phase 2 rewrite: invoke android-reverse-engineering skill in an isolated subagent (fallback to direct scripts), extract Tier-2 payloads for auth/payment/core flows, persist a digest contract to $WORK/. Co-Authored-By: Claude Opus 4.8 --- ...2026-06-21-clone-app-re-subagent-design.md | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-21-clone-app-re-subagent-design.md 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. From 73b3b3d8c53d8db0e821b0b95c44482c1eff656d Mon Sep 17 00:00:00 2001 From: "fatih.bulut" Date: Sun, 21 Jun 2026 14:06:00 +0300 Subject: [PATCH 2/6] docs(clone-app): implementation plan for RE-via-subagent + payloads Co-Authored-By: Claude Opus 4.8 --- .../plans/2026-06-21-clone-app-re-subagent.md | 543 ++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-21-clone-app-re-subagent.md diff --git a/docs/superpowers/plans/2026-06-21-clone-app-re-subagent.md b/docs/superpowers/plans/2026-06-21-clone-app-re-subagent.md new file mode 100644 index 0000000..eb3f36c --- /dev/null +++ b/docs/superpowers/plans/2026-06-21-clone-app-re-subagent.md @@ -0,0 +1,543 @@ +# Clone App — RE-via-Subagent + Payload Extraction Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Rewrite clone-app Phase 2 to run the `android-reverse-engineering` skill inside an isolated subagent (falling back to direct scripts), extract Tier-2 payloads for auth/payment/core flows, and persist a durable digest contract to `$WORK/`. + +**Architecture:** Phase 2 becomes probe → dispatch → consume. A dispatched subagent runs RE in its own context and writes three files (`re-digest.md`, `payloads.json`, `re-summary.txt`) to `$WORK/`; the orchestrator ingests only the ≤40-line summary. A new reference doc `re-digest-contract.md` is the single source of truth for the schema. Both the skill branch and the script-fallback branch write the same files, so Phases 3–7 stay branch-agnostic. The work product is Markdown (SKILL.md prose + reference doc) plus structural bash tests — there is no compiled runtime, so "tests" assert document structure and wiring, matching the repo's existing offline test philosophy. + +**Tech Stack:** Bash (`#!/usr/bin/env bash`, invoked via `bash `), Python 3 stdlib (`json` for validity checks), Markdown skill/reference docs. + +## Global Constraints + +- **Upstream untouched:** No edits under `plugins/android-reverse-engineering/`. After every commit, `git status --porcelain plugins/android-reverse-engineering/` MUST print nothing. +- **All new/changed files live under `plugins/clone-app/`** (plus the design docs already committed). +- **Bash scripts use `#!/usr/bin/env bash`** and are run with `bash ` (shell is zsh; `sh` breaks them). Tests use `set -uo pipefail` (NOT `-e`) and aggregate failures into a `fail` var so every assertion runs. +- **Python is stdlib-only** — `json`, no pip, no venv. +- **Effort is measured in "AI Sprints"** (one focused Claude session), never calendar time — preserve this wording in any SKILL.md edits. +- **Conventional Commits scoped to the plugin:** `feat(clone-app): …`, `test(clone-app): …`, `docs(clone-app): …`. +- **Two pause points in SKILL.md stay:** Phase 4 (choose stack) and Phase 7 (proceed to plan?). Do not add new mandatory pauses in Phase 2. +- **Working dir convention:** `WORK="./work/$PKG"` relative to the user's cwd; decompile output lands at `$WORK/output/` via `decompile.sh -o`. + +--- + +### Task 1: Digest contract reference doc + schema fixtures + contract test + +Establishes the single source of truth for what the subagent must produce, plus offline fixtures and a structural test that locks the schema. This task is independently reviewable: a reviewer can accept the contract/fixtures/test without yet seeing the SKILL.md rewrite. + +**Files:** +- Create: `plugins/clone-app/skills/clone-app/references/re-digest-contract.md` +- Create: `plugins/clone-app/tests/fixtures/re-digest.sample.md` +- Create: `plugins/clone-app/tests/fixtures/payloads.sample.json` +- Test: `plugins/clone-app/tests/test-re-digest-contract.sh` + +**Interfaces:** +- Produces (consumed by Task 2's SKILL.md prose and by the subagent at runtime): + - `re-digest.md` required section headings (exact strings): `## Framework & Stack`, `## Hosts`, `## Endpoint Inventory`, `## Key Flow Payloads`, `## BuildConfig Secrets`, `## Feature Signals`, `## RE Method`. + - `payloads.json` required top-level keys: `package`, `re_method`, `endpoints`, `buildconfig`. Each `endpoints[]` object has keys: `host`, `method`, `path`, `auth`, `source`, `request_body`, `response`, `headers`. + - `re-summary.txt`: plain text, ≤40 lines, fields — framework, host count, endpoint count, key-flow names, secrets-found count, RE method, blockers. + - `RE Method` allowed values: `re-skill`, `direct-scripts`, `limited: `. + +- [ ] **Step 1: Write the failing test** + +Create `plugins/clone-app/tests/test-re-digest-contract.sh`: + +```bash +#!/usr/bin/env bash +set -uo pipefail +HERE="$(cd "$(dirname "$0")" && pwd)" +P="$HERE/.." # plugins/clone-app +CONTRACT="$P/skills/clone-app/references/re-digest-contract.md" +DIGEST_FIX="$HERE/fixtures/re-digest.sample.md" +PAYLOAD_FIX="$HERE/fixtures/payloads.sample.json" +fail=0 +has() { grep -qF "$2" "$1" && echo "PASS: $3" || { echo "FAIL: $3 — '$2' not in ${1##*/}"; fail=1; }; } + +# Contract doc exists and documents every required re-digest.md section heading +for sec in "## Framework & Stack" "## Hosts" "## Endpoint Inventory" \ + "## Key Flow Payloads" "## BuildConfig Secrets" "## Feature Signals" "## RE Method"; do + has "$CONTRACT" "$sec" "contract documents section $sec" +done + +# Contract doc documents every required payloads.json key +for key in '"package"' '"re_method"' '"endpoints"' '"buildconfig"' \ + '"request_body"' '"response"' '"headers"'; do + has "$CONTRACT" "$key" "contract documents json key $key" +done + +# Contract names the three output files and the three RE Method values +for tok in "re-digest.md" "payloads.json" "re-summary.txt" \ + "re-skill" "direct-scripts" "limited:"; do + has "$CONTRACT" "$tok" "contract names token $tok" +done + +# Digest fixture has every required section heading +for sec in "## Framework & Stack" "## Hosts" "## Endpoint Inventory" \ + "## Key Flow Payloads" "## BuildConfig Secrets" "## Feature Signals" "## RE Method"; do + has "$DIGEST_FIX" "$sec" "digest fixture has section $sec" +done + +# Payload fixture is valid JSON and has the required shape +python3 -c " +import json,sys +d=json.load(open('$PAYLOAD_FIX')) +for k in ('package','re_method','endpoints','buildconfig'): + assert k in d, 'missing top key '+k +assert isinstance(d['endpoints'],list) and d['endpoints'], 'endpoints must be non-empty list' +for e in d['endpoints']: + for k in ('host','method','path','auth','source','request_body','response','headers'): + assert k in e, 'endpoint missing key '+k +print('PASS: payload fixture shape valid') +" || { echo "FAIL: payload fixture shape"; fail=1; } + +exit $fail +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `bash plugins/clone-app/tests/test-re-digest-contract.sh` +Expected: FAIL — contract doc and fixtures do not exist yet (grep errors / `FAIL:` lines), exit non-zero. + +- [ ] **Step 3: Create the contract reference doc** + +Create `plugins/clone-app/skills/clone-app/references/re-digest-contract.md`: + +````markdown +# RE Digest Contract + +The Phase 2 subagent runs the reverse-engineering workflow in isolation and +MUST produce these three files under `$WORK/`, then return only the summary. +This file is the single source of truth for their schema. The subagent prompt +points here; do not duplicate the schema into SKILL.md prose. + +## File 1 — `$WORK/re-digest.md` (human-readable, main artifact) + +Required section headings, in this order: + +``` +# 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 flows + — 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: +``` + +## File 2 — `$WORK/payloads.json` (machine-readable, durable memory) + +Required top-level keys: `package`, `re_method`, `endpoints`, `buildconfig`. +Each item in `endpoints` has: `host`, `method`, `path`, `auth`, `source`, +`request_body`, `response`, `headers`. + +```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` and `response` are `null` for Tier-1-only endpoints. +- Populate them ONLY for the key flows: **auth, payment/checkout, and the + 1–2 core feature endpoints** (decision Q3=B). Everything else is a Tier-1 + row with `null` payloads. Going Tier-2 on every endpoint is a non-goal — + it is token-expensive and the RE skill itself warns against it. + +## File 3 — `$WORK/re-summary.txt` (≤40 lines, the only RE text returned) + +Plain text. The subagent's return value = the contents of this file plus the +paths to the two files above. Fields: + +- framework +- host count (first-party / third-party) +- endpoint count +- key-flow names found (auth / payment / core) +- secrets-found count (BuildConfig) +- RE method: `re-skill` | `direct-scripts` | `limited: ` +- blockers / warnings (e.g. obfuscation, framework guard) + +The subagent MUST NOT return raw decompiled sources. + +## RE Method values + +| Value | Meaning | +|---|---| +| `re-skill` | The `android-reverse-engineering` skill ran the workflow. | +| `direct-scripts` | The skill was absent; the sibling plugin's bash scripts ran. | +| `limited: ` | Flutter / React Native / Cordova / Xamarin — Java decompile is shallow; payloads may be empty and the digest is partial. | + +## Framework guard + +If the fingerprint reports Flutter / React Native / Cordova / Xamarin, set +`RE Method: limited: `, write whatever partial signals are +available (manifest, strings, hardcoded URLs, SDK list), and leave payloads +empty where they cannot be recovered. Downstream phases widen the +uncertainty band accordingly. +```` + +- [ ] **Step 4: Create the digest fixture** + +Create `plugins/clone-app/tests/fixtures/re-digest.sample.md`: + +```markdown +# RE Digest — com.example.app + +## Framework & Stack +Native Kotlin · Retrofit + OkHttp · Hilt · kotlinx.serialization · obfuscation: moderate + +## Hosts +| Host | Party | +|------|-------| +| api.example.com | first | +| analytics.thirdparty.io | third | + +## Endpoint Inventory +| Host | Method | Path | Auth | Source | +|------|--------|------|------|--------| +| api.example.com | POST | /v1/auth/login | none | com/example/api/AuthApi.java | +| api.example.com | GET | /v1/users/profile | Bearer | com/example/api/UserApi.java | +| api.example.com | POST | /v1/orders | Bearer | com/example/api/OrderApi.java | + +## Key Flow Payloads +### POST /v1/auth/login (auth) +- request body: `{ "email": "string", "password": "string" }` +- response: `{ "token": "string", "user": {} }` +- headers: `Content-Type: application/json` + +### POST /v1/orders (payment/core) +- request body: `{ "items": [], "total": "number" }` +- response: `{ "order_id": "string", "status": "string" }` +- headers: `Authorization: Bearer ` + +## BuildConfig Secrets +- BASE_URL = https://api.example.com/v1 +- ANALYTICS_KEY = + +## Feature Signals +~18 screens · SDKs: Firebase, AppsFlyer · permissions: INTERNET, ACCESS_NETWORK_STATE + +## RE Method +re-skill +``` + +- [ ] **Step 5: Create the payloads fixture** + +Create `plugins/clone-app/tests/fixtures/payloads.sample.json`: + +```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" } + }, + { + "host": "api.example.com", + "method": "GET", + "path": "/v1/users/profile", + "auth": "Bearer", + "source": "com/example/api/UserApi.java", + "request_body": null, + "response": null, + "headers": { "Authorization": "Bearer " } + } + ], + "buildconfig": { "BASE_URL": "https://api.example.com/v1" } +} +``` + +- [ ] **Step 6: Run test to verify it passes** + +Run: `bash plugins/clone-app/tests/test-re-digest-contract.sh` +Expected: all `PASS:` lines, exit 0. + +- [ ] **Step 7: Verify upstream untouched** + +Run: `git status --porcelain plugins/android-reverse-engineering/` +Expected: no output. + +- [ ] **Step 8: Commit** + +```bash +git add plugins/clone-app/skills/clone-app/references/re-digest-contract.md \ + plugins/clone-app/tests/fixtures/re-digest.sample.md \ + plugins/clone-app/tests/fixtures/payloads.sample.json \ + plugins/clone-app/tests/test-re-digest-contract.sh +git commit -m "test(clone-app): add RE digest contract, fixtures, structural test" +``` + +--- + +### Task 2: Rewrite SKILL.md Phase 2 + update Phases 5–6 + error table + +Rewrites Phase 2 to probe/dispatch/consume with the subagent and fallback, wires the digest into Phases 5–6, and extends the error table. The contract test from Task 1 is extended here to assert the SKILL.md wiring, so this task is independently testable. + +**Files:** +- Modify: `plugins/clone-app/skills/clone-app/SKILL.md` (Phase 2 block lines 43–71; Phase 5 ~93–99; Phase 6 ~101–112; error table ~122–133) +- Modify: `plugins/clone-app/tests/test-re-digest-contract.sh` (append SKILL.md wiring assertions) + +**Interfaces:** +- Consumes (from Task 1): the three output filenames (`re-digest.md`, `payloads.json`, `re-summary.txt`), the `references/re-digest-contract.md` path, and the `RE Method` values. +- Produces: Phase 2 prose that any later phase relies on — `$WORK/re-summary.txt` read in Phase 2c, `$WORK/payloads.json` read in Phase 5, `$WORK/re-digest.md` referenced in Phase 6. + +- [ ] **Step 1: Append failing wiring assertions to the test** + +Add to the end of `plugins/clone-app/tests/test-re-digest-contract.sh`, BEFORE the final `exit $fail` line (replace that final line): + +```bash +# --- SKILL.md Phase 2 wiring (Task 2) --- +SKILL="$P/skills/clone-app/SKILL.md" +hasS() { grep -qF "$1" "$SKILL" && echo "PASS: SKILL $2" || { echo "FAIL: SKILL $2 — '$1' missing"; fail=1; }; } +hasReS() { grep -qE "$1" "$SKILL" && echo "PASS: SKILL $2" || { echo "FAIL: SKILL $2 — /$1/ missing"; fail=1; }; } + +hasS "re-digest-contract.md" "Phase 2 points at the digest contract" +hasReS "subagent|Agent tool|dispatch" "Phase 2 dispatches a subagent" +hasS "android-reverse-engineering skill" "Phase 2 names the RE skill branch" +hasS "direct-scripts" "Phase 2 names the script-fallback branch" +hasS "re-summary.txt" "Phase 2c consumes the summary" +hasS "payloads.json" "Phase 5 consumes payloads.json" +hasS "Backend API Surface" "Phase 6 adds the Backend API Surface section" +hasS "RE subagent" "error table covers subagent failure" + +exit $fail +``` + +- [ ] **Step 2: Run test to verify the new assertions fail** + +Run: `bash plugins/clone-app/tests/test-re-digest-contract.sh` +Expected: Task-1 assertions still PASS; the new `SKILL …` assertions FAIL (SKILL.md not yet rewritten), exit non-zero. + +- [ ] **Step 3: Replace the Phase 2 block in SKILL.md** + +In `plugins/clone-app/skills/clone-app/SKILL.md`, replace the entire `## Phase 2: Reverse Engineering` section (from the `## Phase 2` heading through the line ending `...Keep this in context for later phases.`) with: + +````markdown +## Phase 2: Reverse Engineering (probe → dispatch → consume) + +RE runs inside an **isolated subagent** so the decompiled sources never flood +this orchestrator's context. The subagent prefers the +`android-reverse-engineering` **skill** and falls back to that plugin's bash +**scripts**. Either way it writes the same digest files to `$WORK/`, defined +in `${CLAUDE_PLUGIN_ROOT}/skills/clone-app/references/re-digest-contract.md`. + +### Phase 2a — Probe + +```bash +RE="$(bash ${CLAUDE_PLUGIN_ROOT}/skills/clone-app/scripts/resolve-re-scripts.sh 2>/tmp/re-err)"; RC=$? +``` +- `RC == 0` → the RE **scripts** are on disk (fallback is available). If it + printed a `WARNING:` about bash version, the scripts need **bash 4+** + (macOS ships 3.2; `${VAR,,}` fails as "bad substitution") — install one with + `brew install bash` before the script-fallback branch can succeed. +- Check your own available-skills list for `android-reverse-engineering` → + is the RE **skill** registered? + +Pick the branch: + +| RE skill registered | RE scripts on disk (`RC`) | Branch | +|---|---|---| +| yes | any | **re-skill** | +| no | 0 | **direct-scripts** | +| no | 1 | **stop** — show the `/tmp/re-err` resolver error and halt | + +### Phase 2b — Dispatch the subagent + +Dispatch one subagent (Agent tool, `general-purpose` type — it can both invoke +skills and run bash). Pass it: `$PKG`, `$APK`, `$WORK`, the chosen **branch**, +the resolved `$RE` scripts dir, and the path to `re-digest-contract.md`. Its +instructions: + +1. **Run RE per branch.** + - **re-skill:** invoke the `android-reverse-engineering` skill on `$APK`, + output dir `$WORK/output` — run its full workflow (fingerprint, deps, + decompile, Kotlin-name recovery if Kotlin, API extraction incl. Tier-2). + - **direct-scripts:** run, in order, reading each output before the next: + `bash "$RE/fingerprint.sh" "$APK"`, `bash "$RE/check-deps.sh"` + (install required deps via `bash "$RE/install-dep.sh" `; ask before + optional vineflower/dex2jar), `bash "$RE/decompile.sh" -o "$WORK/output" "$APK"` + (add `--deobf` if obfuscation is heavy), `bash "$RE/recover-kotlin-names.sh" + "$WORK/output/sources" "$WORK/output/names/"` if Kotlin, then + `bash "$RE/find-api-calls.sh" "$WORK/output/sources"`. +2. **Framework guard:** if the fingerprint is Flutter / React Native / Cordova + / Xamarin, Java decompile is shallow — produce a partial digest, set + `RE Method: limited: `, payloads may be empty. +3. **Extract** the Tier-1 endpoint inventory and Tier-2 payloads for **auth, + payment/checkout, and the 1–2 core feature endpoints** (not every endpoint). +4. **Write** `$WORK/re-digest.md`, `$WORK/payloads.json`, `$WORK/re-summary.txt` + exactly per `re-digest-contract.md`. +5. **Return** the contents of `$WORK/re-summary.txt` plus the two file paths — + **never** raw decompiled sources. + +If the subagent fails, retry once; if it still fails and the **direct-scripts** +branch is available, re-dispatch on that branch; otherwise stop and report. + +### Phase 2c — Consume + +Read `$WORK/re-summary.txt` (the only RE text in this context). From it you have: +framework, HTTP stack, host counts, endpoint count, key-flow names, secrets +count, and the RE method. Read `$WORK/re-digest.md` or `$WORK/payloads.json` +**on demand** when a later phase needs detail. Keep the summary in context for +Phases 3–7. +```` + +- [ ] **Step 4: Update Phase 5 to read payloads.json** + +In `plugins/clone-app/skills/clone-app/SKILL.md`, in `## Phase 5: Effort & Cost Estimation`, replace the line: + +``` +- the feature list → AI-Sprint effort table (min-max total, uncertainty band), +``` + +with: + +``` +- read `$WORK/payloads.json`; the endpoint count and the payload complexity of + the key flows size the backend work, +- the feature list + backend surface → AI-Sprint effort table (min-max total, + uncertainty band; widen the band when RE Method is `limited:`), +``` + +- [ ] **Step 5: Update Phase 6 to add the Backend API Surface section** + +In `## Phase 6: Market Viability Report`, after the sentence ending +`...Fill every section from the data gathered.` add: + +``` +Include a **Backend API Surface** section: summarize the Tier-1 inventory from +`$WORK/re-digest.md` and the key-flow payloads from `$WORK/payloads.json` (host +list, endpoint count, auth model, and the auth/payment/core request+response +shapes). If RE Method was `limited:`, say so and note the reduced confidence. +``` + +- [ ] **Step 6: Extend the error table** + +In `plugins/clone-app/skills/clone-app/SKILL.md`, in the `## Error Handling Summary` table, replace the row: + +``` +| RE plugin missing | show resolver error, stop | +``` + +with these rows: + +``` +| RE skill + scripts both missing | show resolver error, stop | +| RE subagent fails | retry once, then fall back to direct-scripts branch; else stop | +| Subagent returned no digest files | re-dispatch once; if still missing, stop and report | +``` + +- [ ] **Step 7: Run the contract test to verify it passes** + +Run: `bash plugins/clone-app/tests/test-re-digest-contract.sh` +Expected: all `PASS:` (Task 1 + the new SKILL wiring assertions), exit 0. + +- [ ] **Step 8: Verify upstream untouched** + +Run: `git status --porcelain plugins/android-reverse-engineering/` +Expected: no output. + +- [ ] **Step 9: Commit** + +```bash +git add plugins/clone-app/skills/clone-app/SKILL.md \ + plugins/clone-app/tests/test-re-digest-contract.sh +git commit -m "feat(clone-app): run RE via isolated subagent with script fallback + payloads" +``` + +--- + +### Task 3: Register the contract doc in the smoke test + full suite green + +Adds the new reference file to the structural smoke check and confirms the whole suite passes. A reviewer can reject this independently if the smoke test or aggregate run regresses. + +**Files:** +- Modify: `plugins/clone-app/tests/smoke-structure.sh:19-21` (the references loop) + +**Interfaces:** +- Consumes (from Task 1): the reference filename `re-digest-contract`. +- Produces: nothing downstream — terminal verification task. + +- [ ] **Step 1: Add the new reference to the smoke test's existence check** + +In `plugins/clone-app/tests/smoke-structure.sh`, replace: + +```bash +for r in stack-recommendation-guide effort-estimation-guide infra-cost-guide report-template; do + must_exist "$P/skills/clone-app/references/$r.md" +done +``` + +with: + +```bash +for r in stack-recommendation-guide effort-estimation-guide infra-cost-guide report-template re-digest-contract; do + must_exist "$P/skills/clone-app/references/$r.md" +done +``` + +- [ ] **Step 2: Run the smoke test** + +Run: `bash plugins/clone-app/tests/smoke-structure.sh` +Expected: all `PASS` lines including `PASS exists: plugins/clone-app/skills/clone-app/references/re-digest-contract.md`, exit 0. + +- [ ] **Step 3: Run the full clone-app suite** + +Run: `bash plugins/clone-app/tests/run-all.sh` +Expected: every suite runs; final line `ALL TESTS PASSED`, exit 0. (`run-all.sh` auto-discovers `test-re-digest-contract.sh` via its `test-*.sh` glob — no registration needed.) + +- [ ] **Step 4: Verify upstream untouched** + +Run: `git status --porcelain plugins/android-reverse-engineering/` +Expected: no output. + +- [ ] **Step 5: Commit** + +```bash +git add plugins/clone-app/tests/smoke-structure.sh +git commit -m "test(clone-app): register re-digest-contract in smoke structure check" +``` + +--- + +## Self-Review + +**Spec coverage:** +- Phase 2 probe/dispatch/consume → Task 2 Step 3. ✓ +- Subagent isolation (Agent tool, general-purpose) → Task 2 Step 3 Phase 2b. ✓ +- Branch decision table (skill / scripts / stop) → Task 2 Step 3 Phase 2a. ✓ +- Digest contract (3 files, schemas, RE Method values, framework guard) → Task 1 Step 3. ✓ +- Tier-2 payloads for auth/payment/core only → contract doc + Task 2 Phase 2b step 3. ✓ +- Durable memory in `$WORK/` (memory option 1) → files written by subagent, consumed on demand. ✓ +- Phase 5 reads payloads.json → Task 2 Step 4. ✓ +- Phase 6 Backend API Surface section → Task 2 Step 5. ✓ +- Error table additions (subagent fail, no digest, both branches missing) → Task 2 Step 6. ✓ +- New fixtures + structural tests, offline → Task 1. ✓ +- smoke-structure.sh updated → Task 3 Step 1. ✓ +- Upstream untouched check → every task's penultimate step + global constraint. ✓ +- `resolve-re-scripts.sh` unchanged → not modified in any task. ✓ + +**Placeholder scan:** No TBD/TODO; every code/doc step shows full content. ✓ + +**Type consistency:** Filenames (`re-digest.md`, `payloads.json`, `re-summary.txt`), JSON keys (`package`, `re_method`, `endpoints`, `buildconfig`, `request_body`, `response`, `headers`), section headings, and RE Method values (`re-skill`, `direct-scripts`, `limited:`) are identical across the contract doc, fixtures, tests, and SKILL.md assertions. ✓ From b6eca91d1d6a2935181193ec11e61a03b8e75c70 Mon Sep 17 00:00:00 2001 From: "fatih.bulut" Date: Sun, 21 Jun 2026 17:12:58 +0300 Subject: [PATCH 3/6] test(clone-app): add RE digest contract, fixtures, structural test --- .../references/re-digest-contract.md | 85 +++++++++++++++++++ .../tests/fixtures/payloads.sample.json | 27 ++++++ .../tests/fixtures/re-digest.sample.md | 38 +++++++++ .../tests/test-re-digest-contract.sh | 48 +++++++++++ 4 files changed, 198 insertions(+) create mode 100644 plugins/clone-app/skills/clone-app/references/re-digest-contract.md create mode 100644 plugins/clone-app/tests/fixtures/payloads.sample.json create mode 100644 plugins/clone-app/tests/fixtures/re-digest.sample.md create mode 100644 plugins/clone-app/tests/test-re-digest-contract.sh diff --git a/plugins/clone-app/skills/clone-app/references/re-digest-contract.md b/plugins/clone-app/skills/clone-app/references/re-digest-contract.md new file mode 100644 index 0000000..0a000ed --- /dev/null +++ b/plugins/clone-app/skills/clone-app/references/re-digest-contract.md @@ -0,0 +1,85 @@ +# RE Digest Contract + +The Phase 2 subagent runs the reverse-engineering workflow in isolation and +MUST produce these three files under `$WORK/`, then return only the summary. +This file is the single source of truth for their schema. The subagent prompt +points here; do not duplicate the schema into SKILL.md prose. + +## File 1 — `$WORK/re-digest.md` (human-readable, main artifact) + +Required section headings, in this order: + +``` +# 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 flows + — 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: +``` + +## File 2 — `$WORK/payloads.json` (machine-readable, durable memory) + +Required top-level keys: `package`, `re_method`, `endpoints`, `buildconfig`. +Each item in `endpoints` has: `host`, `method`, `path`, `auth`, `source`, +`request_body`, `response`, `headers`. + +```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` and `response` are `null` for Tier-1-only endpoints. +- Populate them ONLY for the key flows: **auth, payment/checkout, and the + 1–2 core feature endpoints** (decision Q3=B). Everything else is a Tier-1 + row with `null` payloads. Going Tier-2 on every endpoint is a non-goal — + it is token-expensive and the RE skill itself warns against it. + +## File 3 — `$WORK/re-summary.txt` (≤40 lines, the only RE text returned) + +Plain text. The subagent's return value = the contents of this file plus the +paths to the two files above. Fields: + +- framework +- host count (first-party / third-party) +- endpoint count +- key-flow names found (auth / payment / core) +- secrets-found count (BuildConfig) +- RE method: `re-skill` | `direct-scripts` | `limited: ` +- blockers / warnings (e.g. obfuscation, framework guard) + +The subagent MUST NOT return raw decompiled sources. + +## RE Method values + +| Value | Meaning | +|---|---| +| `re-skill` | The `android-reverse-engineering` skill ran the workflow. | +| `direct-scripts` | The skill was absent; the sibling plugin's bash scripts ran. | +| `limited: ` | Flutter / React Native / Cordova / Xamarin — Java decompile is shallow; payloads may be empty and the digest is partial. | + +## Framework guard + +If the fingerprint reports Flutter / React Native / Cordova / Xamarin, set +`RE Method: limited: `, write whatever partial signals are +available (manifest, strings, hardcoded URLs, SDK list), and leave payloads +empty where they cannot be recovered. Downstream phases widen the +uncertainty band accordingly. diff --git a/plugins/clone-app/tests/fixtures/payloads.sample.json b/plugins/clone-app/tests/fixtures/payloads.sample.json new file mode 100644 index 0000000..1cee721 --- /dev/null +++ b/plugins/clone-app/tests/fixtures/payloads.sample.json @@ -0,0 +1,27 @@ +{ + "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" } + }, + { + "host": "api.example.com", + "method": "GET", + "path": "/v1/users/profile", + "auth": "Bearer", + "source": "com/example/api/UserApi.java", + "request_body": null, + "response": null, + "headers": { "Authorization": "Bearer " } + } + ], + "buildconfig": { "BASE_URL": "https://api.example.com/v1" } +} diff --git a/plugins/clone-app/tests/fixtures/re-digest.sample.md b/plugins/clone-app/tests/fixtures/re-digest.sample.md new file mode 100644 index 0000000..4e46e97 --- /dev/null +++ b/plugins/clone-app/tests/fixtures/re-digest.sample.md @@ -0,0 +1,38 @@ +# RE Digest — com.example.app + +## Framework & Stack +Native Kotlin · Retrofit + OkHttp · Hilt · kotlinx.serialization · obfuscation: moderate + +## Hosts +| Host | Party | +|------|-------| +| api.example.com | first | +| analytics.thirdparty.io | third | + +## Endpoint Inventory +| Host | Method | Path | Auth | Source | +|------|--------|------|------|--------| +| api.example.com | POST | /v1/auth/login | none | com/example/api/AuthApi.java | +| api.example.com | GET | /v1/users/profile | Bearer | com/example/api/UserApi.java | +| api.example.com | POST | /v1/orders | Bearer | com/example/api/OrderApi.java | + +## Key Flow Payloads +### POST /v1/auth/login (auth) +- request body: `{ "email": "string", "password": "string" }` +- response: `{ "token": "string", "user": {} }` +- headers: `Content-Type: application/json` + +### POST /v1/orders (payment/core) +- request body: `{ "items": [], "total": "number" }` +- response: `{ "order_id": "string", "status": "string" }` +- headers: `Authorization: Bearer ` + +## BuildConfig Secrets +- BASE_URL = https://api.example.com/v1 +- ANALYTICS_KEY = + +## Feature Signals +~18 screens · SDKs: Firebase, AppsFlyer · permissions: INTERNET, ACCESS_NETWORK_STATE + +## RE Method +re-skill diff --git a/plugins/clone-app/tests/test-re-digest-contract.sh b/plugins/clone-app/tests/test-re-digest-contract.sh new file mode 100644 index 0000000..e2d0657 --- /dev/null +++ b/plugins/clone-app/tests/test-re-digest-contract.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -uo pipefail +HERE="$(cd "$(dirname "$0")" && pwd)" +P="$HERE/.." # plugins/clone-app +CONTRACT="$P/skills/clone-app/references/re-digest-contract.md" +DIGEST_FIX="$HERE/fixtures/re-digest.sample.md" +PAYLOAD_FIX="$HERE/fixtures/payloads.sample.json" +fail=0 +has() { grep -qF "$2" "$1" && echo "PASS: $3" || { echo "FAIL: $3 — '$2' not in ${1##*/}"; fail=1; }; } + +# Contract doc exists and documents every required re-digest.md section heading +for sec in "## Framework & Stack" "## Hosts" "## Endpoint Inventory" \ + "## Key Flow Payloads" "## BuildConfig Secrets" "## Feature Signals" "## RE Method"; do + has "$CONTRACT" "$sec" "contract documents section $sec" +done + +# Contract doc documents every required payloads.json key +for key in '"package"' '"re_method"' '"endpoints"' '"buildconfig"' \ + '"request_body"' '"response"' '"headers"'; do + has "$CONTRACT" "$key" "contract documents json key $key" +done + +# Contract names the three output files and the three RE Method values +for tok in "re-digest.md" "payloads.json" "re-summary.txt" \ + "re-skill" "direct-scripts" "limited:"; do + has "$CONTRACT" "$tok" "contract names token $tok" +done + +# Digest fixture has every required section heading +for sec in "## Framework & Stack" "## Hosts" "## Endpoint Inventory" \ + "## Key Flow Payloads" "## BuildConfig Secrets" "## Feature Signals" "## RE Method"; do + has "$DIGEST_FIX" "$sec" "digest fixture has section $sec" +done + +# Payload fixture is valid JSON and has the required shape +python3 -c " +import json,sys +d=json.load(open('$PAYLOAD_FIX')) +for k in ('package','re_method','endpoints','buildconfig'): + assert k in d, 'missing top key '+k +assert isinstance(d['endpoints'],list) and d['endpoints'], 'endpoints must be non-empty list' +for e in d['endpoints']: + for k in ('host','method','path','auth','source','request_body','response','headers'): + assert k in e, 'endpoint missing key '+k +print('PASS: payload fixture shape valid') +" || { echo "FAIL: payload fixture shape"; fail=1; } + +exit $fail From 567b512e32457575d76c4482ec8742a9714087b9 Mon Sep 17 00:00:00 2001 From: "fatih.bulut" Date: Sun, 21 Jun 2026 17:19:29 +0300 Subject: [PATCH 4/6] feat(clone-app): run RE via isolated subagent with script fallback + payloads --- plugins/clone-app/skills/clone-app/SKILL.md | 98 ++++++++++++++----- .../tests/test-re-digest-contract.sh | 14 +++ 2 files changed, 86 insertions(+), 26 deletions(-) diff --git a/plugins/clone-app/skills/clone-app/SKILL.md b/plugins/clone-app/skills/clone-app/SKILL.md index a6c16e8..eef3441 100644 --- a/plugins/clone-app/skills/clone-app/SKILL.md +++ b/plugins/clone-app/skills/clone-app/SKILL.md @@ -40,35 +40,72 @@ a Cloudflare bot challenge), retries 3×, and prints the path (`app.apk` or format changed — tell the user the download failed and ask for a local APK/XAPK path; set `APK` to that path. -## Phase 2: Reverse Engineering +## Phase 2: Reverse Engineering (probe → dispatch → consume) + +RE runs inside an **isolated subagent** so the decompiled sources never flood +this orchestrator's context. The subagent prefers the +`android-reverse-engineering` **skill** and falls back to that plugin's bash +**scripts**. Either way it writes the same digest files to `$WORK/`, defined +in `${CLAUDE_PLUGIN_ROOT}/skills/clone-app/references/re-digest-contract.md`. + +### Phase 2a — Probe -Resolve the sibling RE scripts: ```bash -RE="$(bash ${CLAUDE_PLUGIN_ROOT}/skills/clone-app/scripts/resolve-re-scripts.sh)" +RE="$(bash ${CLAUDE_PLUGIN_ROOT}/skills/clone-app/scripts/resolve-re-scripts.sh 2>/tmp/re-err)"; RC=$? ``` -If it exits non-zero, show its error (RE plugin not installed) and stop. If it -prints a `WARNING:` about bash version, the RE scripts need **bash 4+** (macOS -ships 3.2; their `${VAR,,}` syntax fails as "bad substitution" otherwise) — -install one with `brew install bash` before continuing, then re-run Phase 2. +- `RC == 0` → the RE **scripts** are on disk (fallback is available). If it + printed a `WARNING:` about bash version, the scripts need **bash 4+** + (macOS ships 3.2; `${VAR,,}` fails as "bad substitution") — install one with + `brew install bash` before the script-fallback branch can succeed. +- Check your own available-skills list for `android-reverse-engineering` → + is the RE **skill** registered? -Run, in order, reading each output before the next: -1. `bash "$RE/fingerprint.sh" "$APK"` — framework, HTTP stack, obfuscation, SDKs, native libs. - - **If framework is Flutter / React Native / Cordova / Xamarin:** tell the user Java - decompilation is limited; proceed but rely on manifest + strings + hardcoded URLs + - the fingerprint SDK list. Skip steps 3-5's deep API extraction expectations. -2. `bash "$RE/check-deps.sh"` — parse `INSTALL_REQUIRED:` / `INSTALL_OPTIONAL:` lines. - Install required deps with `bash "$RE/install-dep.sh" `; re-run check-deps until clean. - Ask the user before installing optional deps (vineflower, dex2jar). -3. `bash "$RE/decompile.sh" -o "$WORK/output" "$APK"` (add `--deobf` if fingerprint showed heavy obfuscation: `bash "$RE/decompile.sh" -o "$WORK/output" --deobf "$APK"`). - Sources land at `$WORK/output/sources/`. -4. If the app is Kotlin: `bash "$RE/recover-kotlin-names.sh" "$WORK/output/sources" "$WORK/output/names/"`. -5. `bash "$RE/find-api-calls.sh" "$WORK/output/sources"` (full scan; add `--ktor`/`--apollo`/`--paths` as - the fingerprint suggests). +Pick the branch: -From these outputs assemble: framework, HTTP stack, **API endpoint list**, -first-party vs third-party hosts, AndroidManifest summary (permissions, components), -and a **feature list** (screen count, SDKs, backend signals). Keep this in context -for later phases. +| RE skill registered | RE scripts on disk (`RC`) | Branch | +|---|---|---| +| yes | any | **re-skill** | +| no | 0 | **direct-scripts** | +| no | 1 | **stop** — show the `/tmp/re-err` resolver error and halt | + +### Phase 2b — Dispatch the subagent + +Dispatch one subagent (Agent tool, `general-purpose` type — it can both invoke +skills and run bash). Pass it: `$PKG`, `$APK`, `$WORK`, the chosen **branch**, +the resolved `$RE` scripts dir, and the path to `re-digest-contract.md`. Its +instructions: + +1. **Run RE per branch.** + - **re-skill:** invoke the android-reverse-engineering skill on `$APK`, + output dir `$WORK/output` — run its full workflow (fingerprint, deps, + decompile, Kotlin-name recovery if Kotlin, API extraction incl. Tier-2). + - **direct-scripts:** run, in order, reading each output before the next: + `bash "$RE/fingerprint.sh" "$APK"`, `bash "$RE/check-deps.sh"` + (install required deps via `bash "$RE/install-dep.sh" `; ask before + optional vineflower/dex2jar), `bash "$RE/decompile.sh" -o "$WORK/output" "$APK"` + (add `--deobf` if obfuscation is heavy), `bash "$RE/recover-kotlin-names.sh" + "$WORK/output/sources" "$WORK/output/names/"` if Kotlin, then + `bash "$RE/find-api-calls.sh" "$WORK/output/sources"`. +2. **Framework guard:** if the fingerprint is Flutter / React Native / Cordova + / Xamarin, Java decompile is shallow — produce a partial digest, set + `RE Method: limited: `, payloads may be empty. +3. **Extract** the Tier-1 endpoint inventory and Tier-2 payloads for **auth, + payment/checkout, and the 1–2 core feature endpoints** (not every endpoint). +4. **Write** `$WORK/re-digest.md`, `$WORK/payloads.json`, `$WORK/re-summary.txt` + exactly per `re-digest-contract.md`. +5. **Return** the contents of `$WORK/re-summary.txt` plus the two file paths — + **never** raw decompiled sources. + +If the subagent fails, retry once; if it still fails and the **direct-scripts** +branch is available, re-dispatch on that branch; otherwise stop and report. + +### Phase 2c — Consume + +Read `$WORK/re-summary.txt` (the only RE text in this context). From it you have: +framework, HTTP stack, host counts, endpoint count, key-flow names, secrets +count, and the RE method. Read `$WORK/re-digest.md` or `$WORK/payloads.json` +**on demand** when a later phase needs detail. Keep the summary in context for +Phases 3–7. ## Phase 3: Store Analysis @@ -94,7 +131,10 @@ the user to choose. **Wait for the user's choice before Phase 5.** Lock it. Read `${CLAUDE_PLUGIN_ROOT}/skills/clone-app/references/effort-estimation-guide.md` and `infra-cost-guide.md`. Build: -- the feature list → AI-Sprint effort table (min-max total, uncertainty band), +- read `$WORK/payloads.json`; the endpoint count and the payload complexity of + the key flows size the backend work, +- the feature list + backend surface → AI-Sprint effort table (min-max total, + uncertainty band; widen the band when RE Method is `limited:`), - the MVP/Growth/Scale monthly infra cost table. Base both on the **user-selected stack** from Phase 4. @@ -104,6 +144,10 @@ Read `${CLAUDE_PLUGIN_ROOT}/skills/clone-app/references/report-template.md`. Fill every section from the data gathered. For market analysis (competitors, market size), use web search as needed. Produce a GO / CONDITIONAL GO / NO GO verdict tying effort + cost against market opportunity. +Include a **Backend API Surface** section: summarize the Tier-1 inventory from +`$WORK/re-digest.md` and the key-flow payloads from `$WORK/payloads.json` (host +list, endpoint count, auth model, and the auth/payment/core request+response +shapes). If RE Method was `limited:`, say so and note the reduced confidence. Write the report: ``` @@ -124,7 +168,9 @@ implementation plan?" |---|---| | Package not in URL | ask user for package name | | Download fails 3× | ask for local APK path | -| RE plugin missing | show resolver error, stop | +| RE skill + scripts both missing | show resolver error, stop | +| RE subagent fails | retry once, then fall back to direct-scripts branch; else stop | +| Subagent returned no digest files | re-dispatch once; if still missing, stop and report | | Flutter/RN/Cordova/Xamarin | warn, continue with limited RE | | App Store not found | continue Google Play only | | Play scrape returns nulls | web-search fallback, note source | diff --git a/plugins/clone-app/tests/test-re-digest-contract.sh b/plugins/clone-app/tests/test-re-digest-contract.sh index e2d0657..81c70ba 100644 --- a/plugins/clone-app/tests/test-re-digest-contract.sh +++ b/plugins/clone-app/tests/test-re-digest-contract.sh @@ -45,4 +45,18 @@ for e in d['endpoints']: print('PASS: payload fixture shape valid') " || { echo "FAIL: payload fixture shape"; fail=1; } +# --- SKILL.md Phase 2 wiring (Task 2) --- +SKILL="$P/skills/clone-app/SKILL.md" +hasS() { grep -qF "$1" "$SKILL" && echo "PASS: SKILL $2" || { echo "FAIL: SKILL $2 — '$1' missing"; fail=1; }; } +hasReS() { grep -qE "$1" "$SKILL" && echo "PASS: SKILL $2" || { echo "FAIL: SKILL $2 — /$1/ missing"; fail=1; }; } + +hasS "re-digest-contract.md" "Phase 2 points at the digest contract" +hasReS "subagent|Agent tool|dispatch" "Phase 2 dispatches a subagent" +hasS "android-reverse-engineering skill" "Phase 2 names the RE skill branch" +hasS "direct-scripts" "Phase 2 names the script-fallback branch" +hasS "re-summary.txt" "Phase 2c consumes the summary" +hasS "payloads.json" "Phase 5 consumes payloads.json" +hasS "Backend API Surface" "Phase 6 adds the Backend API Surface section" +hasS "RE subagent" "error table covers subagent failure" + exit $fail From c8e5bb08a43d86c54d37dc803d811aa994f2dd2e Mon Sep 17 00:00:00 2001 From: "fatih.bulut" Date: Sun, 21 Jun 2026 17:24:03 +0300 Subject: [PATCH 5/6] test(clone-app): register re-digest-contract in smoke structure check --- plugins/clone-app/tests/smoke-structure.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/clone-app/tests/smoke-structure.sh b/plugins/clone-app/tests/smoke-structure.sh index c6f7462..266dafb 100755 --- a/plugins/clone-app/tests/smoke-structure.sh +++ b/plugins/clone-app/tests/smoke-structure.sh @@ -16,7 +16,7 @@ done for s in scrape-play-store.py check-appstore.py; do must_exist "$P/skills/clone-app/scripts/$s" done -for r in stack-recommendation-guide effort-estimation-guide infra-cost-guide report-template; do +for r in stack-recommendation-guide effort-estimation-guide infra-cost-guide report-template re-digest-contract; do must_exist "$P/skills/clone-app/references/$r.md" done From 5adfa2a1ae5b596878c1b291a46904826d4ed569 Mon Sep 17 00:00:00 2001 From: "fatih.bulut" Date: Sun, 21 Jun 2026 17:29:52 +0300 Subject: [PATCH 6/6] docs(clone-app): tie Phase 2 fallback guard to probe RC==0 Co-Authored-By: Claude Opus 4.8 --- plugins/clone-app/skills/clone-app/SKILL.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/clone-app/skills/clone-app/SKILL.md b/plugins/clone-app/skills/clone-app/SKILL.md index eef3441..7980b97 100644 --- a/plugins/clone-app/skills/clone-app/SKILL.md +++ b/plugins/clone-app/skills/clone-app/SKILL.md @@ -97,7 +97,8 @@ instructions: **never** raw decompiled sources. If the subagent fails, retry once; if it still fails and the **direct-scripts** -branch is available, re-dispatch on that branch; otherwise stop and report. +branch is available (i.e. the Phase 2a probe returned `RC == 0`), re-dispatch on +that branch; otherwise stop and report. ### Phase 2c — Consume