dvn

Public skill

Alias /surface-sweep

Surface Sweep

View prompt

Read https://dvn.pw/surface-sweep.md and help me use this skill for my task. Load task-required stages through dvn when needed.

How to use Surface Sweep
CURRENTVerified 2026-10-24T07:03:39.411Z
Read the Markdown invocation packet

Skill instructions

Original instructions

surface-sweep/SKILL.md

---
name: surface-sweep
description: "Broad visual QA and correction for existing web apps. Use for browser sweeps, responsive overflow, broken interaction states, awkward proportions, or screenshot-backed UI polish across product surfaces. Do NOT use for screenshot collection alone, a new visual identity, backend-only testing, or a public showcase; use surface-sweep-showcase when a showcase is requested."
---

# Surface Sweep

Deliver corrected product surfaces with reproducible browser evidence. A passing test suite or a large screenshot directory does not establish visual quality.

## 1. Establish the product and execution contract

Inspect repository instructions, working-tree state, design authority, routes, component variants, existing browser tests, fixtures, and run commands. Preserve the app's visual language. Both Playwright and Puppeteer are supported. Honor the user's established preference for Puppeteer or another browser automation tool; otherwise default to Playwright. Reuse compatible project fixtures, helpers, and runners. When the preferred harness is unavailable or incompatible with the permitted environment, use a supported alternative and record why. Follow the current tool's API and restrictions; these instructions do not grant additional browser capabilities.

By default, keep Dark Reader enabled during exploratory browsing and include Dark Reader-on compatibility cases throughout the sweep, unless the user opts out. Retain separate native-theme checks with Dark Reader off. For Playwright, run the isolated extension preflight in [browser-checks.md](references/browser-checks.md) before counting any Dark Reader case; launching a browser does not prove the extension is loaded or allowed on the target origin. Record unavailable coverage explicitly.

Identify local/preview/production targets and provider dependencies. Prefer isolated local fixtures for mutations. Label mocks and seeded sessions as simulated evidence. Do not put test-only auth or fixture bypasses into production. Carry out already-authorized delivery; a sweep alone does not authorize purchases, messages, production records, or deployment.

Verify that the running server serves the intended checkout and fresh build. If watching/HMR is disabled or stale, restart only the identified task-owned process and confirm a changed marker before judging post-fix captures.

**Done when:** the target revision, design authority, run command, fixture mechanism, browser harness and selection reason, Dark Reader setup or exception, browser capabilities, and external-action boundary are recorded in the run's evidence.

## 2. Inventory surfaces and state transitions

Read [coverage-and-evidence.md](references/coverage-and-evidence.md) to create a finite coverage matrix and capture manifest. A **surface** is a route or distinct user-visible state: menus, dialogs, drawers, tabs, editors, validation, and recovery states count even without a URL change.

Inventory from both source and browser navigation. Include every in-scope route and primary workflow, then expand high-risk combinations: layout modes, themes, permissions, long content, data density, short viewports, and asynchronous results. Exercise actions that enter, change, leave, and recover each state. Use exact expected content or outcomes, not merely nonempty output.

Distinguish source-implemented, entry-wired, and browser-reachable surfaces. For dormant components, locate the intended entry or test in an isolated component harness when in scope; otherwise record a reasoned exclusion or unresolved reachability. Do not add a production route solely to obtain coverage.

Start with representative desktop, tablet, phone, and narrow supported widths (often 1440, 768, 390, and 320 CSS pixels). Add both sides of actual breakpoints and short-height/landscape views where controls or overlays are constrained. Enumerate all supported theme choices; test System against both OS schemes. Track authored theme, OS scheme, and Dark Reader state separately; a browser transformation does not establish an authored dark theme. Include Dark Reader-on cases for primary workflows at desktop and phone widths and for vulnerable controls, overlays, images, and dense content.

Use risk-based combinations outside critical paths instead of multiplying every axis blindly. State omissions explicitly. Assign stable case IDs and expected assertions before running. If delegation is available, split independent route families or visual review with isolated fixtures and output paths; retain one owner for shared CSS and the final matrix.

**Done when:** every inventoried surface has case IDs or a reasoned exclusion, every primary transition has an expected result, and high-risk combinations are explicit.

## 3. Capture trustworthy evidence

Before implementing a capture harness, read [browser-checks.md](references/browser-checks.md). Use its readiness contract, geometry probes, and diagnostic guidance with the existing test runner.

Observe console errors, uncaught exceptions, failed requests, and relevant HTTP failures before navigation. Assert application readiness, exact fixture state, actual theme, required fonts, and image decode. Use bounded waits tied to state. Preserve intentional loading/error states with controlled fixtures. A missing asset is a failure to diagnose, not permission to hide it.

