A cross-platform, standard-library-only Python package under scripts/device-testing/ that replicates LibreMail''s on-device performance-test scenarios and logging capture. It codifies the methodology run by hand on 2026-07-05 (Pixel 10 Pro XL) and written up in the perf/causation reports.
Package layout
File
Role
perf_harness.py
CLI entry: device selection, logcat streaming, timestamped run dir, report.
breadcrumbs.py
Pure, unit-tested parser for the ImapPerf / MailReader / Reader / MailBackfiller breadcrumbs + open-correlation.
cold-open, message-open (uncached), back-nav, prefetch-ab (fetch-policy toggle: Fetch all on Wi-Fi vs Always on-demand), and cross-provider (buckets by breadcrumb account ref).
Device safety (baked in as hard guardrails)
Allow-list of adb subcommands; everything else (uninstall/root/remount/reboot/push/pull) is refused.
Deny-list + assertions on every shell command: no pm clear / pm uninstall, no reboot/remount/root/verity/factory, no touching databases/files/shared_prefs/datastore/, no redirects; run-as / am constrained to the target package.
The only sanctioned app-state mutation is clearing LibreMail''s own cache/ (exact-match). No pm clear, uninstall, or data wipe can be constructed.
Screen kept awake and restored; every uiautomator/input step guarded against the keyguard and foreign apps (a sample against either is skipped, not measured).
Validated vs. needs the live run
Validated offline (unit tests, no device): breadcrumb parsing + correlation reproduce the manual timing-tables.md figures exactly (Gmail A1 took=31227 ms, rfc822=60457 B, 4.2 KB/s; Outlook O1 took=2934 ms, 139.5 KB/s); the guardrails accept all known-good and refuse all forbidden commands; screen/keyguard recognition; report rendering; and --dry-run emits the correct command plan for all five scenarios.
Needs the first monitored live run: end-to-end hardware timing capture, and the prefetch-absettings-screen navigation (no settings dump existed in the manual run, so set_fetch_policy navigates by on-screen option text with a scroll fallback). Per the brief, auto-merge is intentionally not armed — the maintainer reviews the tooling and we validate it live together.
Tests
python -m unittest discover -s scripts/device-testing/tests -p "test_*.py"
# Ran 68 tests ... OK
Pure Python dev tool (stdlib only, matching the .claude/skills/preflight/*.py convention); no Kotlin/app source touched.
## What
A cross-platform, **standard-library-only** Python package under `scripts/device-testing/` that replicates LibreMail''s on-device performance-test scenarios and logging capture. It codifies the methodology run by hand on 2026-07-05 (Pixel 10 Pro XL) and written up in the perf/causation reports.
## Package layout
| File | Role |
|------|------|
| `perf_harness.py` | CLI entry: device selection, logcat streaming, timestamped run dir, report. |
| `breadcrumbs.py` | **Pure, unit-tested** parser for the `ImapPerf` / `MailReader` / `Reader` / `MailBackfiller` breadcrumbs + open-correlation. |
| `adb.py` | Safety-guarded `adb` wrapper (allow-list + deny-list + assertions). |
| `uidump.py` | uiautomator XML parser + screen recognition (mailbox rows, reader, keyguard/foreign-app guards). |
| `scenarios.py` | The five scenarios. |
| `report.py` | Aggregates + `timing-tables.md` renderer mirroring the manual write-up. |
| `tests/` | 68 stdlib-`unittest` cases + fixtures (a verbatim perf-extract slice; reader/lockscreen/alarm dumps). |
## Scenarios
`cold-open`, `message-open` (uncached), `back-nav`, `prefetch-ab` (fetch-policy toggle: *Fetch all on Wi-Fi* vs *Always on-demand*), and `cross-provider` (buckets by breadcrumb account ref).
## Device safety (baked in as hard guardrails)
- **Allow-list** of adb subcommands; everything else (uninstall/root/remount/reboot/push/pull) is refused.
- **Deny-list + assertions** on every shell command: no `pm clear` / `pm uninstall`, no reboot/remount/root/verity/factory, **no touching `databases/` `files/` `shared_prefs/` `datastore/`**, no redirects; `run-as` / `am` constrained to the target package.
- The **only** sanctioned app-state mutation is clearing LibreMail''s own **`cache/`** (exact-match). No `pm clear`, uninstall, or data wipe can be constructed.
- Screen kept awake and restored; every uiautomator/input step guarded against the keyguard and foreign apps (a sample against either is skipped, not measured).
## Validated vs. needs the live run
**Validated offline (unit tests, no device):** breadcrumb parsing + correlation reproduce the manual `timing-tables.md` figures exactly (Gmail A1 `took=31227 ms`, `rfc822=60457 B`, `4.2 KB/s`; Outlook O1 `took=2934 ms`, `139.5 KB/s`); the guardrails accept all known-good and refuse all forbidden commands; screen/keyguard recognition; report rendering; and `--dry-run` emits the correct command plan for all five scenarios.
**Needs the first monitored live run:** end-to-end hardware timing capture, and the `prefetch-ab` **settings-screen** navigation (no settings dump existed in the manual run, so `set_fetch_policy` navigates by on-screen option text with a scroll fallback). Per the brief, **auto-merge is intentionally not armed** — the maintainer reviews the tooling and we validate it live together.
## Tests
```
python -m unittest discover -s scripts/device-testing/tests -p "test_*.py"
# Ran 68 tests ... OK
```
Pure Python dev tool (stdlib only, matching the `.claude/skills/preflight/*.py` convention); no Kotlin/app source touched.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
A cross-platform, standard-library-only Python package under
scripts/device-testing/that replicates LibreMail''s on-device performance-test scenarios and logging capture. It codifies the methodology run by hand on 2026-07-05 (Pixel 10 Pro XL) and written up in the perf/causation reports.Package layout
perf_harness.pybreadcrumbs.pyImapPerf/MailReader/Reader/MailBackfillerbreadcrumbs + open-correlation.adb.pyadbwrapper (allow-list + deny-list + assertions).uidump.pyscenarios.pyreport.pytiming-tables.mdrenderer mirroring the manual write-up.tests/unittestcases + fixtures (a verbatim perf-extract slice; reader/lockscreen/alarm dumps).Scenarios
cold-open,message-open(uncached),back-nav,prefetch-ab(fetch-policy toggle: Fetch all on Wi-Fi vs Always on-demand), andcross-provider(buckets by breadcrumb account ref).Device safety (baked in as hard guardrails)
pm clear/pm uninstall, no reboot/remount/root/verity/factory, no touchingdatabases/files/shared_prefs/datastore/, no redirects;run-as/amconstrained to the target package.cache/(exact-match). Nopm clear, uninstall, or data wipe can be constructed.Validated vs. needs the live run
Validated offline (unit tests, no device): breadcrumb parsing + correlation reproduce the manual
timing-tables.mdfigures exactly (Gmail A1took=31227 ms,rfc822=60457 B,4.2 KB/s; Outlook O1took=2934 ms,139.5 KB/s); the guardrails accept all known-good and refuse all forbidden commands; screen/keyguard recognition; report rendering; and--dry-runemits the correct command plan for all five scenarios.Needs the first monitored live run: end-to-end hardware timing capture, and the
prefetch-absettings-screen navigation (no settings dump existed in the manual run, soset_fetch_policynavigates by on-screen option text with a scroll fallback). Per the brief, auto-merge is intentionally not armed — the maintainer reviews the tooling and we validate it live together.Tests
Pure Python dev tool (stdlib only, matching the
.claude/skills/preflight/*.pyconvention); no Kotlin/app source touched.🤖 Generated with Claude Code