Inspecting running views¶
Offline validation cannot tell whether a view works. The eyes can: pdk inspect opens a deployed view in a
headless Chromium browser, waits until it renders and its layout is stable, measures every component and combines
three sources about each one:
the
view.jsonthat the gateway has (so every problem points into the file);the browser’s DOM (boxes, text, colors, scrolling, errors in the console);
the gateway’s evaluated component tree (the quality of every binding) and its log (scripts that failed).
The report lists only anomalies, each on the JSON pointer of the component that has it, like the validator.
Commands¶
uv run pdk open PDK/Pump # render it and report load time and browser errors
uv run pdk inspect PDK/Pump # anomalies
uv run pdk inspect PDK/Pump --focus V001 # expand one code, component or pointer
uv run pdk inspect PDK/Pump --viewport 1920x1080
uv run pdk inspect PDK/Pump --viewport desktop,tablet,phone # one report per viewport
uv run pdk screenshot PDK/Pump --component root/Panel --out panel.png
The view is given by its path in the sandbox (PDK/Pump) or by its local folder. The default viewport is
1366×768; --viewport takes WIDTHxHEIGHT or a preset (desktop 1366×768, tablet 768×1024, phone
375×812, wide 1920×1080), and inspect takes several, comma-separated, with one report for each (the
token budget is shared). Inspection always looks at the deployed version: if your local copy differs, the report says so, and
X002 means the page does not render the view.json at all (deploy first).
Anomalies¶
Code |
Name |
Meaning |
|---|---|---|
|
Text cut |
A label, button or link shows less text than it needs (clipped or ended with an ellipsis). The message gives the width needed and the width shown. |
|
Component overflow |
A component extends outside a parent that clips it. |
|
Viewport overflow |
A component extends outside the browser window. |
|
Collapsed |
A component with content was shrunk to zero size inside a parent that has room, typically a table or chart
without |
|
Not rendered |
A component in the |
|
Embedded view failed |
An embedded view or repeater did not load: check |
|
Repeater instances overflow |
A flex repeater’s instances are bigger than the repeater along the axis their number does not explain (the
cross axis without |
|
Low contrast |
Text too close in color to what is behind it (WCAG AA: 4.5:1, or 3:1 for large text). The background is the first opaque one from the text outwards. Only text components whose colors the view chose are judged (not the theme’s defaults, nor text drawn inside charts or tables); text over an image is not judged, and disabled controls are exempt. |
|
Unrequested scroll |
A container scrolls, or shows an empty scrollbar ( |
|
Bad quality |
A binding delivers a Bad quality, for example |
|
Error quality |
A binding fails while evaluating: |
|
Uncertain quality |
A binding has not produced a good value yet. |
|
Script error |
The gateway logged a script error for this component (an event handler or a startup script). |
|
Browser error |
An error in the browser console. |
|
Eyes degraded |
Part of the inspection was not available (for example the gateway’s session API), so only the DOM was checked. |
|
Page out of sync |
The page does not render this |
Expectations¶
A clean inspection means nothing is broken, not that the view is what was requested. --expect turns the
request into checks; each one that fails comes back as A001 with what was measured. Separate expectations with
; or new lines. Components are written as their full name path from root; quote names that contain
spaces.
Expectation |
Checks that… |
|---|---|
|
B is below A; also |
|
the component lies within the other’s box (or its scrolled content). |
|
the edges line up: |
|
a size or position: |
|
the exact text; |
|
the component is rendered with a size (or not). |
|
the control, or the input inside it, is enabled. |
|
the content overflows and the component scrolls along that axis. |
|
the component is wholly in sight: not scrolled away, clipped or outside the window. |
|
text color; also |
|
a property as the gateway evaluated it: |
|
the same for the view’s |
|
the page’s URL path inside the project ( |
|
a popup with that id is open. Its components are written |
|
a simulated tag holds that value (read back from the gateway); |
|
the alarms of the tags at or under that path are active (or cleared). |
Lengths are compared with a 1-pixel tolerance. A malformed expectation is A002 and one that names a component
that does not exist is A003.
Actions¶
--act runs steps in the browser before measuring, so the expectations, the binding qualities and the
script errors all describe the state after them:
Step |
Does |
|---|---|
|
Clicks the component. |
|
Types into the input inside the component and confirms with Tab. |
|
Selects the second visible row of a table. |
|
Picks that option of a dropdown (several labels for a multi-select) and waits until the dropdown shows it. |
|
Moves a slider’s handle with the keyboard until it reads 7 (A004 if 7 is not one of its steps). |
|
Presses a key (Playwright names: |
|
Moves the mouse over the component, or double-clicks it. |
|
Scrolls the component (or the first scrolling element inside it) |
|
Waits that many milliseconds (at most 10,000). |
|
Writes a simulated tag (see Simulated tags); the view receives it through its subscription. |
After each step the page is allowed to settle. A step that cannot be done (a disabled button, a missing row) stops
the sequence as A004; a malformed step is A005. If a step opens a popup, the popup is inspected too and its
anomalies carry the popup:<id>/ prefix.
If a step navigates (a nav action to a page or to a view), the report is about the view the page shows
afterwards, and a note says so: its anomalies, and the components named in --expect and --query, are that
view’s. page /detail and page shows PDK/Detail check where it went. A navigation to a page needs a route
for it in the project’s page configuration; one to a url outside Perspective leaves only page to check.
Example: check that a button becomes enabled once a name is typed.
uv run pdk inspect PDK/Form --act 'type root/Name "P-2"' --expect "root/Save enabled"
Measurements¶
--query prints what was measured for some components, which helps to write or tune expectations without a
screenshot. Terms are separated by commas: a name path (the component and its subtree), a component type
(ia.display.label), a pointer prefix or * for everything.
root/Title ia.display.label @12,12 1342x32 | "Pump P-101" | rgb(50, 50, 50) 20px 700 Noto Sans align start | flex column justify center
Each line gives the position and size in viewport pixels, the text, the color and font, and, when they are not at their defaults, the background, padding, border, flex settings and scrolling.
Screenshots¶
pdk screenshot saves a PNG of the view or of one component (--component root/Panel). Use it for what only
an image can judge, such as colors and visual hierarchy; measurements and expectations are cheaper and more precise
for everything else. --act runs the same steps as inspect --act before capturing, so a popup
(--component popup:detail/root) or the state after typing can be captured.
--compare before.png checks what a change did to the picture: take a screenshot before editing, deploy the
change, and capture again with the same view, viewport and component. The report gives the share of pixels that
changed and the components where they are; the diff image (<out>__diff.png) shows the new capture faded with
the changed pixels in red. Changes outside the components you meant to touch are the regressions to look at.
uv run pdk screenshot PDK/Pump --out before.png
# edit, deploy
uv run pdk screenshot PDK/Pump --compare before.png
# compare: 0.4% of pixels differ in 1 region(s): root/Header/Title 93x13 @12,8
Sessions and the browser¶
Each open view holds a Perspective session on the gateway, and some editions (Maker) limit how many can be open.
PDK reuses one browser and one session between calls; the MCP server closes its browser after two minutes without
use (PDK_EYES_IDLE_S). A browser that goes away only disconnects its session, which would keep its slot until it
times out, so when PDK closes its browser (at the end of a command, or when the MCP server’s browser goes idle) it
also closes its sessions on the gateway. If a gateway still refuses a session, close other Perspective tabs or wait
for idle sessions to time out.