Capture full-page context plus viewport images for sticky controls, menus, dialogs, and focused editing; add component crops for dense details. Restore scroll position after preparing lazy assets. Ordinary captures close incidental menus, while menu-open cases keep them open deliberately. Do not remove product UI or change product styles to make a capture pass. Record any capture-only suppression of development chrome or animation stabilization.

Write artifacts under unique run/case/attempt paths, using test-runner output paths where available. Record CSS viewport separately from raster dimensions and device scale. Keep before evidence when fixing a defect; never silently overwrite it with a later attempt.

**Done when:** every executed case has reproducible state setup, readiness results, diagnostics, assertions, and traceable images, or a recorded capture failure.

## 4. Inspect and correct

Inspect every capture counted as reviewed using an image-capable tool. Contact sheets help triage; inspect each state at a readable scale and open full-resolution crops for dense text, controls, or suspected defects. If images cannot be inspected, keep visual review incomplete. Screenshots are evidence, not assertions by themselves.

Review hierarchy, spacing, readable proportions, text wrapping, icon containment, card density, preview/control balance, scroll effort, sticky obstruction, stacking, contrast, and state feedback against the existing design. In Dark Reader cases, also inspect text/background contrast, focus and selection visibility, icons/logos, images, and semantic status colors. Test pointer, touch emulation, and keyboard behavior: visible focus, tab order, selection, Escape, focus return, outside clicks where intended, input retention, disabled/pending controls, and recovery. Test real zoom or assistive technology only when available; narrow-width emulation is not proof of either.

Record each finding with case ID, severity, symptom, before image, reproduction, root cause, and verification condition. Classify product defects separately from fixture/harness defects before changing code.

Fix root causes in shared components/styles, then check their consumers. Prefer reflow and content-aware sizing over shrinking text, hiding controls, clipping glyphs, or global overflow suppression. Preserve all actions when adapting a desktop table into mobile cards. Keep useful error feedback visible; collapse routine detail only when it obstructs the workflow and preserves semantics.

Add regression assertions that would fail on the observed defect: child-inside-button geometry, non-overlap, reachable dialog actions, exact state changes, or a reviewed focused visual baseline. Never approve a visibly broken baseline or weaken an assertion to accept a regression.

**Done when:** every inspected defect is corrected and linked to a regression check, or remains explicitly unresolved with its reason and impact. Unresolved in-scope defects prevent an unqualified completion claim.

## 5. Recheck and hand off

Rerun corrected cases, shared-component consumers, and the final coverage matrix against the resulting revision. Recapture affected evidence and inspect it again. Run relevant existing build, type, lint, and test checks. When fixing capture instability, demonstrate repeatability with two clean consecutive targeted runs; retries alone do not establish stability.

Reconcile every planned case as passed, failed, blocked, or excluded with reason. A case passes only after its required behavior, geometry, diagnostics, and visual review pass. Deduplicate retries when reporting case totals. Report fixes separately from test/fixture changes so the user can see actual product improvements.

- [ ] All in-scope surfaces and primary transitions have final dispositions.
- [ ] Captures counted as reviewed were actually inspected.
- [ ] Fixed findings have after evidence and passing regression checks.
- [ ] Dark Reader cases have reviewed evidence and final dispositions; opt-outs and capability gaps are explicit.
- [ ] No known in-scope issue is hidden by a screenshot baseline, skip, mock, or CSS clip.
- [ ] Final report links matrix, manifest, representative before/after images, commands/results, and unresolved limitations.

**Done when:** the scoped sweep passes these bounds, or the handoff clearly reports partial completion and the exact blockers. Do not turn base-mode artifacts into a public showcase unless requested.

If the user says "ready for a later showcase," retain private capture provenance and candidate case roles now. Showcase construction and public asset curation remain deferred until requested; future reuse requires matching revision and passing evidence.

## Maintaining these instructions

Review trigger boundaries, linked resources, terminology, and observable completion criteria together. Keep the entry point concise and disclose detailed guidance through references. Validate all relative links and bundled helpers before publishing. No external authoring skill is required.

Skill instructions

Supporting instructions

surface-sweep/references/coverage-and-evidence.md

# Coverage and evidence

Read when planning a sweep and recording its results. Use the repository's existing evidence format where equivalent; the fields below define meaning, not a mandatory framework.

## Matrix

