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
220 changes: 219 additions & 1 deletion .fallowrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,227 @@
},
{
"comment": "Apple perf sampling metadata is selected through the same lazy platform host; Fallow cannot follow the dynamic property read in src/platform-runtime-perf-host.ts.",
"file": "src/platforms/apple/core/perf.ts",
"file": "packages/platform-apple/src/core/perf.ts",
"exports": ["buildAppleFrameSamplingMetadata", "buildAppleMemorySamplingMetadata"]
},
{
"comment": "These host-process helpers are consumed only by integration leak-oracle support and host-process unit tests; Fallow's production graph intentionally excludes both consumers.",
"file": "packages/host-kit/src/process.ts",
"exports": ["uniquePositivePids", "readOwnedProcessRecordFile"]
},
{
"comment": "Apple app-resolution helpers are reached through the named lazy façade in packages/platform-apple/src/app-resolution-facade.ts. Fallow cannot connect dynamic import member reads to these source exports; keep this list limited to the facade's re-exports.",
"file": "packages/platform-apple/src/core/app-resolution.ts",
"exports": ["buildAppNotInstalledError", "resolveIosAppAlias"]
},
{
"comment": "The app-resolution package facade is consumed through workspace package exports. Fallow does not follow that package boundary, so keep only its externally consumed helper that has no visible production edge here.",
"file": "packages/platform-apple/src/app-resolution-facade.ts",
"exports": ["buildAppNotInstalledError"]
},
{
"comment": "The legacy push helper remains a package-root operation reached through a dynamic import; Fallow cannot connect that root wrapper to this source export.",
"file": "packages/platform-apple/src/core/app-device-io.ts",
"exports": ["pushIosNotification"]
},
{
"comment": "The lifecycle package facade is consumed through workspace package exports. Fallow does not follow that package boundary, so keep only the two root lifecycle helpers without visible production edges here.",
"file": "packages/platform-apple/src/app-lifecycle-facade.ts",
"exports": ["openIosApp", "openIosDevice"]
},
{
"comment": "Apple install mechanics are reached through the root lazy façade, while bundle-info consumers use the named install-artifact façade. Fallow cannot connect dynamic import member reads to these source exports; keep this list limited to the actual facade re-exports.",
"file": "packages/platform-apple/src/core/install-artifact.ts",
"exports": ["prepareIosInstallArtifact", "readIosBundleInfo"]
},
{
"comment": "Apple perf mechanics are reached through the named lazy perf façade. Fallow cannot connect dynamic import member reads to these source exports; keep this list limited to the facade's re-exports.",
"file": "packages/platform-apple/src/perf-facade.ts",
"exports": [
"buildAppleFrameSamplingMetadata",
"buildAppleMemorySamplingMetadata",
"buildAppleMemorySnapshotSupport",
"isRetryableIosDeviceTraceRecordFailure",
"resolveIosDevicePerfHint",
"captureAppleMemorySnapshot",
"readAppleProcessSamples",
"resolveAppleExecutable",
"resolveIosDevicePerfTarget",
"sampleAppleFramePerf",
"sampleAppleMemoryPerf",
"cleanupAppleXctracePerfCapture",
"startAppleXctracePerfCapture",
"stopAppleXctracePerfCapture",
"writeAppleXctracePerfReport",
"AppleXctraceCpuProfileReport",
"AppleXctracePerfMode",
"AppleXctracePerfResult"
]
},
{
"comment": "Apple tool-provider mechanics are reached through the named lazy tool-provider façade. Fallow cannot connect dynamic import member reads to these source exports; keep this list limited to the facade's re-exports.",
"file": "packages/platform-apple/src/tool-provider-facade.ts",
"exports": [
"hasScopedAppleToolProvider",
"resolveAppleToolProvider",
"createLocalAppleToolProvider",
"readApplePlistJson",
"runAppleToolCommand",
"runXcrun"
]
},
{
"comment": "The interactions package facade is consumed through workspace package exports. Fallow does not follow that package boundary, so keep the synchronous helper explicitly accounted for.",
"file": "packages/platform-apple/src/interactions-facade.ts",
"exports": ["resolveAppleBackRunnerCommand"]
},
{
"comment": "The runner-operations package facade is consumed through workspace package exports. Fallow does not follow that package boundary, so keep the two operations without visible production edges here explicitly accounted for.",
"file": "packages/platform-apple/src/runner-operations-facade.ts",
"exports": ["hasCachedAppleRunnerArtifact", "runApplePressSeries"]
},
{
"comment": "The device-aware simctl argument builder is reached through the named lazy simctl façade. Fallow cannot connect the dynamic member read to this source export; keep the suppression limited to that re-export.",
"file": "packages/platform-apple/src/core/simctl.ts",
"exports": ["buildSimctlArgsForDevice"]
},
{
"comment": "The device-aware simctl argument builder is a named package entrypoint reached through dynamic platform-runtime imports. Fallow cannot connect those member reads to the re-export; keep the suppression limited to this one facade symbol.",
"file": "packages/platform-apple/src/simctl-facade.ts",
"exports": ["buildSimctlArgs", "buildSimctlArgsForDevice"]
},
{
"comment": "The simulator package facade is consumed through workspace package exports. Fallow does not follow that package boundary, so keep the legacy shutdown operation explicitly accounted for.",
"file": "packages/platform-apple/src/simulator-facade.ts",
"exports": ["shutdownSimulator"]
},
{
"comment": "Apple mechanics are reached through the named lazy façade in packages/platform-apple/src/index.ts. Fallow cannot connect dynamic import member reads to this source export; keep this list limited to wrappers present in that façade.",
"file": "packages/platform-apple/src/core/perf-xctrace.ts",
"exports": ["cleanupAppleXctracePerfCapture"]
},
{
"comment": "Apple runner mechanics are reached through the named lazy façade in packages/platform-apple/src/index.ts. Fallow cannot connect dynamic import member reads to these source exports; keep this list limited to wrappers present in that façade or its cleanup composition.",
"file": "packages/platform-apple/src/core/runner-client.ts",
"exports": [
"notifyIosRunnerAppRelaunched",
"prewarmIosRunnerSession",
"prepareIosRunner",
"resolveRunnerAppBundleId",
"detachIosSimulatorRunnerSessionsForShutdown",
"getRunnerSessionSnapshot",
"scheduleIosRunnerIdleStop",
"stopIosRunnerSession",
"stopAllIosRunnerSessions",
"readStaleRunnerLease",
"verifyLeaseRunnerPidIdentity",
"applyXctestRunnerAppIconFromDerivedPath"
]
},
{
"comment": "The Apple root façade owns the lazy runner-owner mutator; Fallow cannot connect its dynamic import member read to the moved source export.",
"file": "packages/platform-apple/src/core/runner-owner-state.ts",
"exports": ["setRunnerLeaseOwnerStateDir"]
},
{
"comment": "Apple diagnostics are reached through the named lazy façade in packages/platform-apple/src/index.ts. Fallow cannot connect dynamic import member reads to these source exports; keep this list limited to wrappers present in that façade.",
"file": "packages/platform-apple/src/doctor.ts",
"exports": ["appleToolchainCheck", "appleRunnerWarmupCheck"]
},
{
"comment": "macOS helper mechanics are reached through the named lazy façade in packages/platform-apple/src/index.ts. Fallow cannot connect dynamic import member reads to these source exports; keep this list limited to wrappers present in that façade.",
"file": "packages/platform-apple/src/os/macos/helper.ts",
"exports": ["startMacOsAudioProbeProcess", "resolveFrontmostMacOsApp"]
},
{
"comment": "The Apple package root is a cold-start-preserving named façade: its production consumers load the value wrappers through dynamic imports. Fallow cannot connect those member reads, so this exact list records only the façade exports currently reported as unreachable; static consumers remain visible to the audit.",
"file": "packages/platform-apple/src/index.ts",
"exports": [
"appleToolchainCheck",
"appleRunnerWarmupCheck",
"detectSoleRunningIosSimulatorApp",
"findIosSimulatorInstalledApp",
"invalidateIosAppResolutionCache",
"listIosApps",
"resolveIosApp",
"resolveIosSimulatorDeepLinkBundleId",
"closeIosApp",
"openIosApp",
"openIosDevice",
"screenshotIos",
"pushIosNotification",
"readIosClipboardText",
"writeIosClipboardText",
"runAppleToolCommand",
"runXcrun",
"createLocalAppleToolProvider",
"readApplePlistJson",
"setIosSetting",
"readAppleAlert",
"awaitAppleAlert",
"actOnAppleAlert",
"createAppleInteractor",
"ensureBootedSimulator",
"shutdownSimulator",
"withAppleToolProvider",
"prepareIosInstallArtifact",
"symbolicateCrashArtifact",
"queryAppleRunnerSelector",
"resolveFrontmostMacOsApp",
"runMacOsAlertAction",
"startMacOsAudioProbeProcess",
"captureMacOsSurfaceSnapshot",
"cleanupAppleXctracePerfCapture",
"sampleAppleMemoryPerf",
"captureAppleMemorySnapshot",
"sampleAppleFramePerf",
"prepareAppleTraceRecordRetry",
"resolveAppleExecutable",
"resolveIosDevicePerfTarget",
"readAppleProcessSamples",
"startAppleXctracePerfCapture",
"stopAppleXctracePerfCapture",
"writeAppleXctracePerfReport",
"runApplePressSeries",
"runAppleRunnerCommand",
"notifyIosRunnerAppRelaunched",
"prewarmAppleRunnerCache",
"prewarmIosRunnerSession",
"prepareIosRunner",
"resolveRunnerAppBundleId",
"detachIosSimulatorRunnerSessionsForShutdown",
"getRunnerSessionSnapshot",
"scheduleIosRunnerIdleStop",
"stopIosRunnerSession",
"stopAllIosRunnerSessions",
"cleanupRunnerLeasesForOwner",
"readStaleRunnerLease",
"verifyLeaseRunnerPidIdentity",
"applyXctestRunnerAppIconFromDerivedPath",
"AppleMacOsHelperProvider",
"AppleToolAvailabilityChecker",
"AppleToolCommandExecutor",
"AppleXcrunToolProvider",
"IosPhysicalDeviceBackend",
"IosPhysicalDeviceControl",
"IosPhysicalDeviceTunnel",
"PreparedIosInstallArtifact",
"AppleMemoryPerfSample",
"AppleMemorySnapshotResult",
"AppleProcessSample",
"AppleXctraceCpuProfileReport",
"AppleXctracePerfCapture",
"AppleXctracePerfMode",
"AppleXctracePerfResult",
"MacOsPermissionTarget",
"MacOsSnapshotNode"
]
},
{
"comment": "The legacy Maestro fallback wording remains contracts vocabulary for wire/fixture compatibility, but has no in-repo production consumer. The Apple migration changes this file's documentation path, so keep the existing declaration explicit without treating it as a new W4 export leak.",
"file": "packages/contracts/src/interactor-types.ts",
"exports": ["MAESTRO_NON_HITTABLE_FALLBACK_MESSAGE"]
},
{
"comment": "Daemon route handlers are reached only through the dynamic `import()` table in request-handler-chain.ts, which --production analysis cannot follow to a consumer.",
"file": "src/daemon/handlers/{lease,session,snapshot,react-native,record-trace,find,interaction}.ts",
Expand Down
14 changes: 8 additions & 6 deletions docs/adr/0009-apple-platform-consolidation.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ is therefore costly out of proportion to the actual work, and iPadOS/visionOS/wa

Model Apple OSes with an **`AppleOS` discriminant** (`ios | ipados | tvos | watchos | visionos | macos`)
under a single `apple` Platform — **not** six `Platform` literals. The OS-agnostic Apple engine consolidates
under `src/platforms/apple/core/`, with genuinely per-OS code in `src/platforms/apple/os/<os>/` leaves;
under `packages/platform-apple/src/core/`, with genuinely per-OS code in
`packages/platform-apple/src/os/<os>/` leaves;
the Apple plugin is the first instance of the platform-plugin registry (the platform axis of the
completed perfect-shape refactor; the registry and enforcement paths below are authoritative).
Per-OS capability differences become data keyed by `AppleOS`. The additive,
Expand Down Expand Up @@ -62,11 +63,12 @@ This composes with ADR 0008 (the descriptor's capability facet) and ADR 0003.
Implementation status as of 2026-08:

- Shipped: the internal `Platform` collapse to `apple`; additive `appleOs` groundwork; the shared
Apple engine under `src/platforms/apple/core`; macOS leaf files under
`src/platforms/apple/os/macos`; a dedicated tvOS leaf under `src/platforms/apple/os/tvos`;
direct internal imports to the Apple modules; the per-`AppleOS` capability table
(`APPLE_OS_CAPABILITIES`, `src/platforms/apple/capabilities.ts`, parity-pinned against the pre-table
predicates); the watchOS **unsupported sentinel** (reserved in the `AppleOS` type and interactor-rejected —
Apple engine under `packages/platform-apple/src/core`; macOS leaf files under
`packages/platform-apple/src/os/macos`; a dedicated tvOS leaf under
`packages/platform-apple/src/os/tvos`;
direct internal imports to the Apple modules; the per-`AppleOS` runtime facts (including
`packages/platform-apple/src/gesture-facts.ts`; the former capability projection was retired after
its predicates moved into request-bound facts); the watchOS **unsupported sentinel** (reserved in the `AppleOS` type and interactor-rejected —
XCUITest cannot drive watchOS UI — `isSupportedAppleDeploymentLeaf`, the Apple interactor, and
gesture admission reject it — never produced by discovery); and visionOS profile/build/discovery
plus simulator-deployment evidence.
Expand Down
18 changes: 9 additions & 9 deletions fallow-baselines/health.json
Original file line number Diff line number Diff line change
Expand Up @@ -351,38 +351,38 @@
"count": 2
}
},
"src/platforms/apple/core/app-resolution.ts": {
"packages/platform-apple/src/core/app-resolution.ts": {
"crap_moderate": {
"count": 1
}
},
"src/platforms/apple/core/app-settings.ts": {
"packages/platform-apple/src/core/app-settings.ts": {
"crap_moderate": {
"count": 1
}
},
"src/platforms/apple/core/perf.ts": {
"packages/platform-apple/src/core/perf.ts": {
"complexity_high": {
"count": 1
},
"crap_high": {
"count": 1
}
},
"src/platforms/apple/core/screenshot-status-bar.ts": {
"packages/platform-apple/src/core/screenshot-status-bar.ts": {
"complexity_moderate": {
"count": 1
},
"crap_moderate": {
"count": 2
}
},
"src/platforms/apple/core/screenshot.ts": {
"packages/platform-apple/src/core/screenshot.ts": {
"complexity_moderate": {
"count": 1
}
},
"src/platforms/apple/os/macos/helper.ts": {
"packages/platform-apple/src/os/macos/helper.ts": {
"crap_high": {
"count": 1
}
Expand Down Expand Up @@ -578,20 +578,20 @@
"src/snapshot/snapshot-lines.ts:high impact",
"src/utils/result-serialization.ts:high impact",
"src/utils/rect-center.ts:high impact",
"src/platforms/apple/core/app-launch.ts:complexity",
"packages/platform-apple/src/core/app-launch.ts:complexity",
"src/utils/parsing.ts:high impact",
"src/daemon/daemon-command-registry.ts:high impact",
"src/replay/script.ts:complexity",
"src/daemon/handlers/session-doctor-output.ts:high impact",
"src/platforms/apple/core/perf-xml.ts:high impact",
"packages/platform-apple/src/core/perf-xml.ts:high impact",
"src/daemon/daemon-process.ts:high impact",
"src/utils/screenshot-result.ts:high impact",
"packages/platform-web/src/json-utils.ts:high impact",
"packages/platform-android/src/settings.ts:complexity",
"src/utils/text-surface.ts:high impact",
"src/daemon/handlers/session-test-sharding.ts:high impact",
"src/daemon/handlers/session-replay-runtime.ts:complexity",
"src/platforms/apple/core/debug-symbols/utils.ts:high impact",
"packages/platform-apple/src/core/debug-symbols/utils.ts:high impact",
"packages/platform-linux/src/snapshot.ts:high impact",
"src/core/interaction-targeting.ts:high impact",
"packages/maestro/src/internal/runtime-targets.ts:high impact",
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts/src/interactor-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ export const MAESTRO_NON_HITTABLE_FALLBACK_MESSAGE = 'tapped via non-hittable co
* `TextEntryResult.textEntryRoute` (RunnerTests+TextTyping.swift,
* RunnerTests+SynthesizedTextEntry.swift). Closed set, because the runner is
* its only producer and the boundary that narrows it
* (readTypeTextBackendResult, src/platforms/apple/interactions.ts) drops a
* (readTypeTextBackendResult, packages/platform-apple/src/interactions.ts) drops a
* route it cannot name — so a Swift-side addition would silently vanish. The
* route-parity test in src/platforms/apple/core/__tests__/interactions.test.ts
* route-parity test in packages/platform-apple/src/core/__tests__/interactions.test.ts
* reads the Swift sources and fails instead.
*/
export const TEXT_ENTRY_ROUTES = [
Expand Down
12 changes: 12 additions & 0 deletions packages/host-kit/src/host-file.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
export {
createHostDirectoryLinkSync,
accessHostFile,
chmodHostFile,
copyHostFile,
copyHostPath,
ensureHostDirectory,
ensureHostDirectorySync,
hostFileExistsSync,
hostFileLstatSync,
hostFileStat,
hostFileStatSync,
hostHomeDirectory,
hostTemporaryDirectory,
makeHostTemporaryDirectory,
readHostBinaryFile,
readHostDirectory,
readHostDirectorySync,
readHostSymbolicLinkSync,
readHostTextFile,
readHostTextFileSync,
removeHostDirectory,
removeHostPath,
removeHostFileSync,
renameHostPath,
unlinkHostFile,
writeHostBinaryFile,
writeHostTextFile,
writeHostTextFileSync,
} from './internal/host-file.ts';
Loading
Loading