Skip to content

iOS simulator smoke lane flaps on text entry (lost/reordered filled prefix, XCTest keyboard wait) — not reproducible locally under load #1844

Description

@thymikee

Summary

On 2026-08-18 the iOS workflow on main went from green on every run through 12:12Z to failing intermittently (fail/pass/fail) with three different text-entry signatures, on commits that do not touch the Apple runner or text entry. A local reproduction of the exact failing sequence under heavy CPU load passed 9/9, so this is filed as a runner-environment / timing flake with evidence, not as a confirmed product defect. No code change is proposed here.

CI signatures (all GitHub macOS runners, IOS_RUNTIME_VERSION: 26.2)

When (UTC) Ref Lane Failure
12:33 main 3908559fe (run 32137419756) Smoke smoke:automation-input AssertionError: step: wait for Agent Device Tester
13:36 main d0d5c8594 (run 32143319393) live iOS simulator fixture E2E, test/integration/ios-simulator-e2e/live-runner.ts:216 typed email suffix should be observable — expected ada@example.test, get attrs id="field-email" returned "value":".test"
~13:50 PR #1826 head a3388f8e3, run 1 (pure TS test move, no runner changes) runner XCTest RunnerTests.testBareTypeUsesTappedInputWhenSoftwareKeyboardIsHidden — runner log spinning on Checking existence of 'Keyboard (First Match)'
~14:05 PR #1826 same head, run 2 fixture E2E same typed email suffix assertion, value adexamplea@.test (filled prefix with characters reordered)
~14:20 PR #1826 same head, run 3 pass

Same commit, three outcomes; main interleaved passes (12:56 60f6356b0, 13:56 9a0d6dead) with the failures.

Scenario under test (assertFormInput): fill email ada@examplekeyboard dismiss (asserted dismissed=true) → snapshot -ifocus <x> <y> on the email field's rect → type '.test' (asserted textEntryRoute: 'synthesized-first-responder') → get attrs id="field-email".

Commits merged between the last green (2b6d04a13, 12:12Z) and the first red: #1818 (daemon-stop claim report, TS), #1808 (Android), #1820 fix(scroll): keep saturated scroll gestures out of the status bar (iOS scroll only). Later that hour: #1827, #1825, #1814 (TS only). Earlier the same day: #1807, #1811, #1816, #1798 (iOS snapshot/runner).

Local reproduction (does NOT reproduce)

iPhone 16 simulator (416440AE-56FE-43D3-9349-D6CE8D1B1895), repo CLI built from main, isolated --state-dir, the fixture app the smoke lane uses, the exact sequence above scripted, with heavy CPU load generators running alongside:

Iteration after fill after keyboard dismiss after coordinate focus + type pass
1–9 ada@example ada@example ada@example.test 9/9

type reported textEntryRoute: synthesized-first-responder in every iteration; keyboard dismiss reported mechanism: dismissKey.

What that rules out / leaves open

  • Rules out (locally): coordinate focus clearing an already-filled field; keyboard dismiss clearing the field; the synthesized type route replacing instead of appending; CPU contention alone dropping/reordering the fill characters.
  • Still open: (a) the runner's software keyboard never appearing / appearing late on the CI image (the XCTest signature and the wait for Agent Device Tester step both point at slow UI on the runner); (b) synthesized-type commit timing under runner-specific latency — see fix(ios): wait for hidden-keyboard synthesized text to commit before responding #1676 (private text synthesize returns at post-time, not commit-time; observation-only commit wait; tail re-post rejected because it double-posts). The adexamplea@ value (reordered, not truncated) is the strongest hint that characters were committed out of order on the runner, which fix(ios): wait for hidden-keyboard synthesized text to commit before responding #1676's observation-only wait would not prevent.

Suggested next step

Capture the runner-side evidence the lane already produces on failure (runner.log + the request ndjson) as workflow artifacts for these two steps, and correlate the per-character post timestamps against the observed value; only then decide whether text entry needs a commit-ordering guarantee. Do not harden the test or add retries (per #1676's lesson).

Repro commands

See test/integration/ios-simulator-e2e/live-runner.ts assertFormInput; locally: pnpm build, boot iPhone 16, open <fixture bundle> --platform ios --udid 416440AE-… --state-dir <tmp>, then fill 'id="field-email"' 'ada@example', keyboard dismiss, snapshot -i, focus <cx> <cy>, type .test, get attrs 'id="field-email"'; run under yes > /dev/null & ×N for load.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions