Reproducible Rendered UI Validation¶
Use the rendered UI harness when a Swarm Hosts change depends on what a user actually sees or can operate in a browser. It starts temporary control-plane and admin applications, seeds a deterministic synthetic world, logs in without real credentials, and writes sanitized evidence outside the repository.
The default acceptance profile renders these states at exactly 1440x900,
1280x800, 768x1024, and 390x844:
- Minecraft creation;
- large and empty deployment lists;
- healthy and failed resource details;
- degraded/offline status;
- owner, manage/operator, view-only, resource-admin, and light-theme permissions.
The fixture also contains a platform admin, an empty account, online Linux and Windows hosts, an explicitly offline host, pending and disabled actions, long names/paths/logs, 14 deployments, Minecraft, Terraria, and nine other supported game types. IDs are stable. Time-relative fields share one run anchor so they do not decay independently during a sweep.
Run the same profile locally or in the factory¶
Reuse the repository virtual environment. Install the pinned browser-side dependency and Chromium once if they are not already present:
npm ci --prefix scripts/validation/browser --ignore-scripts
.venv/bin/python -m playwright install chromium
Commit the candidate first. Durable evidence fails closed when the worktree is
dirty because each manifest must name the exact tested commit. Export
GITLAB_ISSUE_IID and GITLAB_MR_IID with the actual positive numeric IIDs for
the candidate under review. The required-value expansions below deliberately
stop a copied command before capture if either value is missing; never reuse
provenance from another issue or merge request.
make validate-rendered-ui \
UI_ISSUE="${GITLAB_ISSUE_IID:?Export GITLAB_ISSUE_IID as the actual issue IID}" \
UI_MR="${GITLAB_MR_IID:?Export GITLAB_MR_IID as the actual MR IID}" \
UI_REVIEWER=implementation-worker:skitter \
UI_TEST_RESULT='make test-fast=passed' \
UI_RENDER_ARGS='--allow-findings'
--allow-findings changes only the process exit code so an implementation worker
can retain evidence of an existing UI defect. The manifest and affected capture
remain passed: false; no finding is hidden. An independent reviewer should omit
that option and provide --visual-verdict pass or --visual-verdict fail after
inspecting the screenshots.
Use the inventory profile for the complete route/state matrix:
make validate-rendered-ui \
UI_ISSUE="${GITLAB_ISSUE_IID:?Export GITLAB_ISSUE_IID as the actual issue IID}" \
UI_MR="${GITLAB_MR_IID:?Export GITLAB_MR_IID as the actual MR IID}" \
UI_REVIEWER=independent-validator \
UI_TEST_RESULT='make test-fast=passed' \
UI_RENDER_ARGS='--profile inventory --visual-verdict pass'
Use repeatable --target TARGET_ID or --viewport NAME=WIDTHxHEIGHT arguments
for focused diagnosis. The default acceptance profile always uses all four
contract viewports. Target definitions come from
docs/design/ui-ux-route-state-inventory.json; do not add a second hard-coded
route list.
What the harness records¶
Every capture includes:
- the target ID, surface/base URL placeholder, route and query/modal/drawer state;
- role, fixture, game type, data state, GitLab issue/MR, exact commit SHA, browser/version, viewport, and UTC timestamp;
- viewport and full-page PNG paths, byte lengths, SHA-256 hashes, and sanitation status;
- top-level status, route preservation, console errors, page errors,
Playwright
requestfailedevents, and first-party document/XHR/fetch/asset failures; - page-level horizontal overflow plus separate deliberate terminal/log/code scroll containers;
- axe-core WCAG A/AA critical/serious results and computed color-contrast classification;
- explicit Tab order, viewport visibility, and computed focus-indicator results;
- form validity gating and payload-key checks for the Minecraft create flow;
- the evidence producer, visual verdict, approved exceptions, findings, and test command/results.
The harness captures both viewport and full-page screenshots at every viewport, so mobile content below the first fold is never omitted. Pixel differences and DOM metrics are regression signals, not aesthetic approval.
Evidence manifest contract¶
The artifact directory contains summary.json with schema
swarmhosts_rendered_ui_evidence/v2. Required top-level sections are:
| Section | Contract |
|---|---|
provenance |
Positive GitLab issue/MR IDs, exact 40-character commit SHA, and sourceDirty: false. |
browser |
Browser name/version plus pinned axe-core version and source hash. |
inventory |
Inventory schema/path, total surface count, selected targets, and run profile. |
fixture |
Fixture profile, safe role/state/game coverage, and dynamic key names without token values. |
sessionProfiles |
Every guest/auth role and authStorage: memory-only. |
acceptanceCriteria |
Acceptance criterion IDs mapped to target IDs. |
viewportMatrix |
The exact desktop-wide, desktop-standard, tablet, and mobile dimensions. |
tests |
At least one exact command/result pair supplied by --test-result. |
review |
Reviewer identity and explicit visual verdict. |
approvedExceptions |
Optional check code and reason pairs; unapproved findings remain failures. |
results |
One complete record for each unique target/viewport pair. |
manifestValidation |
Parser result; any missing field, unsafe path, bad hash, dirty source, or sanitation failure rejects the manifest. |
Each result must contain both screenshot kinds, valid SHA-256 hashes, passed
sanitation, console/network/accessibility/keyboard/route results, a visual verdict,
and its applied exceptions. Parser and hashing behavior is covered by
tests/test_rendered_ui_validation_contract.py.
Artifacts must remain under /tmp or another path outside the repository. Browser
storage state is kept in memory, reset/Discord tokens are never written to the
manifest, synthetic sensitive inputs are redacted before screenshots, and no real
account or deployment is contacted.
Existing tooling and migration¶
This extends rather than replaces the existing tools:
scripts/validation/rendered_ui_validation.pyis the inventory-driven implementation/review evidence path.scripts/validation/ui_density_evidence.pyremains the focused before/after collector for compactness and information-density changes.scripts/validation/final_ui_route_sweep.pyremains a compatible 33-route historical gallery entry point, but its v2 output no longer hard-codes issue 238 and its authentication state stays in memory instead of the artifact directory.
Do not approve accessibility based only on color or DOM inspection. The axe-core scan and keyboard/focus traversal are both required, and an independent visual verdict is still necessary for layout or aesthetic claims.