Summary
Beetroot can prove a runtime hook fired — the tier-lsposed-hook e2e asserts BEETROOT_HOOK_FIRED, and a Frida script logs its own success — but it has no primitive to assert that the app under test stayed healthy once the hook armed. There is no CLI verb, backend capability, or workflow step that answers: did the target launch and stay alive — no self-restart, no ANR, no FATAL EXCEPTION, no native crash/tombstone, no Process.killProcess / System.exit?
Why this matters for an on-device hook framework
A hook that fires is not the same as a hook that's correct. A hook that forces an inconsistent runtime state can make the target tear its own UI down and restart, ANR, or crash natively shortly after the hook arms — while still logging "hook fired." Catching that class of regression today requires instrumenting the target app itself (hooking Activity.finish* / finishAndRemoveTask / recreate, Process.killProcess, System.exit; scraping logcat for FATAL / ANR / tombstones; watching the target PID for an unexpected restart). That instrumentation is exactly the boilerplate an E2E framework should own, not push onto every module/script author. Without it, "the hook fired" is a green test that hides an app that is actually unusable.
What's missing
- No "launch package X and assert it is still the same live process after N seconds" check (PID stability / no unexpected restart).
- No "assert no
FATAL EXCEPTION / ANR in <pkg> / native crash (/data/tombstones, DEBUG : signal) attributable to package X since launch" check.
- No soak window: bugs that only surface after the app runs for a while or does I/O (a delayed state revert, a teardown that fires ~hundreds of ms after launch) need an observe-for-N-seconds-then-assert-health mode, not a one-shot check immediately after launch.
beetroot doctor is instance health (sys.boot_completed, Zygisk, the Frida socket) — it says nothing about the app under test.
Proposed shape
A capability that, given a target package, can:
- launch it (or attach to an already-launched instance),
- capture a baseline (PID, logcat cursor),
- after an optional soak window, assert: process still alive and not restarted; no
FATAL EXCEPTION / ANR / native crash attributable to the package; (optionally) the app reached/stayed at a named Activity.
Expose it as a CLI verb (e.g. beetroot assert-alive <name> <pkg> --for 60s) and/or a documented reusable-workflow building block, returning a non-zero exit plus the captured evidence (the crashing stack / tombstone / restart trace) on failure.
Related (not duplicates)
Summary
Beetroot can prove a runtime hook fired — the
tier-lsposed-hooke2e assertsBEETROOT_HOOK_FIRED, and a Frida script logs its own success — but it has no primitive to assert that the app under test stayed healthy once the hook armed. There is no CLI verb, backend capability, or workflow step that answers: did the target launch and stay alive — no self-restart, no ANR, noFATAL EXCEPTION, no native crash/tombstone, noProcess.killProcess/System.exit?Why this matters for an on-device hook framework
A hook that fires is not the same as a hook that's correct. A hook that forces an inconsistent runtime state can make the target tear its own UI down and restart, ANR, or crash natively shortly after the hook arms — while still logging "hook fired." Catching that class of regression today requires instrumenting the target app itself (hooking
Activity.finish*/finishAndRemoveTask/recreate,Process.killProcess,System.exit; scraping logcat forFATAL/ANR/ tombstones; watching the target PID for an unexpected restart). That instrumentation is exactly the boilerplate an E2E framework should own, not push onto every module/script author. Without it, "the hook fired" is a green test that hides an app that is actually unusable.What's missing
FATAL EXCEPTION/ANR in <pkg>/ native crash (/data/tombstones,DEBUG : signal) attributable to package X since launch" check.beetroot doctoris instance health (sys.boot_completed, Zygisk, the Frida socket) — it says nothing about the app under test.Proposed shape
A capability that, given a target package, can:
FATAL EXCEPTION/ANR/ native crash attributable to the package; (optionally) the app reached/stayed at a named Activity.Expose it as a CLI verb (e.g.
beetroot assert-alive <name> <pkg> --for 60s) and/or a documented reusable-workflow building block, returning a non-zero exit plus the captured evidence (the crashing stack / tombstone / restart trace) on failure.Related (not duplicates)