storebound/skills/store-health/SKILL.md
CRT b63f2fdfbc Store operations: TestFlight wait / expire, IAP review submissions, listing pulls, release notes per language, offers, custom product pages, in-app events, reports, triage, keyword ranks, AdAttributionKit scan
- apple testflight wait --build N (progress, timeout, exit 0/1/7) and expire --keep N | --older-than D (dry run, asks)
- apple iap-submit: IAP / subscription / group versions into a review submission; first of a type only with the app
  version (--with-version), --no-submit keeps the draft; read-only MCP plan
- apple listing pull, play listing pull (diff, --write), catalog pull (config proposal, never rewritten)
- whats-new --languages / check / apply: one file per language, agent or hook translation, per-store limits
- apple offer-codes, win-back, promoted, preorder; Play pre-registration as a guide (no API)
- apple cpp and apple events: list, create, upload, submit (asks)
- reports: Apple sales / finance, Play earnings / sales into .storebound/reports with summary and CSV
- triage: TestFlight crash / feedback and Play error reports grouped by signature, device, OS
- aso rank: iTunes Search API ranks and competitors, rate limited
- ads scan: AdAttributionKit / SKAdNetwork Info.plist and source checks
- tests against recorded, sanitized answers; skills, README, CHANGELOG
2026-10-11 23:58:17 +08:00

62 lines
4.9 KiB
Markdown

---
name: store-health
description: Watch a released mobile app's or game's crash and ANR health on both stores - Google Play Android vitals (user-perceived crash rate 1.09 % and ANR rate 0.47 % bad behavior thresholds, 8 % per device model) through the Play Developer Reporting API, App Store power and performance metrics, diagnostic signatures and TestFlight crash reports, crash and feedback triage grouped by signature, device and OS version, a weekly Markdown report, and validate blockers when a threshold is crossed. Use when the user asks about crashes, ANRs, vitals, stability, a weekly health check, or why Play shows a quality warning.
---
# Store health (crashes, ANRs, diagnostics)
CLI: `storebound health` (read-only, both stores; `--apple` / `--play`, `--days 7`), `storebound health --weekly`
(also writes `.storebound/health/<date>.md` and `<date>.json`; the next week compares against it; `--dry` prints
instead). `storebound validate` runs the same checks for live apps. MCP: `health` (read-only), `health_report`.
## Setup (once)
- **Google Play**: enable the **Google Play Developer Reporting API** in the Google Cloud project of the service
account (Cloud Console > APIs & Services > Library). In Play Console > Users and permissions, the service account
needs **View app information (read-only)** for the app. Scope used: `playdeveloperreporting`. Reference:
https://developers.google.com/play/developer/reporting/reference/rest
- **App Store**: the API key that storebound already uses (Admin, App Manager or Developer role reads metrics).
Metrics come from users who share analytics with developers; small apps may show none.
## Read the numbers
- **Play bad behavior thresholds** (28-day average, user-perceived, checked daily; sources:
https://developer.android.com/topic/performance/vitals and Play Console Help answer 9844486):
user-perceived crash rate **1.09 %**, user-perceived ANR rate **0.47 %**, and **8 %** on any single phone model.
Over a threshold, Play can lower the app's visibility and show a warning on its store listing. storebound marks
over = blocker, from 80 % of a threshold = warn.
- Daily values swing on small user counts; the 28-day user-weighted rate is what Play judges. Device rows with fewer
than 500 users are ignored.
- **App Store**: Apple publishes no thresholds. storebound warns on metrics Apple itself rates `poor` (hang rate,
launch time, memory, disk writes, battery) and on diagnostic signatures with a large share of reports (Xcode >
Organizer shows the stack traces). TestFlight crash reports count crashes testers sent from the beta.
## Triage: which crash first
`storebound triage [--days 14] [--build N] [--apple | --play] [--json]` (MCP: `triage`, read-only) groups what testers
and players hit:
- **TestFlight crashes**: every crash report's log is read and turned into a signature (exception type + the first
frame of the crashed thread inside the app; text and `.ips` crash formats), then grouped with its top device models,
OS versions and builds.
- **TestFlight screenshot feedback**: grouped by device; `--comments 3` shows up to three comments per group (cut to 120
characters). Tester emails are never requested (the reads list their fields without `email` / `tester`).
- **Google Play**: the top `--issues` (default 10) crash / ANR issues of the window (Play's own clusters), then their
error reports for the spread by device (marketing name), API level and versionCode. Counts are of the sampled
reports; the issue's total reports and users come from Play.
Fix the top signature first, then check its device / OS column: one model or one OS version points at a device bug.
## Act on it
1. Start with the top issues table (Play: cause + location + versionCode; Apple: signature + build), or with
`storebound triage` for the grouped view.
2. Reproduce on the named device model / OS; for ANRs look for main-thread work (I/O, ads SDK init, big asset
loads), for crashes the null / out-of-memory paths.
3. Ship the fix with a higher versionCode / build number (release-management skill). Halting a rollout stops new
installs but is not a rollback.
4. Next week: `storebound health --weekly` shows the change in percentage points next to last week.
## Gotchas
- `vitals not readable`: the API is not enabled, the service account lacks the permission, or the app has no release
yet. `validate` only notes it; `storebound health` warns.
- storebound reads the Reporting API rates as fractions (0.0109 = 1.09 %). The API reference calls them a
"percentage of distinct users" without stating the scale (not verified against a live response yet): the first
time, compare one number with Play Console > Android vitals and report a mismatch.
- Never share crash logs that contain user data outside the team; never paste tester emails from TestFlight crash
reports into chats or issues.
- Nothing here changes the store: it is safe to run any time.