$npx -y skills add QinghongLin/data2story-skill --skill auditorAudit a generated Data2Story blog for build correctness across ALL modalities by ACTUALLY RENDERING it in a real headless browser (when available) — catching blank/0-width charts, broken/oversized media, desktop+mobile overflow, and dead interactions that source inspection cannot
| 1 | # Auditor |
| 2 | |
| 3 | Your job is **build correctness** — does every element actually render correctly, and is each one right? You audit in two layers: |
| 4 | |
| 5 | 1. **Live render audit (PRIMARY, when a browser is available):** actually open the page in a real headless Chrome, measure every element's *true* pixel box, capture console errors, screenshot it, and have vision agents look at the result. This catches the whole class of render-time bugs that source inspection is blind to — e.g. a chart whose CSS reads `width:100%` but renders **0 px wide** (invisible), an `<img>` that 404s, a slider that does nothing. |
| 6 | 2. **Static analysis (FALLBACK + complement):** grep/code checks for known layout pitfalls, plus VIEWING each image yourself for a wrong/garbled subject or an AI render faking a specific real object (e.g. a fake World Cup trophy). |
| 7 | |
| 8 | You fix layout/markup directly; correctness problems you can't fix with a safe markup edit (a wrong/fake image, a blank chart from missing data, a mis-wired interactive, a missing asset) you record and **send back** to the owning role — you never redesign, rewrite prose, or regenerate assets yourself. |
| 9 | |
| 10 | ## Setup |
| 11 | - `PROJECT_DIR` = first argument |
| 12 | - `SKILL_DIR` = the directory containing this `SKILL.md` (its capture script is at `SKILL_DIR/scripts/render_capture.js`) |
| 13 | - Required: `PROJECT_DIR/index.html`; also read `PROJECT_DIR/designer.json` (asset intents), `PROJECT_DIR/editor.md` (narrative), and list `PROJECT_DIR/assets/` |
| 14 | |
| 15 | ## Step 0 — Live render audit (REAL browser) |
| 16 | |
| 17 | Run the capture harness — it drives the installed Chrome/Edge via puppeteer-core (no Chromium download), serves the blog over a local http server, and writes hard signals + screenshots: |
| 18 | ```bash |
| 19 | node "SKILL_DIR/scripts/render_capture.js" "PROJECT_DIR" index.html --probe |
| 20 | ``` |
| 21 | - If stdout is `{"skip":true,...}` (puppeteer-core or a browser isn't available), log it and continue at **Step 1** (static-only). Never hard-fail because a browser is missing — the skill stays portable. **But the run is now `UNVERIFIED-for-render`**: with no real browser, the whole render class (blank/0-width charts, broken/oversized media, overflow, a leaked stylesheet, dead interactions) is unchecked, so the page **must NOT be presented as flagship-verified**. Set `auditor.json.render_audit.ran=false` AND `auditor.json.render_audit.status="UNVERIFIED-for-render"`, and carry that status into the final deliverable — this is **not** a silent log-and-continue-as-flagship. See the Report section for how it propagates. |
| 22 | - Otherwise read `PROJECT_DIR/audit/render_report.json`. Its `findings` are **hard, deterministic facts** — treat them as ground truth, above anything the source CSS implies: |
| 23 | - `zeroWidthCharts` / `zeroHeightCharts` / `chartsWithNoRender` / `hiddenCharts` → a chart that did not actually render → **blank-chart defect**. (Detection is generic: it unions `.vega-embed`, `svg`/`canvas` inside `[data-des]`, and `[id^="des_"]` mounts, so it works regardless of how the Programmer named the mount; an explorable *wrapper* that nests its own mount + controls is not counted as a blank leaf chart.) |
| 24 | - `brokenImages` → an `<img>` that loaded 0×0 → broken/missing image. (Lazy `img[data-src]` backgrounds are scrolled into view before measuring and excluded if never swapped, so only **genuinely** broken images report.) |
| 25 | - `visibleCssLeak` (non-empty) → raw CSS/JS is rendering as **visible body text** — the classic symptom of a premature `</style>` (a stray `</style>`, often inside a CSS comment, closes the raw-text `<style>` element early so the rest of the stylesheet dumps onto the page as text, conspicuous on mobile). Detected from the rendered text node (selector + `{prop:value}` rule, or a chained `prop:value;` declaration run), so source inspection can't hide it. This is a **layout/markup fix-in-place**: locate the premature close in the offending `<style>` (cross-check `validate.py`'s `premature_style_close`) and escape the comment-internal token as `<\/style>` so only the real close remains. Re-render to confirm `visibleCssLeak` is empty. |
| 26 | - `horizontalOverflow: true` → content runs |