Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .fallowrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,28 @@
{
"file": "src/platforms/ios/index.ts",
"exports": ["listSimulatorApps", "uninstallIosApp"]
},
{
"file": "src/platforms/apple/core/apps.ts",
"exports": ["listSimulatorApps", "uninstallIosApp"]
},
{
"file": "src/platforms/apple/core/runner/runner-contract.ts",
"exports": ["resolveRunnerEarlyExitHint"]
},
{
"file": "src/platforms/apple/core/runner/runner-session.ts",
"exports": ["stopAllIosRunnerSessions"]
},
{
"file": "src/platforms/apple/core/runner/runner-xctestrun.ts",
"exports": [
"resolveRunnerBuildDestination",
"resolveRunnerAppBundleId",
"resolveRunnerSigningBuildSettings",
"resolveRunnerBundleBuildSettings",
"assertSafeDerivedCleanup"
]
}
],
"usedClassMembers": ["name", "listActiveLeases", "delete", "values", "elapsedMs", "isExpired"],
Expand Down
10 changes: 0 additions & 10 deletions .github/workflows/ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,6 @@ jobs:
run: |
node --experimental-strip-types src/bin.ts test test/integration/replays/ios/simulator/01-settings.ad --udid "${{ steps.ios-simulator.outputs.simulator-udid }}" --retries 2 --artifacts-dir test/artifacts/replays-ios-simulator-smoke --report-junit test/artifacts/replays-ios-simulator-smoke.junit.xml

# Gate for runner refactors (Phase 3 step c): assert the iOS runner request
# count is unchanged vs. the committed baseline. Runs in its own isolated
# daemon (temp --state-dir) so it never contends with the smoke daemon's
# lease; `clean:daemon` first releases the shared daemon's UDID lease. A
# real count drift fails loudly; an infra hiccup is tolerated (see harness).
- name: Assert iOS runner request count
run: |
pnpm clean:daemon
node --experimental-strip-types scripts/runner-request-count/run.ts --udid "${{ steps.ios-simulator.outputs.simulator-udid }}" --prepare-timeout-ms "$AGENT_DEVICE_IOS_PREPARE_TIMEOUT_MS" --artifacts-dir test/artifacts/runner-request-count

- name: Run iOS physical device smoke replay
if: env.IOS_UDID != ''
env:
Expand Down
15 changes: 13 additions & 2 deletions docs/adr/0009-apple-platform-consolidation.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,16 @@ preserved). The tvOS focus-only interaction contract (no coordinate `tap`) must
and snapshot fidelity is uneven (the deep-RN AX-server fallback is iOS-simulator-only). The final
`Platform` collapse of `ios`+`macos` into `apple` is the last, highest-diff step.