Each case has: ID, surface/route, initial fixture and role, action sequence, expected visible result, browser engine, CSS viewport, device scale, authored theme/OS scheme, Dark Reader mode (`off`, `extension`, or `api`) and effective state/settings, assertions, capture kinds, and disposition. Use stable IDs rather than screenshot filenames as identity. Give native and Dark Reader-on variants distinct case IDs so their coverage and baselines cannot be conflated.

Use `planned`/`not-executed` during preparation; final sweep dispositions must reconcile these to executed results, blockers, or reasoned exclusions. A user-requested planning-only exercise reports zero executions and does not claim a completed sweep. Report parameterized case families separately from expanded case IDs; neither planned families nor retries count as executed unique cases.

Inventory applicable categories:

| Surface | States and transitions that frequently expose defects |
| --- | --- |
| Shell/navigation | First load, active tab, collapsed/expanded navigation, deep link, back/forward, scrolled content, theme persistence |
| Lists/details | Empty, one item, typical and dense lists, long unbroken text, multiline notes, filter/no results/clear, pagination, missing optional metadata |
| Editors/configurators | Every mode, selected/unselected options, min/max values, long input, linked controls, reset/undo, preview updates, persistence/reload |
| Forms/overlays | Open, focus entry, invalid submit, corrected input, pending, success, error/retry, close/reopen, bottom actions, scroll locking and focus restoration |
| Account/permissions | Signed out, supported signed-in roles, protected navigation, unavailable/expired session, role-specific controls |
| Async/provider flows | Slow response, expected rejection, network failure, retry, stale/expired data, duplicate click prevention; label mocked versus live |

Apply actual product limits: test accepted maxima and one invalid input when validation is in scope. Include real-shaped synthetic fixtures as well as adversarial strings; a showcase-friendly example alone is weak QA. Do not silently replace a requested exact fixture with an approximation.

Separate the current source behavior from the intended acceptance condition. Resolve exact assertions from the product contract, domain rules, or established tests; an existing misleading success message is not its own correctness oracle. If the needed contract is unavailable within scope, record that uncertainty and continue independent coverage rather than inventing an expected value.

Freeze or inject fixture time where dates, countdowns, renewals, or expiry affect states. Record timezone and locale when formatting matters. Keep identical data across before/after comparisons; wall-clock-relative fixtures otherwise change the image without a product change.

Cover critical state transitions at desktop and mobile, every supported layout/theme on representative surfaces, and vulnerable components across their breakpoint edges. For omitted combinations record why sampled coverage is sufficient. A broad sweep has no fixed screenshot quota.

## Capture manifest

Keep one run manifest with target URL/environment, source revision and dirty-tree note, timestamp, startup/test commands, browser harness and selection reason, browser/version/OS, Dark Reader version/setup or opt-out/limitation, fixture version/seed, capture stabilization policy, and cases. Keep private session files and raw diagnostic payloads out of public artifacts.

For each case record:

```json
{
  "id": "editor-validation-phone",
  "surface": "/editor",
  "state": "invalid-submit",
  "fixture": "synthetic-long-title-v1",
  "role": "local-test-user",
  "viewport": { "width": 390, "height": 844 },
  "deviceScaleFactor": 2,
  "browser": "chromium",
  "theme": "light",
  "osScheme": "light",
  "darkReader": { "mode": "off", "enabled": false },
  "providerMode": "mocked",
  "attempt": 1,
  "status": "failed",
  "readiness": "passed",
  "assertions": { "errorVisible": "passed", "actionsReachable": "failed" },
  "visualReview": "reviewed",
  "captures": [{ "kind": "viewport", "path": "before/editor-validation-phone.png", "rasterWidth": 780, "rasterHeight": 1688 }],
  "findings": ["UI-003"]
}
```

This is an illustrative failed case, not proof of a run. Add diagnostics and rerun evidence in the project's format. Use `not-reviewed` until inspection occurs. Capture failure or unavailable auth is `blocked`/`failed`, never a pass. Exclusions need a reason and must appear in the denominator explanation.

## Findings and report

Each finding records symptom and impact, affected cases, severity, before image, reproduction, root cause, changed source, regression check, after image, and final disposition. Prioritize blocked tasks/data loss, inaccessible actions, overlap/clipping, and then proportions/spacing. If no product fix is needed, state that conclusion with actual review coverage.

Report distinct counts: planned cases; unique executed cases; passed/failed/blocked/excluded; captured states; inspected states; product findings fixed/open; harness findings fixed/open. List browser, physical-device, and Dark Reader gaps; distinguish extension results from API simulation. An 80-image run with five reviewed images is five reviewed images.

Keep raw captures/logs in ignored or external run directories. Retain minimal approved regression baselines according to repo policy. Curated public assets belong only to the showcase workflow. Do not commit an entire transient corpus just to preserve a screenshot count.

