(command: string, device: DeviceInfo)
| 79 | } |
| 80 | |
| 81 | export function isCommandSupportedOnDevice(command: string, device: DeviceInfo): boolean { |
| 82 | const capability = COMMAND_CAPABILITY_MATRIX[command]; |
| 83 | if (!capability) return true; |
| 84 | // Platform -> capability-bucket selection now flows through the single |
| 85 | // PlatformPlugin registry (ADR-0009, Phase 3 step b.1): the bucket a leaf |
| 86 | // platform reads from a CommandCapability is the owning plugin's |
| 87 | // `capability.bucket`. This replaces the former `selectCapabilityForPlatform` |
| 88 | // fold over `platformDescriptors`; the plugin bucket is proven byte-for-byte |
| 89 | // equal to that derivation by `platform-plugin/__tests__/parity.test.ts`, and |
| 90 | // `__tests__/capability-plugin-routing-parity.test.ts` pins that this swap leaves |
| 91 | // `isCommandSupportedOnDevice` unchanged across the full command x device matrix. |
| 92 | // `tryGetPlugin` returns undefined only for an unregistered platform — the same |
| 93 | // "no bucket -> unsupported" fall-through the fold produced for a platform with |
| 94 | // no capability family (ADR-0009's plugin registry: `if (!plugin) return false`). |
| 95 | const plugin = tryGetPlugin(device.platform); |
| 96 | if (!plugin) return false; |
| 97 | const byPlatform = capability[plugin.capability.bucket]; |
| 98 | if (!byPlatform) return false; |
| 99 | // The per-command `supports()` gate now flows through the owning PlatformPlugin |
| 100 | // (ADR-0009, Phase 3 step b.2): the family that owns `device.platform` carries the |
| 101 | // `supports()` closure RELOCATED VERBATIM in `capability.supportsByDefault`, keyed by |
| 102 | // command. A family with no entry for `command` admits it unchanged — proven equal to |
| 103 | // the former command-facet closure across the device matrix by |
| 104 | // `__tests__/capability-plugin-routing-parity.test.ts`. |
| 105 | const supportsByDefault = plugin.capability.supportsByDefault?.[command]; |
| 106 | if (supportsByDefault && !supportsByDefault(device)) return false; |
| 107 | const kind = (device.kind ?? 'unknown') as keyof KindMatrix; |
| 108 | return byPlatform[kind] === true; |
| 109 | } |
| 110 | |
| 111 | export function unsupportedHintForDevice(command: string, device: DeviceInfo): string | undefined { |
| 112 | // Counterpart of the `supports()` relocation (Phase 3 step b.2): the hint closure is |
searching dependent graphs…