Repository navigation
Closed
Labels
Description
Purpose
Every other device-level system input is drivable (home, back, app-switcher, orientation, tv-remote), but the iPhone Action Button is not, so system Shortcut/App Intent delivery — including while the app is backgrounded or terminated — cannot be exercised. Requested in #2655.
API
agent-device action-buttonawait client.command.actionButton();No positional and no flags. Two research findings set this shape:
XCUIDevice.press(_:)(XCUIAutomation, Xcode 16.3+) takes noforDuration:overload, unlike theXCUIRemote.press(_:forDuration:)thattv-remoteuses. Apress|long-pressverb and--duration-mstherefore cannot be honoured for.action, and would ship a flag that is silently ignored.- The Action Button has no slide gesture. Apple's Action Button guide documents exactly one input: "press and hold the Action button". The capacitive surface you slide a finger across is the Camera Control, a separate button exposed as
XCUIDevice.Button.camera, and XCUITest offers no slide/light-press API for either.
So this is shaped like home (device-level, no arguments), not like tv-remote.
Required behavior
- Public
action-buttoncommand descriptor:frameworkTier: 'extended',daemon.route: 'generic',refFrameEffect: 'may-invalidate', the generic mutating traits, andplatformExecution: { kind: 'device-runtime', uses: [actionButtonRuntimeUse] }. - New
actionButtonruntime operation on the ADR 0019 fact path: apackages/contracts/src/action-button-runtime.tsowner module (intent, operations, facts, binder), aRUNTIME_OPERATION_NAMESentry, anINTERACTOR_OPERATIONSrow, an owner-statedactionButtoncell inUnavailablePlatformRuntimeFacts, and an optionalactionButton?(): Promise<void>Interactormember — optional because only Apple can press it. - No
--settleand no post-action observation. The Action Button is expected to deliver to a backgrounded or terminated app, so the press must preserve the app's starting state: the runner must notactivate()the app first, and the command must not re-capture the previously-foreground app. This is what keeps it onhome's trait set rather thanpress'ssettle-and-verify. - Apple fact: available on iOS/iPadOS simulator and physical-device leaves; tvOS, macOS and watchOS refuse at the fact level. Within an admitted leaf, a device without the button refuses on
XCUIDevice.hasHardwareButton(.action)reported as a typed reason — never error-text matching. - Every other platform owner states its own refusal cell (Android, HarmonyOS, web, Vega, Linux, WebDriver, Limrun). The completeness gates make an unstated cell a compile error rather than an assumed default.
Completion conditions
agent-device action-buttonpresses the Action Button on an iPhone simulator and returns{ action: 'action-button', message: … }.- On a device whose model has no Action Button, it fails with a typed unsupported reason and a hint naming the hardware requirement — not a generic transport error.
agent-device action-buttonon Android, web, tvOS, macOS, Vega, Linux and HarmonyOS is refused by fact admission before any runner request is issued.- A press issued while the app is backgrounded does not foreground it, and the response carries no settle or observation payload.
- Node surface
client.command.actionButton()and the MCP tool are present, with the MCP output schema derived fromCommandResultMap. pnpm check:affected --runand the registry, owner-files, and generic-route completeness gates pass.
Dependencies
None. The Camera Control (XCUIDevice.Button.camera) is deliberately out of scope: XCUITest can only click it, and a press-only camera-control command that cannot slide is a separate decision.
Activity
feat(action-button): press the iPhone Action Button
feat(action-button): press the iPhone Action Button (callstack#2702)