Skill instructions

Supporting instructions

surface-sweep/references/browser-checks.md

# Browser checks

Read when implementing or adapting the harness. Prefer existing test helpers and installed tool documentation. The optional [browser-probes.mjs](../scripts/browser-probes.mjs) exports two browser-context functions usable with permitted Playwright/Puppeteer `page.evaluate`. Import it into a project harness or copy the needed function into a maintained test helper. No browser package is bundled or installed by the script.

## Dark Reader setup and verification

Use an actual Dark Reader extension in an isolated test profile/context when the permitted harness supports it. Otherwise, when script injection is permitted, use the [official Dark Reader API](https://github.com/darkreader/darkreader#using-dark-reader-on-a-website) from a versioned local test bundle. Keep this tooling outside the shipped app and its runtime dependencies. API injection is simulated compatibility evidence; only an extension run establishes extension behavior. OS dark-mode emulation and CSS inversion are not substitutes for Dark Reader.

### Playwright extension preflight

Use a fresh persistent profile and headed Chrome for extension cases. Keep the extension directory, profile, and ID in local runner configuration or environment variables; never reuse a personal browser profile or commit the extension binary. Playwright launch flags can appear to succeed while Chrome ignores the extension, so assert it is present before capture. For Chrome builds that support the CDP Extensions domain:

```js
import { chromium } from 'playwright';

const profileDir = process.env.PLAYWRIGHT_PROFILE_DIR;
const darkReaderDir = process.env.DARK_READER_EXTENSION_DIR;
const darkReaderId = process.env.DARK_READER_EXTENSION_ID;
if (!profileDir || !darkReaderDir || !darkReaderId) {
  throw new Error('Set an isolated profile, Dark Reader directory, and extension ID');
}

const context = await chromium.launchPersistentContext(profileDir, {
  channel: 'chrome',
  headless: false,
  ignoreDefaultArgs: ['--disable-extensions'],
});
const browser = context.browser();
if (!browser) throw new Error('Persistent Chrome browser is unavailable');

const cdp = await browser.newBrowserCDPSession();
let { extensions } = await cdp.send('Extensions.getExtensions');
if (!extensions.some(extension => extension.id === darkReaderId)) {
  await cdp.send('Extensions.loadUnpacked', { path: darkReaderDir });
  ({ extensions } = await cdp.send('Extensions.getExtensions'));
}
if (!extensions.some(extension => extension.id === darkReaderId)) {
  throw new Error('Dark Reader did not load in this Playwright context');
}
```

If this CDP method is unavailable, use the browser's supported extension-loading method and keep the same presence and visual checks. In the isolated profile, grant Dark Reader host access to the test origin (`chrome://extensions/?id=…`); Chromium may default to “On click.” Prefer access limited to the local or preview origin. Do not treat installation alone as permission to transform the page.

Before app screenshots, open a simple light probe served from the test origin and verify that its known light background and text are transformed. This proves extension access even when the product itself uses a native dark theme that Dark Reader leaves unchanged. Then verify the actual target page and record an unchanged native-dark result as such. Repeat the check after creating a new context or changing origins.

Record extension/API version, settings, injection or loading method, and effective enabled state. Assert that Dark Reader is active and that representative computed colors reflect its transformation, then wait for style and geometry stability before capture. Reapply and verify the setup after navigation or reload; check dynamically opened overlays and newly loaded content too. If Dark Reader intentionally leaves a native-dark page unchanged, verify and record that decision instead of claiming a transformed rendering.

Pair Dark Reader-on cases with native cases using the same fixture and viewport in a clean context or with Dark Reader verified off. Keep their captures and visual baselines separate. Diagnose defects in both states; fix product compatibility without disabling Dark Reader, concealing controls, or shipping the test injection as the fix. Recheck native rendering after compatibility changes.

When extension loading and permitted API injection are both unavailable, record the exact limitation and continue native coverage. Preserve any explicit user opt-out. Report unexecuted Dark Reader cases as blocked or excluded with reason; do not silently substitute a native dark theme or claim full compatibility. Respect host injection, network, and CSP restrictions rather than bypassing them to obtain a capture.

## Readiness before capture

1. Observe errors and failed responses before navigation; retain narrow, explained exceptions for intentional error fixtures.
2. Wait for a meaningful app-ready marker and exact expected state. Network idle alone is insufficient for hydration, streaming, or delayed rendering.
3. Set theme through the supported app control and assert its application. Verify the case's Dark Reader state separately using the setup above.
4. Wait for required fonts and images with a deadline. `document.fonts.ready` does not prove a particular face loaded; verify required faces/assets separately where fallback rendering would invalidate the result.
5. Scroll the relevant containers to exercise lazy content, then restore page and nested-container scroll/focus. Do not force virtualized lists into a giant synthetic DOM; capture representative scrolled segments. Capture original sticky positions with viewport images.
6. Assert key geometry is stable across successive frames or bounded polling. Wait for intended transitions; reduced-motion emulation or screenshot animation disabling is a recorded capture policy, not coverage of motion behavior.

`await page.evaluate(waitForAssets, { timeoutMs: 10000 })` waits for document fonts and the images currently present. Its default scope is the document. It rejects broken or undecodable images and times out rather than waiting forever. For a focused crop, pass a selector as `scope`; hidden/offscreen images in that scope are included. Prepare lazy content first. Check CSS backgrounds, SVG external references, canvas/WebGL rendering, and dynamic image insertion with app-specific readiness assertions; the helper cannot prove those ready.

## Geometry and reachability

Document overflow and internal overflow are different. A child can exceed its button while `document.scrollWidth === clientWidth`. A parent with `overflow:hidden` can also conceal a real defect.

Use `page.evaluate(inspectGeometry, options)` to collect document width and **explicit** relationships:

```js
const result = await page.evaluate(inspectGeometry, {
  tolerance: 1,
  contain: [{ parent: '.motion-button', child: '.motion-glyphs' }],
  separate: [{ a: '.detail-title', b: '.detail-actions' }],
  inViewport: ['.dialog-close', '.dialog-submit']
});
expect(result.documentOverflow).toBeLessThanOrEqual(1);
expect(result.issues).toEqual([]);
```

Selectors are examples; replace them from inspected source/DOM. `contain` examines matching descendants in each visible parent. `separate` checks pairs across the two selector sets; scope them narrowly so unrelated repeated rows are not compared. Missing/hidden required targets produce issues. Intentional scroll regions, offscreen carousel slides, tooltips, or decorative overlaps require a narrower relationship, not a global exception.

Bounding rectangles do not establish glyph shape, clipping through all ancestors, contrast, or clickability. Add application assertions for text/icon contents, computed clipping, target sizes, and real keyboard/pointer interactions. For dialogs with scrollable content, check initially visible close controls, then scroll within the dialog and prove bottom actions reachable; do not require the entire dialog body to fit at once. Verify sticky bars do not cover controls at top, middle, and bottom scroll positions.

The bundled probe uses layout-viewport coordinates. For pinch zoom or a real virtual keyboard, record `visualViewport` bounds/offset/scale and test reachability in that visible area separately. A page that fits its layout viewport can still hide essential actions behind browser or keyboard UI.

## Regression and runtime limits

- Assert exact visible output and state transitions alongside geometry. `textContent.length > 0` cannot verify formatting or correct data.
- Missing required controls or fixture records must fail the case, not silently skip an optional-looking branch. Compare executed case IDs with the planned matrix. Standalone scripts must return a nonzero exit status for unexpected failures or missing cases; writing a JSON report and exiting zero is not an automated gate.
- Use screenshot comparisons for stable, reviewed high-value regions. Record engine, OS/fonts, viewport, device scale, theme, and Dark Reader state/settings; do not regenerate baselines automatically after a failure.
- Serialise fixture-mutating tests only when they share mutable state. Otherwise isolate data/context per worker and parallelize independent cases. Never let parallel capture paths collide.
- Capture trace/screenshot diagnostics for the initial failure, including when there are no retries. Check response status as well as network exceptions.
- A mobile device preset using Chromium is Chromium emulation, not Safari. Run WebKit when Safari behavior matters and report engines actually exercised. Virtual keyboard, browser chrome, and hardware behavior require separate evidence.
- Actual extensions must be exercised when extension compatibility is in scope. A theme-lock meta tag proves only markup; API injection and a real extension run are different evidence.
- Keep provider fixtures deterministic and local. UI error/success coverage from mocked responses is not provider integration qualification.
Source and verification details

Canonical skill ID: public/surface-sweep

Freshness: Age: 0 seconds; source check: verified

Main source: surface-sweep/SKILL.md

Main Git blob: 586905bd0ce2974414db8b154a9b392913f10993

Supporting source: surface-sweep/references/coverage-and-evidence.md · 79a4224456f79db9d487fe030f7e7ccbb072c7fb

Supporting source: surface-sweep/references/browser-checks.md · fca3be74c5ecd7d9cbf819c46602256d82e3cf27

  • devin-thomas/skills @ dce5977166216e8e88fcf56b6b53c76aaf91be5c; verified 2026-10-24T07:03:39.411Z