Accessible, well-described media is read by both ranking systems and AI extractors — alt text is the primary semantic handle for an image. Reference: references/schema-tier1.md (VideoObject row).
Inputs
Work from the PageSnapshot named in your dispatch envelope: read parsed from <run_dir>/pages/<slug>.json (images[] with alt_present/sized/lazy, iframes, jsonld[]); Grep pages/<slug>.html for verbatim evidence; site artifacts live in <run_dir>/site/{robots.json,sitemaps.json,discovery.json}. Deterministic findings already emitted by audit.mjs are listed in <run_dir>/findings.deterministic.json — do not re-emit those ids; add model-judged findings only. If invoked directly with a URL/path and no snapshot exists, first run node "${CLAUDE_PLUGIN_ROOT}/scripts/snapshot.mjs" <target> --out "${CLAUDE_PLUGIN_DATA}/runs" and use the printed snapshot path.
Audits
Working from the PageSnapshot (parsed_rendered when render.used is not none, else parsed):
- Alt presence: every content
<img>has analtattribute. Distinguish decorative images (alt=""+role="presentation"is correct, not a finding) from missingaltentirely (fail). - Alt quality: not empty on a content image; not the filename (
IMG_2031.jpg); not duplicated verbatim across distinct images; not keyword-stuffed (comma-separated keyword lists are an anti-pattern). Alt should be descriptive and contextual to surrounding content. Target length ~80-140 chars — long enough to be specific, short enough that screen readers/AI don't truncate. - Dimensions:
widthandheightset on<img>(or aspect-ratio reserved in CSS) to prevent layout shift (CLS, a Core Web Vitals input — defer the CWV measurement itself to the perf module). - Format: flag legacy
jpg/pngwhere a modern format (WebP/AVIF) or a responsive<picture>/srcsetwould serve smaller bytes. - Video: embedded video (
<video>, YouTube/Vimeo iframe) withoutVideoObjectJSON-LD — coordinate with M5; required/recommended props inreferences/schema-tier1.md.
Fixes
- AUTO (
fixable: auto): addwidth/heightto<img>from the source asset's intrinsic dimensions (deterministic, additive, verifiable) — emitted as a diff forfix. - PROPOSED (
fixable: proposed): generate contextual alt text inferred from the image plus its surrounding heading/caption/paragraph. Drafts require per-item human accept (alt is editorial). Never fabricate what an image depicts beyond what the page context supports — leave a clearly-markedTODO: describe imageplaceholder when context is insufficient, or ask the user. - ADVISORY (
fixable: advisory): format upgrades (WebP/AVIF,srcset). The tool cannot transcode binaries, so it never writes these — it recommends only.
Verification
- Method
dom_assert: re-parse the snapshot and assert the condition (alt non-empty,width+heightpresent, not a filename, etc.). - When dimension checks need the intrinsic size of a remote asset and no fetch tier is available, status is
needs_api, never a falsepass.
Findings
Emit findings per schema/finding.schema.json; axis both; severity 3 across the module. Severity policy: 5 is reserved for catastrophic, eligibility-killing facts at site/template scope; 4 major · 3 moderate · 2 minor · 1 cosmetic · 0 informational — and only an established severity-5 fail in an active category can cap a score (references/scoring-model.md). Nothing in M9 reaches 4.
M9.alt.missing— content<img>with noaltattribute. statusfail,fixable: proposed, confidenceestablished.evidence.observedquotes the offending<img>tag.M9.img.no_dimensions—<img>lackingwidth/height. statuswarn,fixable: auto, confidencedirectional(CLS link).M9.video.missing_videoobject— embedded video without VideoObject schema. statuswarn,fixable: proposed, confidenceestablished. Each finding:evidence.observedquotes the page;verification.reproduceis runnable, e.g.node "${CLAUDE_PLUGIN_ROOT}/scripts/parse-html.mjs" --snapshot <pages/<slug>.json>(or--url <u>) then inspect theimagesblock (missing_alt,empty_alt,missing_dimensions).expected_impactis banded + confidence-tagged (no naked %).
Honesty
- Alt text aids accessibility and image/AI understanding; treat ranking lift as
directional, not a guaranteed gain — do not promise traffic from alt rewrites. - Keyword-stuffing alt is harmful, not helpful — flag it, never generate it.
- WebP/AVIF reduce bytes (a real perf input) but format alone is not a documented ranking factor; keep it
advisory/lowmagnitude.