Skip to content

fix(ios): prevent stale post-gesture snapshot acceptance - #1573

Draft
thymikee wants to merge 1 commit into
mainfrom
agent/fix-post-gesture-stale-accept-1569
Draft

fix(ios): prevent stale post-gesture snapshot acceptance#1573
thymikee wants to merge 1 commit into
mainfrom
agent/fix-post-gesture-stale-accept-1569

Conversation

@thymikee

@thymikee thymikee commented Aug 3, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #1569.

Post-gesture stabilization could accept a baseline-matching XCTest tree after only about six slow captures because the distrust deadline was wall-clock based. Under contention, that left stale checkout geometry in session state.

  • Use a fixed 12-observation distrust budget plus a separate 15-second hard ceiling.
  • After the first quiet baseline match, explicitly request an independent snapshot backend for subsequent Apple captures. On iOS simulators this runs private AX before XCTest tree/query tiers; ordinary snapshots remain tree-first and physical devices retain their existing behavior.
  • Thread the preference through daemon dispatch and runner contracts, with diagnostics and focused regression coverage.

This addresses both observed causes: slow capture latency no longer reduces the evidence collected, and the runner no longer repeatedly trusts the same XCTest channel when it is the suspected stale source.

Validation

  • Counterfactual red: the old implementation accepted after 6 simulated 500 ms captures; the regression requires at least 12.
  • pnpm check:affected --run passed; 3,617 tests, 100% changed-line coverage, 88.89% changed-branch coverage.
  • pnpm build:xcuitest:ios passed with TEST BUILD SUCCEEDED.
  • Typecheck, format, lint, layering, fallow, and build passed.
  • The focused native XCTest selector discovered 0 tests; the full RunnerTests class is a long-lived listener, so native validation was limited to the successful runner build. GitHub Swift runner jobs remain authoritative.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 1.96 MB 1.95 MB -6.1 kB
JS gzip 626.6 kB 625.0 kB -1.6 kB
npm tarball 746.3 kB 745.1 kB -1.2 kB
npm unpacked 2.61 MB 2.61 MB -4.4 kB

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 24.5 ms 24.8 ms +0.3 ms
CLI --help 61.8 ms 60.0 ms -1.8 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/session.js -6.1 kB -1.7 kB
dist/src/internal/daemon.js +644 B +208 B
dist/src/screenshot-result.js -195 B -35 B
dist/src/viewport-dimension.js +190 B +32 B
dist/src/context.js +54 B +27 B

@thymikee

thymikee commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

Reviewed exact head 2aba9e5366b58540828eb660528bae77458ae69a.

P1 — the new runner regression is not executed by CI. testEffectiveSnapshotCapturePlanPrefersIndependentBackendForFreshnessProbe is the only runner-level assertion that the new preference moves private AX ahead of XCTest, but .github/workflows/ios.yml runs a fixed -only-testing selector list that omits it. The green TypeScript coverage verifies orchestration and command forwarding, not the native backend plan. Add this test selector (or equivalent runner-level coverage) to the gated XCTest run and execute it.

The implementation otherwise follows the intended post-gesture → snapshot preference → Apple runner route while leaving ordinary/raw snapshots and physical-device ordering unchanged. Before readiness, also rebase/resync onto current main and provide exact-head live simulator evidence for the stale-checkout case, including the independent-backend-preferred log and a healthy latency/control run. The current iOS smoke does not force this path. No ready-for-human label until the gate and evidence are updated.

Residual risk: no separately authorized cross-vendor review was run.

@thymikee

thymikee commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

CI follow-up at the same head: the failed iOS smoke is not on this PR’s changed production route, but it still needs an owner-action rerun before readiness. The failure is a 90s alert get daemon timeout after the deep-link destination wait; that scenario has not performed a gesture, so post-gesture stabilization and the independent snapshot preference cannot fire. Re-run iOS smoke on this SHA; if it repeats, compare on current main and investigate the alert/deep-link system-modal path separately. The uploaded artifact does not include the referenced daemon NDJSON, so this run alone is insufficient to call it an infrastructure flake.

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.

Post-gesture stale-accept saturates routinely on the checkout screen; wall-clock retry budget starves under contention into stale-geometry interactions

1 participant