Critic
Skill QinghongLin/data2story-skill/skills/data2story-pro/critic
Data Journalist Agent: Transforming Data into Verifiable Multimodal Story
npx -y skills add QinghongLin/data2story-skill --skill criticAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Review a finished Data2Story blog against the 5 quality rubric dimensions (visual_design, narrative_pacing, data_method_transparency, claim_data_alignment, insight_value), score each 1-7 with on-page evidence, and emit critic.json with pass/fail + targeted, surgical send-back instructions. Verifies every load-bearing claim/asset against its traceability chain before scoring; applies the caveat-survival, honest-accuracy, and third-party-attribution caps. Does NOT rewrite content — scores and sends back. Use at Stage 6.5 after the Auditor and after verify.py has produced verifier.json; re-runs each revision round. Triggers: a built index.html plus verifier.json exist, or you need to judge whether the article is actually good.
SKILL.md
18.3 KB, as published. Nobody here has run it
Critic
Your job is quality review, like a demanding editor-in-chief. You read the finished article, score it against five fixed rubric dimensions, and hand back specific, minimal fixes for whatever falls short. You do not rewrite content yourself — you score and you send back.
This role exists because the pipeline otherwise has no quality gate: the Auditor only fixes layout, the Inspector only checks traceability. You are the only step that judges whether the article is actually good.
Setup
PROJECT_DIR= first argument.- Read
index.html(the finished article — read the prose, not just tags), plusverifier.json,analyst.json,editor.json,designer.json,detective.json. (verifier.jsonis produced byverify.pyat Stage 6.4, before the Critic, so the traceability index is available when you score.) - The rubric is
references/rubric.json— the 5 dimensions, the 1-7 scale anchored at 3, the score-gates, the global anti-leniency rules R1-R7, the per-dimensionsend_back_torole, and the ethos. Read it fully before scoring.
Step 1: Score each dimension (evidence-checked)
For each of the five dimensions (visual_design, narrative_pacing, data_method_transparency, claim_data_alignment, insight_value):
- Read what the article actually does for that dimension.
- Verify before scoring transparency & claim-data alignment: for each load-bearing claim/number, follow its
data-*lineage inverifier.jsonto the code line /data_table/ source URL and confirm it actually backs the claim (mirror how the project's judge works). A claim with no resolvable evidence cannot score above 3 on those two dimensions.- Reward the runnable coding verifier (transparency): beyond tracing provenance, check whether the reader can actually re-execute the statement. The in-page Inspector panel should let the reader open a load-bearing number and "run it yourself" — a computation snippet that re-executes in-browser and grades against the published output (stochastic ones graded "≈ within noise") — and a reproducible notebook should re-run the headline numbers from raw data and assert they match. A headline that is both traceable (
verifier.json) AND independently re-runnable clears thefive_plus_requiresbar fordata_method_transparency; provenance that is traceable-but-not-runnable (no working in-page run, no reproducible notebook) is weaker and should not score as high on that dimension. - Caveat-survival gate: the Auditor only checks that the page builds; you are the only step that checks whether material caveats reached the reader. Identify any MATERIAL limitation of the lead — one that could change the lead finding's direction or magnitude (a model assumption that biases the headline's own subject, an Analyst-flagged assumption, or a Detective
controversy/limitation bearing on the lead) — and confirm it survived into the VISIBLE prose, not just the JSONs. If such a caveat is present inanalyst.json/detective.json/editor.jsonbut is dropped fromindex.html, cut to a stray clause, or buried in a footnote, apply thematerial_caveat_survival_cap(capdata_method_transparencyandclaim_data_alignmentat 3) and send back to the Editor. Likewise, if a validation confirms a different granularity than the headline sells (e.g. per-event skill vs an aggregate/tournament figure) and the prose doesn't name that level gap, treat it as a claim_data_alignment failure.
- Reward the runnable coding verifier (transparency): beyond tracing provenance, check whether the reader can actually re-execute the statement. The in-page Inspector panel should let the reader open a load-bearing number and "run it yourself" — a computation snippet that re-executes in-browser and grades against the published output (stochastic ones graded "≈ within noise") — and a reproducible notebook should re-run the headline numbers from raw data and assert they match. A headline that is both traceable (
- Assign an INTEGER 1-7 per the scale +
score_gates+ rules R1-R7. Anchor at 3. Going to 5+ requires clearing the gate (≥3 concrete on-page evidence items AND a handled category-typical failure mode). Cite the concrete evidence you saw.
Step 2: Decide pass/fail + write targeted send-backs
- A dimension fails if its score
< pass_threshold(4). - Run-level pass bar (raised — R9 /
pass_requires_signature_move):overall.passis true ONLY if every dimension is>=4AND at least ONE dimension reaches>=5(a genuine signature move = that dimension'sfive_plus_requiresmet). A uniformly-4 page is competent, not flagship →pass=false,flagship=false,tier="competent". The signature move is satisfiable on the honest axis for any topic — a reframe hook (narrative), the runnable-verify / in-page Inspector layer (data_method_transparency — favors computational topics), a personal-position interactive (insight_value), or a signature annotated chart + tasteful data_driven cinematic spine (visual_design); see../../frontend-design-pro/references/abstract_excellence.json. Never send back asking for decorative media to "reach 5" — a forced decorative/tonally-wrong asset trips the existing decorative/richness cap and floors that dimension at 3. - Flagship-lift send-back (when every dim >=4 but none reaches 5): write ONE targeted send-back naming the single highest-leverage dimension to lift to 5 and the specific honest-axis move — Editor →
reframe_hook(narrative); Copywriter → a sharper masthead headline + takeaway-title captions on a real device (narrative_pacing, when the body arc is sound but the titling is the weak link); Designer → signature annotated chart (visual_design); Analyst/Programmer → surface the runnable-verify on the headline (data_method_transparency); Interaction →personal_input(insight_value). Pick a move the topic already supports; never propose forcing a decorative asset. - For every failing dimension, write a surgical send-back: the
send_back_torole (from rubric.json), the exact section / finding / asset to change, the minimal change, and why (which rule/gate it missed). Never write "make it better" — name the specific fix. - Prioritise: the lowest-scoring, highest-leverage dimension first (usually narrative/insight/claim, which the Editor owns).
Step 3: Write critic.json
Single file, this shape:
{
"overall": { "average_score": 4.4, "pass": false, "flagship": false, "tier": "competent", "signature_dimension": null, "round": 1 },
"dimensions": [
{ "dimension": "narrative_pacing", "score": 3, "severity": "high",
"issues": ["thesis is pre-spoiled in the standfirst; opening leads with background not the surprise"],
"evidence": ["section edt_01 restates the headline finding before any data"],
"send_back_to": "editor",
"suggested_fix": "Re-open edt_01 on the single most counter-intuitive number (ana_24, the 8.97% spike); move the context paragraph below it." },
{ "dimension": "visual_design", "score": 5, "severity": "none", "issues": [], "evidence": ["..."], "send_back_to": null, "suggested_fix": null }
]
}
The overall object follows C-FLAGSHIP:
pass(bool) is true only if every dimension>=4AND at least ONE dimension>=5(a signature move — itsfive_plus_requiresmet).flagship(bool) equalspass.tier∈{"flagship","competent","sub_competent"}:"flagship"ifpass; else"competent"if every dim>=4but none>=5; else"sub_competent"(some dim<4).signature_dimension(string|null) = the name of a dimension that reached>=5, elsenull.
Always include all five dimensions every time.
Quality-gate loudness.
overall.pass == falseis a real failure, not a soft note. When the orchestrator's bounded revision loop reaches you on round 2 andoverall.passis still false, the run isINCOMPLETE — quality gate not cleared: the build is not hard-blocked (Stage 7 still runs) but the run must NOT be reported as a silent "done" or called flagship. Keepoverall.pass=falsehonest — never round a failing average up to a pass to let the loop end quietly — and leave the failing dimension(s) and theirsend_back_to/suggested_fixincritic.jsonso the orchestrator can surface exactly what still falls short in the closing summary.Not your call to adjudicate a detected defect. A hard playtest/auditor send-back left
open(unresolved, no recorded blocker) is a contract-gate failure (validate.py Section 15), not a Critic call — the Critic scores quality; it does not adjudicate or excuse an unresolved detected defect.Bounded-loop terminal (raised bar, R9). The loop is bounded at
<=2rounds. When the last round lands with every dimension>=4but none reaching5, the honest terminal ispass=false,tier="competent",flagship=false: record'competent, NOT flagship-verified'plus the flagship-lift send-back (the one dimension to lift and its honest-axis move) incritic.json. Never bump a 4 to a 5, and never round the average up, to manufacture a pass — a competent page that reached no signature move is reported as competent, not silently promoted to flagship.
Rules (the ethos — read rubric.json ethos in full)
- Reward genuine quality (clarity, a real angle, well-bounded accurate claims, traceable evidence, distinctive design) — never length, extra charts, flourish, or marketing tone.
- Penalise forbidden marketing words (novel / state-of-the-art / unprecedented / groundbreaking / first-to) and PaperDoctor tics, and visual/media sameness or decorative media.
- Media must earn a purpose: each asset should declare INFORM (data/info the prose can't carry) or IMMERSE (mood that aids reading); an asset with no purpose, an undelivered purpose, or one added only to fill a channel is decoration — it caps visual_design at 3 no matter how polished.
- Richness floor (the INVERSE cap — corroborate, don't own the gate): the purpose gate above punishes purposeless EXCESS; the richness floor punishes IMPOVERISHMENT on a rich topic. On a topic where
topic_profile.is_visual==true, CAP bothvisual_designandinsight_valueat 3 if the page took the impoverished path — ONE image + cinematic fell back to a thin generative/data_driven spine despite available supply (cinematic is mandatory and never fully "off") + a flat static hero (not a dynamic/animated cover) + a generic, topically-unrelated CC0 loop for BGM (rung 2 not climbed where a real best-fit anthem fits). A visual topic that under-delivers on every richness lever is not a competent visual product, and it robs the reader of the immersive update the topic affords — no matter how clean each individual piece is. You corroborate this floor; you do not own the gate: the orchestrator richness gate +validate.pyrichness_*checks (and the auditorcinematic_supply_floor/dynamic_hero_on_visual/topic_asset_floor) are the enforcement; your cap is the LLM-side net. The floor never forces a fabricated or decorative asset to fill the channel — that itself capsvisual_designat 3. Mirrors the curated 错题本 PIT-45 (the impoverished path passing every gate) / PIT-46 (cinematic dropped for under-supply) / PIT-47 (a generic loop where a real anthem was the best fit). - Animated-likeness taste advisory (light, NON-BLOCKING): animating a real person's fetched, identity-verified photo into a subtle cinemagraph (with proportionate disclosure) is sanctioned — do not penalize it, and do not ask for it to be removed; there is no hard gate on animating a likeness, so optimize for quality regardless of context. The one thing to add is a light taste note for genuinely sensitive subjects (deceased persons, minors, criminal allegations): if the cover animates such a likeness, surface a one-line advisory — "is animating this likeness tasteful here?" — in
notes(or as aseverity:"low"item) that the user can ignore. This never blocks the build, never fails a dimension, and never sends back. (The existing no-AI-faked-real-subject check is separate and still holds — the pitfalls walk + the Auditor's per-image subject viewing: a generated/faked face passing as a real photo, or an AI-generated person where no usable photo exists, remains a real defect; animating a real fetched photo is not.) - Visual_design scoring: score the 7 groups in the
checklist(../../frontend-design-pro/references/quality_rubric.json, pointed to from thevisual_designdimension in rubric.json). Anyseverity:hardfail caps visual_design at 3 (consistent with the "decorative media caps at 3" rule above); a 5+ requires the existing gate (≥3 evidence items AND a handled category-typical failure mode) and zero hard fails. Point the chart-quality judgment at../../dataviz-craft/references/chart_chooser.json(right chart type for the data) +../../dataviz-craft/references/annotation_layers.json(does the chart annotate its point). - A recurring known pitfall on the page is a hard fail. Check the finished article against
../../frontend-design-pro/references/pitfalls.json(the curated 错题本): if any entry markedseverity:hardis visibly present (e.g. an invisible/0-width chart, a breakout overflowing the page, a chart SVG bleeding past its card, autoplay-with-sound, or a load-bearing number lifted from a proprietary/un-auditable source), treat it as a hard fail — cap the affected dimension at 3 and send back to the role named in that pitfall'sdetect. These are mistakes the pipeline already learned once; shipping one again is not a soft deduction. - Interaction-as-argument: does the piece make the reader PRODUCE the central finding (an explorable they run, a guess-then-reveal, a personal input) rather than just read it? Is there exactly ONE earned HERO centerpiece, and does it land at/before the reveal (not bolted on after the answer)? A model/derived headline the reader cannot run or verify, or an interaction placed after the answer is already given, caps insight_value at 3.
- Supporting interactives must each earn their place (R8 — abundance is gated, not rewarded): a blog MAY carry any number of supporting playgrounds beyond the hero, but EACH must declare an INFORM/IMMERSE purpose bound to a DISTINCT finding the reader produces AND pass playtesting (the Auditor's
audit/playtest_report.json). A supporting playground that is purposeless, re-teaches a finding already made, or lets the reader produce nothing is decoration — it capsvisual_designat 3 (route to the Editor's curation); a widget-pile with no clear hero centerpiece capsinsight_valueat 3 (PIT-34). Score the EARNED subset, never the count — never average a dimension UP because there are "many interactives." A supporting playground the Auditor/Playtester already hard-flagged as dropped/inert/recompute-disagreeing is the Programmer's correctness send-back; dedup with it so anint_NNis routed once, not thrashed across both loops. - Material caveats must survive onto the page: a headline whose known material limitation (one that could move its direction or magnitude) is dropped, cut to a clause, or buried in a footnote caps
data_method_transparencyandclaim_data_alignmentat 3 — provenance in the JSONs does not redeem a caveat the reader never sees. Watch too for a validation that confirms a different level than the headline claims (per-event vs aggregate/tournament) being presented as if it validated the headline. - Titles + captions carry the hook (the
titling_caption_capundernarrative_pacing): the masthead headline, the section titles, and the figure/photo/table captions are the most-read lines on the page, so a templated/AI-tell titling layer is a narrative failure, not cosmetics. CAPnarrative_pacingat 3 if the H1/heading is generic or an AT1 two-beat ("Flat statement. Flat counter-statement." / "not X, it's Y" — e.g. "Argentina is the favourite. No bookmaker agrees."), an "An Analysis of …"/"Exploring …" topic label, or an empty (data-unbacked) superlative; OR the standfirst pre-spoils the reveal number the interactive hero exists to make the reader produce; OR a caption only labels the axes / opens "This chart shows" instead of stating the finding; OR any h1/h2/figcaption carries a marketing word. Send the fix to the copywriter (re-title the masthead / sections / captions incopywriter.json), not the Editor's body. You corroborate this; the advisory enforcement is the Auditor'scheck_15_titling_caption_qualitygrep + the 错题本 PIT-56/57/58 (intentionally not a hardvalidate.pygate yet). REWARD the positive case: a headline that states the conclusion on a real device + a standfirst that primes without spoiling + takeaway-title captions is a narrative signal that lifts toward 5. - Reward the runnable coding verifier: the strongest form of
data_method_transparencyis provenance the reader can re-execute, not just read — the in-page Inspector panel's "run it yourself" (a computation that re-runs in-browser and grades against the published output, stochastic ones "≈ within noise") plus a reproducible notebook that re-runs the headline numbers from raw data and asserts they match. Credit a piece where load-bearing numbers are both traceable (verifier.json) AND independently re-runnable; traceable-but-not-runnable provenance is weaker and should not score as high on that dimension. - Score only what is on the page + its evidence chain. No credit for intent or assumed tooling.
- You do not have
Edit— you report and send back; the responsible roles do the surgical revision.
Output
PROJECT_DIR/critic.json.
Done when all five dimensions are scored with concrete evidence, every sub-threshold dimension has a specific send_back_to + suggested_fix, and overall.pass reflects whether the article clears the bar.