The capability matrix admitted `viewport` on every Apple simulator and
device while no Apple interactor implements `setViewport`, so the command
was routed to the device and only rejected inside dispatch with the
backend-shaped "viewport is not supported by this backend". Nothing can
serve it there: Apple screen geometry is fixed by the selected device type
and neither simctl nor XCTest exposes a resize primitive, so viewport is a
web-surface contract (its CLI summary and docs already say so).
Deny it in the descriptor's capability facet, matching the adjacent Android
denial, and give the Apple family an unsupported hint that names the surface
that does support it. Admission now fails before the request reaches the
device: "viewport is not supported on this device" with supportedOn: web.
The iOS simulator coverage manifest's known-gap row becomes a
capability-denial row owned by the static coverage test, which retires the
whole known-gap level and the `full:known-gaps` live scenario that existed
only to pin this failure.
Closes #1407
Summary
viewportwas admitted by the capability matrix on every Apple simulator and physical device, but no Apple interactor implementssetViewport. The command was therefore routed all the way to the device and rejected inside dispatch with a backend-shaped error. Nothing can serve it there — Apple screen geometry is fixed by the selected device type, and neithersimctlnor XCTest exposes a resize primitive — soviewportis a web-surface contract, which is what its CLI summary ("Resize the active web viewport for the current session") and every doc example (--platform web) already say.This denies
viewportduring capability admission for Apple targets, matching the Android denial on the adjacent line of the same descriptor, and gives the Apple family an unsupported hint that names the surface that does support it.Before, on a booted iOS simulator:
After:
capabilitiesno longer advertisesviewporton Apple targets. Web viewport resizing (agent-device viewport 1280 900 --platform web) is unchanged, and Android was already denied.Coverage moves with the behavior: the iOS simulator coverage manifest's
known-gaprow becomes acapability-denialrow owned by the static coverage test (the same shapetv-remoteuses). That was the only known-gap row, so theknown-gaplevel and thefull:known-gapslive scenario — which existed solely to runviewport 390 844on a real simulator and assert it fails — are retired with it. The denial and its hint are now pinned bycapabilities.test.ts, both independent Apple capability-parity oracles, and the simulator coverage test.Closes #1407
Validation
Live on a booted iPhone 17 Pro simulator (iOS 26.2), before/after against builds of the same worktree: the before run's request diagnostics show
platform_command_prepare→platform_command→request_failed, i.e. the request reached the Apple interactor; the after run showsrequest_start→request_failedonly, so admission now rejects it before the device is touched.capabilitiesoutput confirmsviewportdisappeared from the simulator's admitted set. The verification session was opened and closed with an isolated--state-dir, and its daemon stopped.The web path was not exercised live — the managed
agent-browserbackend is not installed on this host — so web coverage here isweb-desktop.test.ts(green, asserts theset viewport 1280 900provider call) plus the web column ofcapabilities.test.ts.Unit suite, typecheck/lint/build/layering/MCP-metadata, fallow (clean on all 11 changed files), and the iOS simulator coverage smoke suite pass.
provider-scenarios/android-test-suite.test.tsfails 3-6 timeout-shaped tests with a shifting failure set on this host; it reproduces identically with these changes stashed, so it is host contention, not this change. GitHub remains authoritative.Notes
11 files touched, all within the viewport command family and its coverage manifests. No docs update was needed: the command surface, CLI help, and
website/docsalready describeviewportas web-only — this change makes capability admission agree with them. CHANGELOG updated under Unreleased.