This composes with ADR 0008 (the descriptor's capability facet) and ADR 0003. The phased sequencing and
per-OS readiness live in `plans/apple-platform-consolidation.md`; this ADR owns the decision.
This composes with ADR 0008 (the descriptor's capability facet) and ADR 0003.

Implementation status as of 2026-06:

- Shipped: additive `appleOs` groundwork, the shared Apple engine under `src/platforms/apple/core`, macOS leaf
files under `src/platforms/apple/os/macos`, direct internal imports to the Apple modules, and visionOS
profile/build/discovery groundwork.
- Deferred: the public `Platform` collapse from `ios`/`macos` to `apple`, a dedicated tvOS leaf, per-`AppleOS`
capability tables, and any watchOS unsupported sentinel. watchOS remains out of scope for the current
consolidation.

This ADR owns the architectural decision; implementation progress for the remaining platform-plugin work lives
in `plans/phase3-platform-plugin-progress.md`.
20 changes: 10 additions & 10 deletions fallow-baselines/health.json
Original file line number Diff line number Diff line change
Expand Up @@ -434,15 +434,15 @@
"count": 1
}
},
"src/platforms/ios/apps.ts": {
"src/platforms/apple/core/apps.ts": {
"complexity_high": {
"count": 1
},
"crap_moderate": {
"count": 2
}
},
"src/platforms/ios/devices.ts": {
"src/platforms/apple/core/devices.ts": {
"crap_moderate": {
"count": 1
}
Expand All @@ -455,43 +455,43 @@
"count": 1
}
},
"src/platforms/ios/macos-helper.ts": {
"src/platforms/apple/os/macos/helper.ts": {
"crap_high": {
"count": 1
}
},
"src/platforms/ios/perf.ts": {
"src/platforms/apple/core/perf.ts": {
"complexity_high": {
"count": 1
},
"crap_high": {
"count": 1
}
},
"src/platforms/ios/runner-transport.ts": {
"src/platforms/apple/core/runner/runner-transport.ts": {
"crap_high": {
"count": 1
}
},
"src/platforms/ios/runner-xctestrun.ts": {
"src/platforms/apple/core/runner/runner-xctestrun.ts": {
"complexity_moderate": {
"count": 1
}
},
"src/platforms/ios/screenshot-status-bar.ts": {
"src/platforms/apple/core/screenshot-status-bar.ts": {
"complexity_moderate": {
"count": 1
},
"crap_moderate": {
"count": 2
}
},
"src/platforms/ios/screenshot.ts": {
"src/platforms/apple/core/screenshot.ts": {
"complexity_moderate": {
"count": 1
}
},
"src/platforms/ios/simulator.ts": {
"src/platforms/apple/core/simulator.ts": {
"crap_moderate": {
"count": 1
}
Expand Down Expand Up @@ -701,7 +701,7 @@
"src/cli/commands/connection-runtime.ts:complexity",
"src/daemon/context.ts:high impact",
"src/utils/success-text.ts:high impact",
"src/platforms/ios/apps.ts:complexity",
"src/platforms/apple/core/apps.ts:complexity",
"src/compat/maestro/runtime-targets.ts:high impact",
"src/utils/timeouts.ts:high impact",
"src/replay/script-utils.ts:high impact",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,8 @@
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator";
TARGETED_DEVICE_FAMILY = "1,2,3";
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator xros xrsimulator";
TARGETED_DEVICE_FAMILY = "1,2,3,7";
TVOS_DEPLOYMENT_TARGET = 15.6;
};
name = Debug;
Expand Down Expand Up @@ -387,8 +387,8 @@
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator";
TARGETED_DEVICE_FAMILY = "1,2,3";
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator xros xrsimulator";
TARGETED_DEVICE_FAMILY = "1,2,3,7";
TVOS_DEPLOYMENT_TARGET = 15.6;
};
name = Release;
Expand All @@ -412,8 +412,8 @@
SWIFT_OBJC_BRIDGING_HEADER = "AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h";
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator";
TARGETED_DEVICE_FAMILY = "1,2,3";
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator xros xrsimulator";
TARGETED_DEVICE_FAMILY = "1,2,3,7";
TVOS_DEPLOYMENT_TARGET = 15.6;
TEST_TARGET_NAME = AgentDeviceRunner;
};
Expand All @@ -438,8 +438,8 @@
SWIFT_OBJC_BRIDGING_HEADER = "AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h";
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 5.0;
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator";
TARGETED_DEVICE_FAMILY = "1,2,3";
SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator xros xrsimulator";
TARGETED_DEVICE_FAMILY = "1,2,3,7";
TVOS_DEPLOYMENT_TARGET = 15.6;
TEST_TARGET_NAME = AgentDeviceRunner;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,31 @@ - (void)viewDidLoad {

@end

#if defined(TARGET_OS_VISION) && TARGET_OS_VISION
@interface AgentDeviceRunnerSceneDelegate : UIResponder <UIWindowSceneDelegate>
@property(nonatomic, strong) UIWindow *window;
@end

@implementation AgentDeviceRunnerSceneDelegate

- (void)scene:(UIScene *)scene
willConnectToSession:(UISceneSession *)session
options:(UISceneConnectionOptions *)connectionOptions {
(void)session;
(void)connectionOptions;

if (![scene isKindOfClass:UIWindowScene.class]) {
return;
}

self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
self.window.rootViewController = [[AgentDeviceRunnerViewController alloc] init];
[self.window makeKeyAndVisible];
}

@end
#endif

@interface AgentDeviceRunnerAppDelegate : UIResponder <UIApplicationDelegate>
@property(nonatomic, strong) UIWindow *window;
@end
Expand All @@ -93,13 +118,33 @@ - (BOOL)application:(UIApplication *)application
(void)application;
(void)launchOptions;

#if defined(TARGET_OS_VISION) && TARGET_OS_VISION
return YES;
#else
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
self.window.rootViewController = [[AgentDeviceRunnerViewController alloc] init];
[self.window makeKeyAndVisible];

return YES;
#endif
}

#if defined(TARGET_OS_VISION) && TARGET_OS_VISION
- (UISceneConfiguration *)application:(UIApplication *)application
configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession
options:(UISceneConnectionOptions *)options {
(void)application;
(void)connectingSceneSession;
(void)options;

UISceneConfiguration *configuration =
[[UISceneConfiguration alloc] initWithName:@"Default Configuration"
sessionRole:UIWindowSceneSessionRoleApplication];
configuration.delegateClass = AgentDeviceRunnerSceneDelegate.class;
return configuration;
}
#endif

@end

int main(int argc, char *argv[]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ extension RunnerTests {
}

func rotateDevice(to orientationName: String) -> Bool {
#if os(macOS) || os(tvOS)
#if os(macOS) || os(tvOS) || os(visionOS)
return false
#else
switch orientationName {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,16 @@
"clean:xcuitest:ios": "node scripts/clean-xcuitest-derived.mjs ios",
"clean:xcuitest:macos": "node scripts/clean-xcuitest-derived.mjs macos",
"clean:xcuitest:tvos": "node scripts/clean-xcuitest-derived.mjs tvos",
"clean:xcuitest:visionos": "node scripts/clean-xcuitest-derived.mjs visionos",
"build:node": "pnpm build && pnpm clean:daemon",
"build:xcuitest": "pnpm build:xcuitest:ios && pnpm build:xcuitest:macos",
"build:xcuitest:ios": "AGENT_DEVICE_XCUITEST_PLATFORM=ios sh ./scripts/build-xcuitest-apple.sh",
"build:xcuitest:ios:clean": "pnpm clean:xcuitest:ios && pnpm build:xcuitest:ios",
"build:xcuitest:macos": "AGENT_DEVICE_XCUITEST_PLATFORM=macos sh ./scripts/build-xcuitest-apple.sh",
"build:xcuitest:tvos": "AGENT_DEVICE_XCUITEST_PLATFORM=tvos sh ./scripts/build-xcuitest-apple.sh",
"build:xcuitest:tvos:clean": "pnpm clean:xcuitest:tvos && pnpm build:xcuitest:tvos",
"build:xcuitest:visionos": "AGENT_DEVICE_XCUITEST_PLATFORM=visionos sh ./scripts/build-xcuitest-apple.sh",
"build:xcuitest:visionos:clean": "pnpm clean:xcuitest:visionos && pnpm build:xcuitest:visionos",
"build:android-snapshot-helper": "sh ./scripts/build-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") .tmp/android-snapshot-helper",
"package:android-snapshot-helper": "sh ./scripts/package-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") v$(node -p \"require('./package.json').version\") .tmp/android-snapshot-helper",
"package:android-snapshot-helper:npm": "rm -rf android-snapshot-helper/dist && sh ./scripts/package-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") v$(node -p \"require('./package.json').version\") android-snapshot-helper/dist",
Expand All @@ -98,7 +101,6 @@
"perf": "node --experimental-strip-types scripts/perf/run.ts",
"perf:ios": "node --experimental-strip-types scripts/perf/run.ts --platform ios",
"perf:android": "node --experimental-strip-types scripts/perf/run.ts --platform android",
"validate:runner-count": "node --experimental-strip-types scripts/runner-request-count/run.ts",
"lint": "oxlint . --deny-warnings",
"format": "node ./node_modules/oxfmt/bin/oxfmt --write src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
"format:check": "node ./node_modules/oxfmt/bin/oxfmt --check src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
Expand Down
Loading
Loading