Skip to content

feat(client): interactions.keyboardDismiss - #1

Merged
thatswiftdev merged 3 commits into
mainfrom
feat/interactions-keyboard-dismiss
Sep 28, 2026
Merged

thatswiftdev merged 3 commits into
mainfrom
feat/interactions-keyboard-dismiss

Conversation

@thatswiftdev

Copy link
Copy Markdown
Owner

What

Adds interactions.keyboardDismiss({ udid }) to the agent-device client — the daemon keyboard dismiss command exposed through the interactions surface.

Why

Lionidas (test-case runner) needs to hide the on-screen keyboard after field fills. The previous approach (tapping a coordinate on the keyboard's Done bar) was device-specific and misfired across logical sizes. The runner's own keyboardDismiss is coordinate-free and works on every device (live-verified on iPhone 16 + iPhone 14 Plus sims).

How

  • TDD: red test first — asserts the daemon request contract (command keyboard, positional dismiss, udid flag); 48/48 in src/__tests__/client.test.ts.
  • Impl is two lines: map to executeCommand('keyboard', { action: 'dismiss', udid }); the command projection maps action → positional.

Downstream

Apple simulators join Android emulators in the boot --headless admission:
cold-booting through the daemon (boot --headless / programmatic
DeviceBootOptions.headless) now skips 'open -a Simulator', so automation
surfaces boot devices without splashing a GUI window over the desktop.

- readiness: AppleReadinessOptions.headless gates showSimulator() on the
  cold-boot path only (warm boots never opened it; default unchanged)
- runtime: bootTargetHeadless admitted where boot is (iOS/iPadOS/tvOS/
  visionOS simulators; macOS has no window, watchOS cannot boot) via
  module-level appleBootHeadlessFact — kept inspectFacts under the
  fallow complexity threshold
- daemon: stale 'Android only' rejection message now names both platforms
- tests: runtime-headless (cold GUI open / headless skip / warm never),
  leaf table gains the headless column, harness fact admits Apple sims,
  the old non-Android rejection test inverted into the admission test
launchArgs / launchConsole / clearAppState change the launch SHAPE — an
open carrying any of them is definitionally a fresh launch, so the old
process (launched under different args) must not survive. Previously
terminateRunningApp was only set for relaunch:true opens; an args-carrying
open against a live process made simctl launch silently no-op (rc=0, same
pid — verified live) and the new args never applied.

Symptom downstream: Crucible's -uitest-live-refresh launch arg was
dropped whenever the app was already running, so the test seam never
armed and world-swap refreshes failed SWAP_NOT_CONFIRMED.

isDirectAppLaunch (already the direct-launch classifier) now also gates
terminateRunningApp. Tests updated to the new invariant: the console-pty
provider scenario expects --terminate-running-process; the
relaunch+clearAppState daemon test expects terminateRunningApp true
(belt-and-braces after its close-first). 2348/2348.
…ismissal

exposes the daemon 'keyboard dismiss' command through the interactions
surface so callers can hide the on-screen keyboard without coordinate
taps (device-independent; routes to the apple runner's dismissal or the
android dismiss-key path per platform).

TDD: red test asserted the daemon request shape (command 'keyboard',
positional 'dismiss', udid flag) before the two-line impl.
@thatswiftdev
thatswiftdev merged commit 0d41aa9 into main Sep 28, 2026
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