Skip to content

fix(apple): carry the runner's sparse verdict through a viewport refusal - #2572

Merged
thymikee merged 2 commits into
mainfrom
fix/ios-sparse-capture-verdict-diagnosis
Sep 14, 2026
Merged

fix(apple): carry the runner's sparse verdict through a viewport refusal#2572
thymikee merged 2 commits into
mainfrom
fix/ios-sparse-capture-verdict-diagnosis

Conversation

@thymikee

Copy link
Copy Markdown
Member

Summary

A capture that no backend could read failed with an internal engine invariant — regular iOS snapshot presentation requires a valid viewport — naming neither the backend that was asked nor the screen that defeated it. The runner already declares such a payload sparse (backend, reasonCode, its own reason); the daemon read that verdict and then discarded it while reconstructing a viewport from the synthetic root every sparse payload carries.

The refusal now carries error.details.snapshotQuality, and the hint composes the shared sparse-capture advice with the presented surface host. replay/test keep the verdict in REPLAY_DIVERGENCE details instead of truncating to four cause keys. Same command over an ASWebAuthenticationSession sheet, before: details { reason: "invalid-viewport", field: "viewport" } plus a generic hint. After: the same message, plus snapshotQuality: { state: "sparse", backend: "private-ax", reasonCode: "requested-backend", reason: "the private AX backend was selected because this capture asked for accessibility custom actions" } and a hint naming com.apple.SafariViewService.

Refs #2560 — diagnosis, not the flow fix. That flow still fails on this surface until the capture plan stops routing presented out-of-process surfaces to private AX, which ADR 0004 already diagnosed for #2403; that capability declaration is the follow-up. Six files.

Validation

Commit c37e17d3f7: pnpm check:affected --run passed (1874 tests); check:quick, check:layering, check:daemon-wire-compat passed.

Live: iPhone 17 Pro simulators on iOS 26.2 and iOS 18.6, UIKit app presenting ASWebAuthenticationSession, driven by this checkout's CLI — plain snapshot stayed healthy (35 nodes, backend: tree), snapshot --actions produced the quoted pair before and after the change. Manual sessions closed, created simulators deleted.

Unresolved risk: whether the reporter's run armed the XCTest-channel penalty needs their runner log (SNAPSHOT_XCTEST_CHANNEL_PENALIZED / _DEFERRED).

A payload the runner declared sparse carries the backend, reason code, and reason that explain it, yet the daemon dropped all of it while reconstructing a viewport from the synthetic root that sparse payloads always carry. Callers saw only an internal engine invariant. The verdict now travels as error.details.snapshotQuality and the hint composes the shared sparse-capture advice with the presented surface host.
The replay failure wrapper rebuilds cause details from a four-key allowlist, so the verdict a device-facing capture produced could not reach the agent that replayed the step.
@github-actions

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
Installed (including dependencies) 4.52 MB 4.52 MB +540 B
Package (unpacked) 4.52 MB 4.52 MB +540 B
Package (download) 1.33 MB 1.33 MB +398 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 23.0 ms 22.5 ms -0.4 ms
CLI --help 61.3 ms 63.3 ms +2.0 ms

@thymikee

Copy link
Copy Markdown
Member Author

No code findings at c37e17d. The runner’s sparse verdict survives presentation refusal and replay error wrapping, with reported live evidence on two iOS versions. The remaining smoke failure is the same automation-longpress scroll assertion seen on #2565 before its successful retry, so it appears unrelated; rerun that check before merge. Ready for human review.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Sep 13, 2026
@thymikee
thymikee merged commit 508b750 into main Sep 14, 2026
17 of 18 checks passed
@thymikee
thymikee deleted the fix/ios-sparse-capture-verdict-diagnosis branch September 14, 2026 09:34
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-09-14 09:34 UTC

thymikee added a commit that referenced this pull request Sep 14, 2026
…name system surfaces in refusals

An optional: true Maestro step that skipped stayed a warning that the
terminal never printed once a later step failed: the accumulated channel
rode only on the success response, so the repro run in #2560 reported a
bare failure with no trace of the skip. The engine now emits warnings on
the failure event, the daemon copies them onto the failure response's
error details, and the failed test result carries the same array the
passed result already had; replay prints them through its facet formatter
and the test reporter adds a Warnings section that renders whether tests
pass or fail.

A regular iOS presentation refusal from the runner now also carries the
registry identity of the system surface the tree was acquired from in
error details, so a capture-boundary miss under optional: true stops
looking like a selector problem; the sparse-declared verdict path is
owned by #2572.
thymikee added a commit that referenced this pull request Sep 14, 2026
…name system surfaces in refusals

An optional: true Maestro step that skipped stayed a warning that the
terminal never printed once a later step failed: the accumulated channel
rode only on the success response, so the repro run in #2560 reported a
bare failure with no trace of the skip. The engine now emits warnings on
the failure event, the daemon copies them onto the failure response's
error details, and the failed test result carries the same array the
passed result already had; replay prints them through its facet formatter
and the test reporter adds a Warnings section that renders whether tests
pass or fail.

A regular iOS presentation refusal from the runner now also carries the
registry identity of the system surface the tree was acquired from in
error details, so a capture-boundary miss under optional: true stops
looking like a selector problem; the sparse-declared verdict path is
owned by #2572.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant