Agent Browser CLI
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…
Audit 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…
$ npx skills add QinghongLin/data2story-skill --skill auditor -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install QinghongLin/data2story-skill auditor --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/QinghongLin/data2story-skill.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/data2story-pro/auditor .claude/skills/auditor && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "auditor" agent skill from https://github.com/QinghongLin/data2story-skill/tree/main/skills/data2story-pro/auditor into .claude/skills/auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auditor", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/QinghongLin/data2story-skill/tree/main/skills/data2story-pro/auditorType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add QinghongLin/data2story-skill --skill auditor -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install QinghongLin/data2story-skill auditor --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/QinghongLin/data2story-skill.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/data2story-pro/auditor .agents/skills/auditor && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "auditor" agent skill from https://github.com/QinghongLin/data2story-skill/tree/main/skills/data2story-pro/auditor into .agents/skills/auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auditor", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add QinghongLin/data2story-skill --skill auditor -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install QinghongLin/data2story-skill auditor --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/QinghongLin/data2story-skill.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/data2story-pro/auditor .cursor/skills/auditor && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "auditor" agent skill from https://github.com/QinghongLin/data2story-skill/tree/main/skills/data2story-pro/auditor into .cursor/skills/auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auditor", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/QinghongLin/data2story-skill.git --path skills/data2story-pro/auditor--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add QinghongLin/data2story-skill --skill auditor -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install QinghongLin/data2story-skill auditor --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/QinghongLin/data2story-skill.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/data2story-pro/auditor .gemini/skills/auditor && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "auditor" agent skill from https://github.com/QinghongLin/data2story-skill/tree/main/skills/data2story-pro/auditor into .gemini/skills/auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auditor", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install QinghongLin/data2story-skill auditorInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add QinghongLin/data2story-skill --skill auditor -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/QinghongLin/data2story-skill.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/data2story-pro/auditor .github/skills/auditor && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "auditor" agent skill from https://github.com/QinghongLin/data2story-skill/tree/main/skills/data2story-pro/auditor into .github/skills/auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auditor", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add QinghongLin/data2story-skill --skill auditor -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install QinghongLin/data2story-skill auditor --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/QinghongLin/data2story-skill.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/data2story-pro/auditor .opencode/skills/auditor && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "auditor" agent skill from https://github.com/QinghongLin/data2story-skill/tree/main/skills/data2story-pro/auditor into .opencode/skills/auditor/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auditor", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
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…
Auditor is an agent skill from QinghongLin/data2story-skill. Audit 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 see — then having vision agents review the screenshots, playtesting every interactive, and walking the flagship capability contract. Plus VIEW every image for a wrong/AI-faked subject. Fixes layout in place; sends content-correctness…
Its SKILL.md is about 6.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files, including scripts and reference files (for example `references/checks.json`, `references/fix_patterns.json` and `references/flagship_contract.json`).
It sits in Productivity & Automation, covering Browser automation. The repository describes itself as: Data Journalist Agent: Transforming Data into Verifiable Multimodal Story. The licence is MIT.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 63a55c1. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
Bash(*)ReadWriteEditGrepGlobAgentFrom allowed-tools in the SKILL.md frontmatter.
Ships 2 files in scripts/ (JavaScript), which the agent can run.
Shell commands in SKILL.md call:
nodenpmFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npm, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Auditor loads about 6.4k tokens when it runs, and up to ~33k if it reads all its reference files. Until then it costs about 192 tokens; SKILL.md has 2,920 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Bash(*), Read, Write, Edit, Grep, Glob, AgentAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from QinghongLin/data2story-skill at commit 63a55c1, republished under its MIT licence (© QinghongLin). 2,920 words, ~6,376 tokens.
.claude/skills/auditor/SKILL.md (or your agent's skills folder). This skill also uses 6 other files; get the full folder from GitHub.Your job is build correctness — does every element actually render correctly, and is each one right? You audit in two layers:
width:100% but renders 0 px wide (invisible), an <img> that 404s, a slider that does nothing.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.
PROJECT_DIR = first argumentSKILL_DIR = the directory containing this SKILL.md (its capture script is at SKILL_DIR/scripts/render_capture.js)PROJECT_DIR/index.html; also read PROJECT_DIR/designer.json (asset intents), PROJECT_DIR/editor.md (narrative), and list PROJECT_DIR/assets/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:
node "SKILL_DIR/scripts/render_capture.js" "PROJECT_DIR" index.html --probe{"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.PROJECT_DIR/audit/render_report.json. Its findings are hard, deterministic facts — treat them as ground truth, above anything the source CSS implies: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.)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.)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.horizontalOverflow: true → content runs off the page (desktop, 1280px).mobile.horizontalOverflow: true → content runs off the page at a phone viewport (~390×844). The harness runs a separate mobile pass (reported under mobile:{} with _mobile.png). Mobile overflow is a real defect — virality is mobile — and gets the same fix-in-place treatment as desktop overflow (responsive width constraints on the offending chart/table/element). Don't dismiss it because desktop is clean.oversizedAssets / performance.totalOverBudget → an asset (or the whole page) blows the performance budget: audio > 3 MB, single image > 600 KB, video > 3 MB, total payload > ~8 MB. A heavy payload (e.g. a 14 MB FLAC) silently tanks mobile load. This is a send-back to the owning role (Designer for generated media, Scout for sourced media: re-encode/compress/trim or pick a lighter asset) recorded as oversized_asset — not a layout fix. oversized_asset stays for the disjoint referenced-AND-over-budget case; a heavy unreferenced master is not yours to compress — render_report.performance.unreferencedAssets is now ACTIONED downstream (the Inspector's relocate_unreferenced.py moves it to provenance/ at Stage 7, and validate.py Section 16 then asserts assets/ ships no unreferenced heavy master — asset_unreferenced_heavy), so just report it, don't compress it.console entries of type error / pageerror / requestfailed → a JS error or a 404 on an asset (e.g. a missing video/poster).
Each maps to a fix-in-place (layout) or a send-back (content) per the Rules below.The metrics give hard numbers but can't judge taste (ugly default colors, an image whose subject is wrong, a dead interaction). For that, spawn 2–3 vision subagents with the Agent tool, in parallel, each pointed at PROJECT_DIR/audit/shots/*.png + render_report.json + designer.json/editor.md, plus the shared design-quality rubric ../../frontend-design-pro/references/quality_rubric.json scoped to that agent's lens via the rubric's lens_map. Give each a different lens for coverage:
analyst.json; score the rubric groups lens_map maps to this lens (chart_quality + color), and read ../../dataviz-craft/references/axis_label_polish.json + ../../dataviz-craft/references/encoding_craft.json to detect misleading axes / wrong encodings.lens_map maps to this lens (typography + layout_spacing + anti_template)._probe_before.png vs _probe_after.png pair (did the interactive actually change?); score the rubric groups lens_map maps to this lens (motion + accessibility).Instruct each to return STRICT JSON {verdict, findings:[{severity, area, element, evidence, owner, fix_hint}], notes}, to report only what is visibly true in the screenshots/metrics, and to return a PASS/FAIL per criterion id from its rubric groups with the screenshot evidence for each.
Cross-validate: a defect flagged by ≥2 agents, OR by 1 agent and corroborated by a hard metric, is high-confidence → act on it. Lone, unconfirmed minor opinions → note them, don't thrash. Merge the agent consensus with the hard signals, dedup, and route each surviving item to fix-in-place or send-back.
The render audit proves the page renders; the playtester proves every interactive actually works and its numbers are right. It closes the Python→JS-live→Pyodide loop no other gate checks. Run it AFTER Step 0/0b and BEFORE the flagship contract gate (Step 1c), so a dropped/inert/disagreeing playground hard-fails the contract:
node "SKILL_DIR/scripts/playtest_drive.js" "PROJECT_DIR" index.htmlIt reads interaction.json playtest_handoff.build_ids + per_id, and for EACH id finds [data-int="<id>"], scrolls it in, drives every declared control (sets input[type=range]/number values + dispatches input+change, advances selects, toggles checkboxes, .click()s a run/reveal button — a synthetic click can never move a native range, exactly the render-capture pattern), then reads the declared [data-play-out=<id>] readout (NOT whole-container innerText — that misses chart-only changes). It writes PROJECT_DIR/audit/playtest_report.json.
{"skip":true,...} (no puppeteer-core or no browser), it still writes playtest_report.json with ran:false, every check UNVERIFIED, and a blanket human-eyeball flag — it never reports PASS. Log it and continue; interaction correctness is then UNVERIFIED (flag it, don't assume clean — same rule as PIT-06). Like the render skip above, a playtest skip puts the run in UNVERIFIED-for-render: a page with interactives whose playtest never ran is not flagship-verified, and that status propagates to the final deliverable (see the Report section) — never silently certified as flagship.playtest_report.json. It scores five checks per playground (PASS / FAIL / ≈ within noise / UNVERIFIED / NA):interaction_dead_control).data_table figure — exact (within a small relative epsilon) for a derived number, or within a declared Monte-Carlo band for a stochastic one (graded ≈ within noise, sampled 2–3× median, never a hard PASS). A disagreement is a hard interaction_recompute_disagrees — the reader would produce a different number than the article claims.<noscript> + a if(!MODEL){…published;return} static path + prefers-reduced-motion still reveal the number, and the at-rest number is in the static DOM (so a blocked CDN still shows it). No static fallback is a hard interaction_no_degradation.<button>/<input>/<select> (not an onclick div/span), each labelled, hit-area ≥44px, first control takes keyboard focus / Tab-reachable.#verifyToggle on, driving a control does not change the readout (Verify is inspect-only) and clicking the playground opens the provenance drawer. (NA when the page has no verify layer.)playtest_report.json playgrounds[].send_backs[] already carries its type (a canonical name in references/report_types.json: flagship_dropped_supporting_playground, interaction_dead_control, interaction_recompute_disagrees, interaction_no_degradation, interaction_purposeless), send_back_to, severity, detail, evidence. Union them into your auditor.json.send_backs — correctness defects (dead/inert control, recompute disagreement, no degradation, dropped playground) go to the Programmer / Interaction Engineer via the Auditor's existing ≤2-round loop; purpose/abundance defects (a playground with no INFORM/IMMERSE purpose, a widget-pile) go to the Critic loop. No new third loop. Dedup with the render metrics + the pitfall walk on element+role so an int_NN co-flagged by the playtester and the Critic is routed once, not thrashed across both loops.needs_human_eyeball, never self-approved): animation feel, payoff legibility, "does it delight." Carry its needs_human_eyeball notes into your report; the final visual/feel sign-off is the user's, not a headless self-approval.Whether or not the browser ran, also run the cheap source checks for known layout pitfalls (unwrapped visuals, missing spacing, centering, responsive gaps). The grep commands + patterns are in references/checks.json. These run even with no browser and catch some issues pre-render.
Run each known-pitfall detect. Walk ../../frontend-design-pro/references/pitfalls.json (the curated 错题本 of past-run bugs) and execute every entry's detect (its grep/check) against this page — width:container charts not routed through embedChart, breakouts using margin:auto instead of margin-inline:calc(...), SVGs overflowing their card, per-section scrim seams, starved card bars, autoplay-on-load audio, IP-risky proprietary numbers, oversized/orphaned media. Each hit maps to the matching remedy in fix_patterns.json (fix-in-place) or a send-back to the owning role.
Walk references/flagship_contract.json — the IF-THEN contract for flagship-grade elements the dataset EARNED but the page may have silently dropped. For each entry:
trigger by reading the role JSONs / the shared topic_profile it names (editor.json lead ana_*, analyst.json calculation, interaction.json centerpiece and supporting[], designer.json chart/asset-array items, scout.json asset arrays, cinematographer.json meta.mode, ../references/topic_profile.json). The interactive_supporting_set entry reads interaction.json.supporting[] and the Step 0c audit/playtest_report.json (each supporting id must resolve to a wired element AND have passed the playtester — fires==PASS and recompute_oracle within tolerance). If the trigger is false (the capability isn't present — e.g. an abstract/statistical dataset with no computed headline, no centerpiece, no charts, no cinematic mode), SKIP the entry. By construction an abstract dataset trips none of these.find/pattern. A hard entry whose required artifact is missing/broken is a hard send-back — record it in auditor.json.send_backs with send_back_to = the entry's role and type = its report_type. A soft entry that misses is an advisory — note it (do not block); record it as a low-severity send-back or in notes.check_* (named in each entry's ref): responsive_charts↔PIT-01, multi_asset_gallery↔PIT-21/check_6, cinematic_background↔validate.py §6. If that pitfall (or a hard render metric like zeroWidthCharts) already flagged the same element, route it once — do not double-send. Use the canonical type/report_type names from references/report_types.json.This is a WHAT-to-check layer reusing the existing send-back machinery; it adds no new gate beyond auditor.json.send_backs.
List assets (ls PROJECT_DIR/assets/) and read designer.json. Read (view) each image asset and confirm it depicts its intended subject — especially that no AI-generated image poses as a specific real object/place/person (the trophy / stadium / flag test). Check each video's poster + duration + refs, each chart mount for inlined data + valid encoding fields, and each interactive's wiring against the ids/data it needs. (When the render audit ran, prefer its screenshots/metrics for "did it render"; use your own image-viewing for "is the subject right".)
For each LAYOUT issue, use Edit for minimal, surgical changes (prefer inline styles). Before/after templates for the common fixes are in references/fix_patterns.json. Do not "fix" a correctness problem by editing pixels or rewriting content — record it as a send-back.
After edits: if the render audit ran, re-run render_capture.js and confirm the previously-failing findings are gone — e.g. zeroWidthCharts is now empty, the 404 resolved, overflow cleared. That is real evidence the fix worked, not "the CSS looks right now." Then confirm all data-* attributes intact, no prose changed, asset paths unchanged (except a corrected ref), and re-grep for residual static issues (verify_after_fixes in fix_patterns.json). The capture→fix→recapture loop is bounded to ≤2 rounds; then record any residual issues and proceed.
render_report.json says a chart is 0-width, it IS invisible to readers no matter what the CSS text says.<style> unless necessary).data-des, data-ana, data-edt, id, class.auditor.json.send_backs with its owning role; never rewrite content or regenerate assets yourself.oversized_asset. You don't compress assets yourself.mobile.horizontalOverflow like desktop overflow and fix it in place (responsive width on the offending element); never wave it through because the desktop pass was clean..vega-embed to display:block; width:100%; center narrower charts via .vega-embed svg{display:block;margin:0 auto} — never .vega-embed{display:inline-block}, which makes Vega measure 0 width). A blank chart from missing data/encoding is a send-back to the Programmer.Write PROJECT_DIR/auditor.json:
{ "render_audit": {"ran": true, "status": "verified", "verdict": "issues",
"zeroWidthCharts": [], "visibleCssLeak": [], "consoleErrors": 1,
"mobileHorizontalOverflow": false, "totalPayloadMb": 19.2,
"agents": 3, "confirmed_by_vision": ["des_07 video block"]},
"fixes": [ {"type": "chart_mount_zero_width", "count": 1, "lines": [245]} ],
"send_backs": [ {"type": "missing_asset", "element": "des_07", "severity": "high",
"send_back_to": "designer", "resolution": "fixed",
"detail": "assets/trophy_push.mp4 returns 404 — fetch/generate the video or drop the block",
"evidence": "render_report console 404 + 2 vision agents"},
{"type": "oversized_asset", "element": "assets/scout_bgm.flac", "severity": "high",
"send_back_to": "scout", "resolution": "blocker_recorded",
"blocker_reason": "only licensed track available; demo-gated, swap before publish",
"detail": "13.4 MB FLAC (budget 3 MB) — re-encode to a compressed format or trim; total payload 19.2 MB > 8 MB",
"evidence": "render_report.performance.oversizedAssets"} ] }Set render_audit.ran=false when the browser wasn't available (static-only run). Use [] for empty arrays. Canonical type names are in references/report_types.json.
Every send-back carries a resolution (fixed | blocker_recorded | open) + a blocker_reason. A send-back is open until acted on; after a clearing re-run set resolution:"fixed", and if the call can't be fixed (a false positive, or a genuinely-unfixable constraint) set resolution:"blocker_recorded" with a blocker_reason. A false-positive or non-fixable call is recorded as resolution:"blocker_recorded" with a blocker_reason — NEVER a silent severity-downgrade or omission (the contract gate's Section 15 fails any send-back left open or any hard playtest fail with no matching resolution).
render_audit.status propagation. When render_capture.js OR playtest_drive.js skipped (no browser/puppeteer), set render_audit.status="UNVERIFIED-for-render" (alongside ran=false); otherwise status="verified". This status is load-bearing, not a log line: an UNVERIFIED-for-render run has its whole render/interaction class unchecked, so it must not be presented as flagship-verified. The orchestrator carries this status into the final deliverable — the page is surfaced as "render UNVERIFIED (no browser available); not flagship-verified" rather than silently shipped as flagship-quality. (A verified run with zero outstanding findings is the only state that may be called flagship-verified for render.)
Modified PROJECT_DIR/index.html (layout fixed) + PROJECT_DIR/auditor.json (render_audit + fixes + send_backs) + PROJECT_DIR/audit/render_report.json + PROJECT_DIR/audit/shots/*.png.
Done when: the live render audit reports no blank/0-width charts, no broken media, no desktop or mobile overflow, no oversized assets / over-budget payload, and a working interaction (or those are recorded as send-backs — oversized assets to Designer/Scout); every image subject has been verified; and the static checks are clean.
The live render audit needs puppeteer-core (in the skill repo's node_modules/) + an installed Chrome or Edge. If absent, render_capture.js prints {"skip":true} and the Auditor runs static-only — the skill never breaks for users without a browser. To enable: run npm install puppeteer-core in the skill repo root; set the CHROME_PATH env var if the browser is in a nonstandard location.
You are the lead of the Auditor team. Your member is the Critic (5-dimension content-quality review). You two are orthogonal lenses on the same finished page: you judge build/render correctness, the Critic judges whether the article is actually good. Together you produce the page's two send-back streams.
Skill critic PROJECT_DIR at Stage 6.5, after you finish. The Critic reads the rendered index.html, verifier.json, and the role JSONs.auditor.json.send_backs (render/build correctness — blank charts, broken/oversized media, overflow, dead interactions) and the Critic's critic.json.dimensions[].send_back_to (5-dimension content quality) are produced independently and can both flag the same element from different angles. Before any upstream role is re-run, the two streams must be unioned and de-duplicated so a co-flagged element is routed once (one consolidated fix to its owning role), not fixed twice or thrashed between rounds. Each item still carries its own severity/detail/evidence; dedup is on the target element + owning role.verify.py fall between you and the Critic, and are orchestrator-owned. After you finish (Stage 6) the top orchestrator runs the contract gate validate.py and the Inspector team's verify.py (Stage 6.4) before invoking the Critic, so the Critic scores against a contract-valid page with a fresh verifier.json. The bounded revision loop (max 2 rounds) that applies the merged send-backs — re-running the Programmer, you (the Auditor), validate.py, verify.py, then the Critic — is run by the orchestrator, not by this team.This is coordination prose, not a new gate: your auditor.json shape (render_audit + fixes + send_backs), the canonical type names, and your fix-in-place vs send-back rules are all unchanged.
© QinghongLin, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 6 other files (scripts, references) in skills/data2story-pro/auditor of QinghongLin/data2story-skill.
Open the folder on GitHubat commit 63a55c1
Auditor next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Auditor this skillQinghongLin/data2story-skill | 156 | — | ~6.4k | Automated safety check: Notes | MIT | |
| Agent Browser CLIvercel-labs/agent-browser | 44k | 24 repos | ~864 | Automated safety check: Pass | Apache-2.0 | |
| Dev Browser AutomationMemTensor/MemOS | 12k | 3 repos | ~1.7k | Automated safety check: Pass | Apache-2.0 | |
| Electron App Automationvercel-labs/agent-browser | 44k | 5 repos | ~1.7k | Automated safety check: Pass | Apache-2.0 | |
| Next Dev Loopvercel/next.js | 143k | 9 repos | ~2.3k | Automated safety check: Pass | MIT | |
| Skyvern Browser AutomationSkyvern-AI/skyvern | 23k | 1 repos | ~2.9k | Automated safety check: Pass | AGPL-3.0 |
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…
MemTensor/MemOS
Automates a real browser through short TypeScript scripts that keep page state between runs, for navigating, filling forms, taking screenshots and extracting data.
vercel-labs/agent-browser
Automates Electron desktop apps such as VS Code, Slack or Discord by connecting agent-browser to their Chrome DevTools Protocol port.
vercel/next.js
Verify Next.js runtime behavior after editing app code. An agent skill from vercel/next.js.
Skyvern-AI/skyvern
Picks the right Skyvern CLI command for a web task, from quick yes/no checks to reusable multi-page workflows, instead of falling back to plain page fetching.
zenstory-ai/oh-story-claudecode
Drives a Chrome window over the DevTools Protocol with the agent-browser CLI, so the agent can reuse your logged-in sessions, read pages and pull tokens.
QinghongLin/data2story-skill
Run sentence-level traceability verification on a Data2Story blog (verify.py - verifier.json), then emit the in-page Inspector panel (the reader-facing runnable verifier) + the verify/ artifacts…
QinghongLin/data2story-skill
Review a finished Data2Story blog against the 5 quality rubric dimensions (visualdesign, narrativepacing, datamethodtransparency, claimdataalignment, insightvalue), score each 1-7 with on-page…
QinghongLin/data2story-skill
Research external context for a dataset — domain background, history, related studies, and why this data matters.
QinghongLin/data2story-skill
Run sentence-level traceability verification on a blog, then generate viewer.html with interactive evidence panel.
QinghongLin/data2story-skill
A skill your agent uses to turn a dataset into a verifiable multimedia blog (a data story / data-driven article / interactive dashboard from a dataset).
QinghongLin/data2story-skill
Generate text embeddings via OpenRouter using Qwen3-Embedding-8B.
Categories
Audit 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…. Auditor is an agent skill from QinghongLin/data2story-skill. Audit 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 see — then having vision agents review the screenshots, playtesting every interactive, and walking the flagship capability contract.
Auditor fits situations like: tasks that involve Browser automation.
Run `npx skills add QinghongLin/data2story-skill --skill auditor -a claude-code`. Or copy the skill folder (skills/data2story-pro/auditor in QinghongLin/data2story-skill) into .claude/skills/auditor in your project. Claude Code loads it when a task matches its description.
Run `npx skills add QinghongLin/data2story-skill --skill auditor -a codex`. Or copy the skill folder (skills/data2story-pro/auditor in QinghongLin/data2story-skill) into .agents/skills/auditor in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add QinghongLin/data2story-skill --skill auditor -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/auditor, .gemini/skills/auditor, .github/skills/auditor and .opencode/skills/auditor in your project.
Going by SKILL.md and its folder, Auditor needs JavaScript for the scripts in its folder and the command-line tools its instructions call (node and npm). Our summary lists: Node.js. Its frontmatter pre-approves these tools: Bash(*), Read, Write, Edit, Grep, Glob, Agent.
SKILL.md contains no URLs. Its commands use npm, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Auditor is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.4k tokens (SKILL.md is roughly 26k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 27k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Auditor: Agent Browser CLI (vercel-labs/agent-browser, 44k stars), Dev Browser Automation (MemTensor/MemOS, 12k stars), Electron App Automation (vercel-labs/agent-browser, 44k stars) and Next Dev Loop (vercel/next.js, 143k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
QinghongLin (a GitHub user) maintains it in QinghongLin/data2story-skill, which has 156 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on July 5, 2026.
Source: QinghongLin/data2story-skill on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.