Skip to content
Prev Previous commit
Next Next commit
fix(apple): exclude physical Watches from inventory
  • Loading branch information
csark0812 committed Sep 28, 2026
commit c9a63e35c9bc5786a303a9b270b76ef212170930
10 changes: 8 additions & 2 deletions packages/platform-apple/src/inventory-classification.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,14 @@ test('devicectl classification resolves tvOS, iPadOS, and visionOS vocabulary',
]),
'watchos',
);
assert.equal(resolveAppleOs('mobile', ['Watch6,4']), 'watchos');
assert.equal(isAppleProductType('Watch6,4'), true);
assert.equal(resolveAppleOs('mobile', ['iOS-26-0', 'Watch6,4']), 'ios');
assert.equal(isAppleProductType('Watch6,4'), false);
assert.equal(
isSupportedAppleDevicectlDevice({
hardwareProperties: { platform: 'iOS', productType: 'Watch6,4' },
}),
false,
);
});

test('devicectl records map to normalized physical Apple devices', () => {
Expand Down
9 changes: 7 additions & 2 deletions packages/platform-apple/src/inventory-classification.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { AppleOS, DeviceInfo, DeviceTarget } from '@agent-device/kernel/device';

const APPLE_PRODUCT_TYPE_PATTERN = /^(iphone|ipad|ipod|appletv|watch\d+,\d+|realitydevice)/i;
const APPLE_PRODUCT_TYPE_PATTERN = /^(iphone|ipad|ipod|appletv|realitydevice)/i;
const APPLE_IPAD_PATTERN = /ipad/i;
const APPLE_VISION_PATTERN = /\b(apple vision|vision pro|xros|visionos|realitydevice)\b/i;
// OS identity must come from Xcode/CoreDevice identifiers, never a user-editable device label.
const APPLE_WATCH_PATTERN = /(?:\bwatchos\b|simdevicetype\.apple-watch|^watch\d+,\d+$)/i;
const APPLE_WATCH_PATTERN = /(?:\bwatchos\b|simdevicetype\.apple-watch)/i;
const APPLE_MOBILE_LABEL_PATTERN = /\b(iphone|ipad|ipod)\b/i;
const APPLE_TV_PRODUCT_TYPE_PATTERN = /^appletv/i;
const APPLE_TV_LABEL_HINTS = ['apple tv', 'appletv', 'tvos'] as const;
Expand Down Expand Up @@ -97,6 +97,11 @@ export function resolveAppleTargetFromDevicectlDevice(device: DevicectlAppleDevi

export function isSupportedAppleDevicectlDevice(device: DevicectlAppleDevice): boolean {
const platform = normalizeAppleDescriptor(device.hardwareProperties?.platform);
// A paired physical Watch is not an interactive target in this runtime. Do not surface it as
// selectable Apple inventory; pairing owns its discovery separately.
if (/^watch\d+,\d+$/i.test(devicectlProductType(device)) || platform.includes('watchos')) {
return false;
}
if (platform.includes('ios') || isAppleTvPlatform(platform) || isAppleVisionPlatform(platform)) {
return true;
}
Expand Down
3 changes: 1 addition & 2 deletions packages/platform-apple/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,7 @@ export function createApplePlatformRuntime(host: PlatformRuntimeHost): PlatformR
...viewportRuntimeOperationFacts({ setViewport: viewportUnavailable }),
...focusRuntimeOperationFacts({ focus: appleFocusFact(device, watchHidAvailable) }),
...appleGestureAndScrollFacts(device, watchHidAvailable),
// Text entry rides the same interactor authority the point focus does, so it shares the
// exact kind cell (parity with the retired `type` bucket, `{ simulator, device }`).
// The watchOS host HID backend has no text-entry route, so this remains unavailable there.
...typeTextRuntimeOperationFacts({
type:
device.appleOs === 'watchos' ? unavailable : appleFocusFact(device, watchHidAvailable),
Expand Down