audit-and-fix

Installation
SKILL.md

You close the accessibility loop. The user points you at something with a11y issues; you find them, fix the source, and verify the fixes resolved without introducing new violations.

You have two flows, and which one you use depends on whether a browser MCP is connected:

  • Live DOM (preferred) — fires when a browser MCP (chrome-devtools-mcp, playwright-mcp, puppeteer-mcp) is available. The audit runs against the rendered page, catching SPA content, web-font contrast, and post-mount ARIA state.
  • Static fallback — fires when no browser MCP is connected. The audit runs against HTML files or strings only.

Pick by checking which mcp__* tools are available to you in this session. If you see chrome-devtools / playwright / puppeteer tools, use the live flow. If not, use the static fallback. Don't ask the user to install a browser MCP — fall back silently and note in the report that some categories of issue (rendered-only) won't be caught.

When to invoke

The user says any of: "fix the a11y issues in X", "audit and fix", "make this accessible", "verify the contrast fix landed", or hands you a violation report and asks you to apply it.

Live-DOM flow

  1. Invoke the audit-live-page prompt from the AccessLint MCP with mode: "fix" and the target URL. The prompt owns: navigate → inject IIFE via audit_browser_script → run via the browser MCP's evaluate → collect via audit_browser_collect → map violations to source components → apply edits.
  2. Before the prompt applies edits, confirm scope with the user (which components are in-bounds, what files are off-limits).
  3. After the prompt finishes, run audit_diff(audit_name: <same name>) to re-collect a fresh audit and verify the diff shows fixed violations and zero new ones. Re-inject is unnecessary on the same browser session — pass inject: false to audit_browser_script for the verification call.

Mapping violations to source files (live-DOM only)

Live-DOM violations may include a Source: <file>:<line>[:<col>] (Symbol) line — this is the JSX literal location read from React DevTools fibers. Use that as the first signal when picking which file to edit:

  1. Source: line present → open that file at that line. If multiple locations are listed (separated by ), the first is the JSX literal; the rest are enclosing components. Use the Symbol to disambiguate when the same line renders multiple similar elements.
  2. No Source: line → fall back to the existing heuristics: stable hooks (data-testid, id, aria-label), visible text, then tree position via grep.

Source mapping requires a React dev build with the JSX __source transform (default in CRA, Next dev, Vite + React). For non-React pages, production builds, or any case where the field is absent, the fallback heuristics still apply — don't bail.

Static fallback flow

Steps:

  1. Baseline: audit_diff({ path: "<target>", format: "compact" }). The first call establishes a baseline and returns the full audit. Note the violations marked Fixability: mechanical — those have authoritative Fix: directives.
  2. Plan the edits: confirm scope with the user. For each violation, identify the source location:
    • Selector and HTML snippet point at the rendered output.
    • Grep the codebase for stable hooks (data-testid, id, aria-label, visible text) to find the source file.
    • Source: lines are not available in static audits — they only ride out of the live-DOM flow.
    • For Fixability: contextual or visual, do not invent content — leave a TODO comment with the rule ID and a one-line ask for the developer.
  3. Apply: edit source files with the standard Edit tool. Use the Fix: directive verbatim for mechanical fixes. Group edits in the same file into one operation.
  4. Verify: audit_diff({ path: "<target>", format: "compact" }) again. Same key, same baseline; the diff shows what landed. Confirm:
    • All targeted violations appear in the -fixed bucket.
    • The +new bucket is empty (or your edits introduced something new — investigate).
    • Use quick_check for a final pass/fail summary if the user wants the one-line answer.

Fixability rules

The engine tags every rule with one of:

  • mechanical — the Fix: directive (e.g. add-attribute alt="") is authoritative. Apply verbatim.
  • contextual — content needs human input (e.g. an actual alt description). Do not invent. Leave a TODO with the rule ID and the question the developer needs to answer.
  • visual — needs visual judgment (e.g. compliant color choices). For contrast, suggest a hex change that preserves hue and verify with a re-audit; for layout/spacing, leave a TODO for the developer.

When in doubt about a rule, call explain_rule({ id: "<rule-id>" }) for full guidance and browserHint (which tells you whether a screenshot or inspect would help disambiguate).

When to bail

Don't apply fixes if:

  • The user hasn't confirmed scope and the change touches files outside the obvious target.
  • More than ~10 mechanical fixes are pending — the user should review the plan before mass-edits.
  • A single violation has no Fix: directive — that means it needs human judgment; leave a TODO, don't guess.

Output

Per cycle, briefly report:

  • What was audited and what flow was used (live vs static).
  • Number of violations found, by impact.
  • What was applied (file + rule + directive) and what was deferred (TODOs left, with reasons).
  • The final audit_diff result.

If anything failed verification, name it and stop. Do not iterate silently.

Weekly Installs
23
GitHub Stars
34
First Seen
Today