Skip to content

fix(validation): pre-grant POST_NOTIFICATIONS before Android Stage 1 capture#78

Merged
dadachi merged 1 commit into
mainfrom
fix/android-stage1-notification-permission
May 22, 2026
Merged

fix(validation): pre-grant POST_NOTIFICATIONS before Android Stage 1 capture#78
dadachi merged 1 commit into
mainfrom
fix/android-stage1-notification-permission

Conversation

@dadachi
Copy link
Copy Markdown
Contributor

@dadachi dadachi commented May 22, 2026

Problem

On Android 13+ (API 33+) the POST_NOTIFICATIONS runtime-permission dialog fires on first launch. It overlays the home screen at exactly the moment Stage 1 captures its screenshot, so the Layer 3 vision judge fails renders-cleanly on an otherwise-correct build — a false negative that fails the entire run.

Found while generating a real validation-report.html from an actual vet-clinic-queue run: Layer 1 3/3, Layer 2 3/3, reviewer PASS, but Layer 3 1/2 with the Android judge rationale:

The "Welcome to …" text behind the modal overlaps/collides with the modal dialog, and the "Start" button appears cut off at the right edge.

Fix

Insert a best-effort adb shell pm grant <pkg> android.permission.POST_NOTIFICATIONS between install and the monkey launch in installAndLaunchAndroid, so the dialog never appears.

Best-effort by design: on older API levels (where it isn't a runtime permission) or apps that don't declare it, pm grant errors — the result is ignored so it never blocks the launch. The generated app declares the permission (push notifications), and the CI emulator is API 33+, so the grant applies.

Verification

Re-ran the full three-platform pipeline (NATIVEAPPTEMPLATE_VISUAL=1) against a booted iPhone 17 Pro + Android emulator:

before after
Android Layer 3 renders-cleanly ❌ FAIL (modal overlay) ✅ PASS (clean home capture)
Overall FAIL (Layer 3 1/2) PASS (Layer 3 2/2)

iOS Layer 3 unaffected (still 2/2). npm run build, npm run typecheck:tests, and npm test (49/49) all green locally.

Scope

Agent code only — one function in src/validation/launch.ts (+ its header comment). No substrate changes.

🤖 Generated with Claude Code

…capture

Android 13+ (API 33+) pops the POST_NOTIFICATIONS runtime-permission
dialog on first launch. It overlays the home screen exactly when Stage 1
grabs its screenshot, so Layer 3's "renders-cleanly" rubric fails on an
otherwise-correct build — a false negative that fails the whole run.

Insert a best-effort `adb shell pm grant <pkg> POST_NOTIFICATIONS`
between install and launch so the dialog never appears. Best-effort: on
older API levels (where it isn't a runtime permission) or apps that don't
declare it, `pm grant` errors and we ignore the result, so it never
blocks the launch.

Verified end-to-end: a real vet-clinic-queue run that was Layer 3 1/2
(Android renders-cleanly FAIL, modal over the welcome screen) now passes
Layer 3 2/2 with a clean Android home capture — overall PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dadachi dadachi merged commit b59c1a7 into main May 22, 2026
1 check passed
@dadachi dadachi deleted the fix/android-stage1-notification-permission branch May 22, 2026 11:35
dadachi added a commit that referenced this pull request May 23, 2026
… walk (#88)

A real VISUAL=2 run surfaced two iOS system dialogs blocking Stage 2 (an
iOS system alert makes the accessibility tree return ONLY the alert's
elements, hiding the app — so the next wait_for_text saw "5 elements" and
timed out):

- Keychain "Save password?" appears LATE — after the rails_runner email
  confirm, not at signup — re-covering the auth screen before the Sign-In
  tap. Dismiss it again right before tapping Sign In (was only dismissed at
  signup time). This took iOS Stage 2 from 21/22 to 35/36.
- Notification permission ("通知を送信します") pops when the list loads,
  hiding the "Sample" entry. Dismiss it before the Sample wait. Push is
  paid-only, so the step is optional and no-ops on free / Android (which
  pre-grants POST_NOTIFICATIONS, #78).

Both dismissals are optional with JP+EN labels (exact, so "許可" doesn't
match "許可しない"). Also drop the now-unused `primaryName` local.

Note: Stage 1/Stage 2 capture is still flaky run-to-run (timing/vision
variance) — a separate stability pass; this PR is the validated scenario
content fix.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant