Skip to content

fix: preserve clear state before iOS launch URLs - #1486

Merged
thymikee merged 3 commits into
mainfrom
agent/preserve-ios-clear-state-url-launch
Jul 29, 2026
Merged

fix: preserve clear state before iOS launch URLs#1486
thymikee merged 3 commits into
mainfrom
agent/preserve-ios-clear-state-url-launch

Conversation

@thymikee

@thymikee thymikee commented Jul 29, 2026

Copy link
Copy Markdown
Member

Summary

Preserve clearAppState on the direct iOS app launch before applying a stored runtime launch URL, and strip app-only flags from the follow-up URL dispatch.

Remove the unreachable direct deep-link relaunch branch, reuse the local simulator lifecycle predicate, and replace duplicated iOS test fixtures. Fix the CI-observed keyboard-dismissal race by waiting a bounded interval for the tapped native keyboard control to take effect, then observing current keyboard state. The keyboard behavior now lives in a focused runner module instead of further growing the interaction module.

Scope spans twelve files across the session-open / Apple lifecycle path, iOS live smoke coverage, and the Apple runner's keyboard boundary.

Validation

  • pnpm format:check && pnpm typecheck && pnpm lint
  • pnpm check:fallow
  • Focused serial regression suites: 286 passed
  • pnpm build:xcuitest: iOS and macOS runner builds passed
  • Live iOS simulator fixture E2E on iPhone 17 Pro with the rebuilt runner: 11 passed
  • Full pnpm check tooling/build/Fallow gates passed; its parallel unit fan-out hit documented host contention, and all 13 failed tests passed in their six files when rerun serially (224 passed)
  • Exact-head CI passed for 6d7f48f92, including the 15-minute iOS smoke lane

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 1.87 MB 1.87 MB -79 B
JS gzip 602.9 kB 602.9 kB -25 B
npm tarball 720.7 kB 720.9 kB +200 B
npm unpacked 2.52 MB 2.52 MB +157 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 26.5 ms 25.9 ms -0.6 ms
CLI --help 70.5 ms 55.5 ms -15.0 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/apps.js -64 B -17 B
dist/src/session.js -15 B -8 B

@thymikee

Copy link
Copy Markdown
Member Author

Review at 68428e4: code path is sound and CI is green, but one required device-evidence gap remains.

The fix correctly forces the app-only launch before the stored URL when clearAppState is set, then strips app-only flags from the URL dispatch. However, the reported iOS fixture run does not exercise that combination: the live URL scenario uses relaunch without clear state, while clear-state coverage opens the app without a stored launch URL. The new handler test mocks dispatch, so it cannot prove data clear -> launch -> URL delivery on a simulator.

Add one real simulator fixture journey through launchApp(clearState: true) with a stored launch URL, asserting both reset-state evidence and the deep-link destination. No ready-for-human until that exact path is proven.

@thymikee

thymikee commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Addressed in fb68ca9ca.

Added a real iOS simulator fixture journey through the public Maestro launchApp(clearState: true) path with the session's stored launch URL. The journey:

  • seeds a canary in the fixture's real data container,
  • replays launchApp(clearState: true) through the existing session-owned daemon,
  • proves the canary was removed,
  • asserts the exact Automation lab destination, cold.start event, and {"source":"deep-link"} payload,
  • then navigates onward to the catalog.

Device validation: iPhone 17 Pro simulator (C25DBB5B-9254-4293-A8D5-2785C78DE03A), live smoke + coverage 11/11 passed in 99.45s. Artifacts: test/artifacts/ios-simulator/smoke/1785334840163-53419.

Pre-push format, typecheck, lint, and coverage gates also pass.

@thymikee

Copy link
Copy Markdown
Member Author

Exact-head code review is clean. The real Maestro launchApp(clearState) route now preserves clearing on the direct iOS app launch, strips app-only flags from the follow-up URL dispatch, and the live regression is non-vacuous: it seeds the actual data container, runs public replay, requires the canary to disappear, and verifies the deep-link payload. The exact-head iOS job progressed beyond this scenario, so the new journey passed.

Readiness is held by the later failed iOS keyboard-dismiss step (UNSUPPORTED_OPERATION in smoke:form-input), not by the changed journey. Rerun it and investigate fixture isolation if it repeats; no ready-for-human label while the required check is red. Also update the PR body’s stale six-file scope count to the current ten files and record the live journey/current CI state.

@thymikee

Copy link
Copy Markdown
Member Author

Addressed the readiness feedback and investigated the failing iOS job from its uploaded runner artifacts.

The failure was not fixture isolation and the runner did find a safe native dismiss control. runner.log shows XCTest finding and tapping the "Done" Button, then immediately sampling Keyboard once and returning UNSUPPORTED_OPERATION. The fixed sleepFor(0.2) plus one observation was a race with the keyboard transition on the slower CI host.

The runner now captures the visible keyboard, taps the same allowlisted native control, waits up to two seconds for that keyboard to disappear, and then reads current keyboard visibility. The fresh final read means a replacement keyboard still correctly reports failure; there is no navigation fallback, retry tap, or relaxed success condition.

I also extracted the keyboard helpers from the already oversized RunnerTests+Interaction.swift into RunnerTests+Keyboard.swift, keeping the change aligned with the runner's existing responsibility-oriented file structure.

Validation on the exact fix:

  • rebuilt iOS and macOS XCTest runners
  • ran the full fixture-backed iOS simulator smoke on iPhone 17 Pro: 11/11 passed, including the clear-state/deep-link journey followed by form input and keyboard dismissal
  • final serial regression set: 286/286 passed
  • formatting, typechecking, lint, build, and Fallow are clean
  • the aggregate parallel unit fan-out reproduced documented host contention; all 13 failures passed serially in their six owning files (224/224)

The PR body now reflects the current twelve-file scope and validation. Exact-head CI is running for 6d7f48f92.

@thymikee

Copy link
Copy Markdown
Member Author

Reviewed exact head 6d7f48f9: no code findings. The keyboard change replaces the fixed post-tap delay with a bounded observation of the actual keyboard element, and the real production route still reports failure if the keyboard remains or reappears. The extracted Swift module is compiled by the synchronized Xcode group; exact-head runner compilation and the static/core gates are green. The live regression is non-vacuous: it drives public keyboard dismiss, asserts dismissed: true / visible: false, compares before/after screenshots, and the same fixture run proves clear-state URL launch by deleting a seeded container canary and checking the destination payload. GitHub’s exact-head iOS smoke is still in progress, but there is no confirmed failing CI. Ready for human review.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Jul 29, 2026
@thymikee
thymikee merged commit 9e75eab into main Jul 29, 2026
30 checks passed
@thymikee
thymikee deleted the agent/preserve-ios-clear-state-url-launch branch July 29, 2026 16:20
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-29 16:20 UTC

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