One headless browser: ps-qa drives chuzz, and qa-inspect-host goes - #19
Merged
Conversation
`ps-qa click` reads frame metrics either side of the action, as context. A headless host owns a document and no compositor, so it answers "unsupported", and the whole command failed with inspector returned unsupported: the headless page serves diagnostics Capture, Snapshot and WindowComposition only before the click was ever dispatched. The one thing that could drive a built site could not be clicked. The numbers are now optional where they are only context, and the command says the host has none rather than printing zeroes. Where they are the point -- `idle`, `frames`, `drift`, `blink` -- nothing changes and the refusal still fails the command: a zeroed reading from a host that never painted would pass every one of those while proving nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
It was a second one. `ps-qa` drove it, chuzz is what ships, and the web platform existed in only chuzz: `URLSearchParams`, `matchMedia`, storage, the observers and `performance.getEntriesByType` are supplied by chuzz's document loader, and a host without them blanks every routed page before its first render. So the harness measured a browser nobody uses, and every gap closed for the browser had to be closed a second time here, by hand. It is `chuzz-headless` now, in pathscale/chuzz, loading through the same loader and the same engine a tab uses and serving this protocol over the same socket. `ps-qa` still links no renderer, and the `core` job's dependency-tree gate still proves it: that constraint was about the socket, never about which repository the host lives in. `--host` was always a path, so nothing in `ps-qa` needed changing to point at it. What goes with the crate is the `host` CI job, which was the one place `ps-qa` drove a live page end to end. That coverage moves to chuzz, where both halves exist, rather than being dropped: pathscale/chuzz#37 carries the fixture and the socket test. The published `qa-inspect-host` 0.1.12 stays on the registry, so the `@pathscale/ui` component sweep keeps working until it is pointed at the new host. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The documented layout puts `ps-qa.ron` beside the checks, and the check glob read it as one: every run failed with "Expected opening `[`" at line 5, pointing at the profile's syntax, which is correct, rather than at the file being included by mistake. The layout the documentation describes could not be used. Found writing the first site's checks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Publishing is per-crate and triggered by the version, and a site's CI installs the driver from the registry. Without this the documented check layout still fails there: `ps-qa.ron` beside the checks is read as a check group and every run stops with "Expected opening `[`". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pathscale
force-pushed
the
feat/target-controls-with-no-area
branch
from
September 8, 2026 07:41
9a0b13f to
b1bcc97
Compare
Every site's `qa.yml` sets `QA_TIMEOUT_SCALE` in the job environment and nothing read it, so all eleven of them would have run a shared runner against the strict local latency contract. The knob was `--timeout-scale` and only that. Found on nofilter.io, where it is not a runner-speed nicety: every navigation reloads and re-executes a 1.8MB bundle, so arrival takes about a second of engine time and the 900ms default gave up, went home, and reported the surface as unreachable. The flag still wins when both are given. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An outcome poll narrows to the pane the action happened in, so a settling check does not serialise a large tree every turn. It probed the full document once when the scoped verdict said the result was absent, and never again. That made it permanently blind to anything outside the pane that arrived after that single probe. A sign-in is exactly this shape: the credential is accepted, the account page replaces the pane, and the shell's header swaps a Login for a Logout. The probe was taken before the swap, so the poll stayed scoped for the rest of its deadline. Measured on honey.id against auth-dev: thirty seconds of polling never saw `button:Logout`, and one fresh snapshot taken a second after the harness disconnected found it at once. The check now passes in three. The one-shot becomes an interval. Between probes the stability samples stay scoped, which is what the scope was for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`inventory` classified a control by its DOM id before it looked at whether the application had declared it an exception. A link that leaves for a third party, a native file panel, a session-ending action: each was reported as `failed-missing-id`, so the only way to clear the audit was to give an id to a control no check will ever address, or to withdraw the exception. The exceptions now come first. This is what makes the mechanism usable for the fleet, where most links on a marketing page go to GitHub, crates.io or docs.rs and following them would make a run depend on those services rather than on the site under test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One line in the outcome loop was wrapped the other way; `cargo fmt --check` is the only failing job on this branch.
…hanged
`fix(qa): count a declared exception as excluded, not as unaddressable` moved
the manual and isolated exclusions ahead of the id checks in
`inventory_class`, so a control the application has excluded is reported as
excluded rather than as missing an id. The test still asserted the previous
order and was not updated, so it failed with
left: Manual right: MissingId
The function is right: an exclusion says no check will drive this control, and
reporting it as unaddressable names a defect that can only be fixed by
withdrawing the exception.
Split in two rather than just corrected. The first test keeps its subject, id
defects on a control that is not excluded. The second asserts the precedence
directly, because it is a decision rather than an accident and the last test
that touched it was silently wrong about it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
There were two headless browsers.
ps-qadroveqa-inspect-host, chuzz is what ships, and the web platform existed in only one of them.URLSearchParams,matchMedia, storage, the observers andperformance.getEntriesByTypecome from chuzz's document loader. A host without them blanks every routed page before its first render —@solidjs/routerdestructures the result ofperformance.getEntriesByTypeduring setup — so this harness could not reach a single site in the fleet, and every gap closed for the browser had to be closed a second time here, by hand.The host is a mode of the browser now:
chuzz-headless, in pathscale/chuzz#37. It loads through the same loader and the same engine a tab uses and serves this protocol over the same socket.ps-qastill links no renderer, and thecorejob's dependency-tree gate still proves it: that constraint was about the socket, never about which repository the host lives in.--hostwas always a path, so nothing inps-qaneeded changing to point at it.Also here
ps-qa clickcould not be used against a headless host. It read frame metrics either side of the action, as context, and failed outright when the host said it had none:A host that owns a document and no compositor is telling the truth there, and the one thing that could drive a built site could not be clicked. The numbers are optional where they are only context now, and the command says the host has none rather than printing zeroes. Where they are the point —
idle,frames,drift,blink— nothing changes and the refusal still fails the command, because a zeroed reading from a host that never painted would pass every one of those while proving nothing.Four earlier commits on this branch that had never been pushed, all from driving the
@pathscale/uisweep:feat(ps-qa)!type before pressing, and target a control the renderer laid out but did not paint.fix(ps-qa)the descriptor is the line that looks like one. The page shares the host's stdout, so oneconsole.logat startup was read as a path and the component was reported as never having started — wrong about the host and about the component. Found on ThemeColorPicker.qa-inspect-hostcommits that the deletion supersedes. The substance of one, replacing a field's text by byte arithmetic rather than by a selection that needs a font catalogue, is carried into the new host in feat(headless): ps-qa drives chuzz, so there is one browser chuzz#37.What this costs
The
hostCI job goes with the crate. It was the one placeps-qadrove a live page end to end, and it cannot be rebuilt here: this workspace may not link an engine. That coverage moves to chuzz, where both halves exist; pathscale/chuzz#37 carries the fixture and the socket test.The published
qa-inspect-host0.1.12 stays on the registry, so the@pathscale/uicomponent sweep keeps working until it is pointed at the new host.Verified
chuzz-headlessserving support.cafe's built dist, driven by thisps-qaover the socket:findreports 4 buttons and 9 links with real geometry,auditreports 3 audited and 0 faults, clicking "Switch to light mode" renames the control to "Switch to dark mode", and clicking "Log in" leaves the home page and loads/login.🤖 Generated with Claude Code