data2story

$npx mdskill add QinghongLin/data2story-skill/data2story

Orchestrates a multi-agent pipeline to turn a dataset into a blog post.

  • Solves the problem of transforming raw data into a polished narrative blog.
  • Depends on Bash, Read, Write, Glob, Grep, Skill, Agent, WebSearch, WebFetch tools.
  • Decides actions by running detective, analyst, editor, designer, programmer, auditor, inspector in sequence.
  • Delivers results by creating a versioned project folder with assets, code, and final blog.

SKILL.md

.github/skills/data2storyView on GitHub ↗
---
name: data2story
description: "Data Journalist Agent (Data2Story) — orchestrator: turn a dataset into a blog. Runs detective → analyst → editor → designer → programmer → auditor → inspector in sequence. Creates a versioned project folder for each run."
argument-hint: [data path]
allowed-tools: Bash(*), Read, Write, Glob, Grep, Skill, Agent, WebSearch, WebFetch
---

# Data Journalist Agent (Data2Story)

Turn **$ARGUMENTS** into a blog. Orchestrates the roles below in sequence.

## Setup

Resolve paths before doing anything:

- Never hard-code machine-local paths and never ask the user to export path variables.
- Resolve `SKILL_DIR` = the directory containing this `SKILL.md` (`.../skills/data2story`)
- Resolve `ARCHIVE_DIR` = the ancestor directory that contains `skills/` (two levels up from `SKILL_DIR`, i.e. `SKILL_DIR/../..`)
- Resolve `DATA2STORY_ROOT` = parent of `ARCHIVE_DIR`
- Commands below use symbolic placeholders such as `ARCHIVE_DIR`; replace them with resolved, quoted paths before running Bash.
- `DATA_NAME` = the dataset folder name (e.g. `pick_a_card`)
- `DATA_DIR` = if `$ARGUMENTS` is an existing path, use that path; otherwise use `DATA2STORY_ROOT/data/{DATA_NAME}`
- `TIMESTAMP` = current time formatted as `MMDD_HHMM` (e.g. `0401_1618`): `date +%m%d_%H%M` (run in bash)
- `PROJECT_DIR` = `DATA2STORY_ROOT/project/{DATA_NAME}/blog_{MODEL}_{TIMESTAMP}`
- Create `PROJECT_DIR/`, `PROJECT_DIR/assets/`, `PROJECT_DIR/code/`

## Archival

Immediately after creating `PROJECT_DIR`, snapshot the current skills:

```bash
mkdir -p PROJECT_DIR/archival
cp -r ARCHIVE_DIR/skills PROJECT_DIR/archival/skills
```

This preserves the exact skill versions used for this run.

## Tools available

All media tools route through OpenRouter. Set `OPENROUTER_API_KEY` before any generation call.

Media generation is the Designer's job, so the media tools (text2image, text2video, image2video, text2music, embeddings) live under `SKILL_DIR/designer/scripts/openrouter-*/`. The full list — default models and exact `python3 ...` invocations — is in **[`designer/references/tools.json`](designer/references/tools.json)**; full per-tool docs are each tool's own `SKILL.md` under `SKILL_DIR/designer/scripts/openrouter-*/`.

## Pipeline Overview

The pipeline is a single linear sequence that produces a traceable HTML blog from raw data:

```
DATA → Detective → Analyst → Editor → Designer → Programmer → Auditor → Inspector → final index.html + viewer.html
```

Run each stage in order. Each stage reads the previous artifact(s) before starting. Do not proceed to the next stage until the current artifact is complete.

### Stage 1 — Detective
Input: `DATA_DIR`
Output: `PROJECT_DIR/detective.json`
What: Researches external context — background knowledge, domain history, related findings, why this data matters. Each finding gets a `det_xx` ID.

### Stage 2 — Analyst
Input: `DATA_DIR`, `PROJECT_DIR/detective.json`
Output: `PROJECT_DIR/code/*.py`, `PROJECT_DIR/analyst.json`
What: Exhaustive quantitative analysis of the data, informed by detective's context. All code saved to `code/` as runnable scripts. Each finding gets an `ana_xx` ID with `calculation` (file + lines + output) and `data_table` (chart-ready data).

### Stage 3 — Editor
Input: `PROJECT_DIR/detective.json`, `PROJECT_DIR/analyst.json`
Output: `PROJECT_DIR/editor.md`, `PROJECT_DIR/editor.json`
What: Editorial decisions — which findings matter, what the narrative arc is, what the blog argues. Each section gets an `edt_xx` ID with explicit references to `ana_xx` findings and `det_xx` context. No visual design.

### Stage 4 — Designer
Input: `PROJECT_DIR/editor.md`, `PROJECT_DIR/editor.json`, `PROJECT_DIR/analyst.json`
Output: `PROJECT_DIR/designer.json`, `PROJECT_DIR/assets/*`
What: Data-driven creative visual decisions — how to present each point using charts, images, video, audio, maps, interactives, stat callouts, instances, or text-only treatment when appropriate. The media mix should emerge from the dataset's properties, not from a fixed checklist. The page should be **multimedia-rich by default**: borrow the visual language from the shared [`frontend-design`](../frontend-design/) skill and use all five channels (chart, image, video, audio, interactive/map) unless a channel's documented fallback would be fabricated or purely decorative. Each visual gets a `des_xx` ID with `data_source` pointing to `ana_xx` data_tables when data-driven. Generates selected assets. No HTML.

### Stage 5 — Programmer
Input: `PROJECT_DIR/editor.md`, `PROJECT_DIR/editor.json`, `PROJECT_DIR/analyst.json`, `PROJECT_DIR/designer.json`
Output: `PROJECT_DIR/index.html`
What: Implements the final blog in HTML. Applies the theme/accent recorded in `designer.json` `page_rhythm` and borrows component + token recipes from the [`frontend-design`](../frontend-design/) skill. Resolves chart data from analyst.json data_tables (NO raw data access). Tags every element with `data-edt`, `data-ana`, `data-det`, `data-des` attributes for traceability.

### Stage 6 — Auditor
Input: `PROJECT_DIR/index.html`
Output: `PROJECT_DIR/index.html` (modified), `PROJECT_DIR/auditor.json`
What: Detects and fixes layout issues (overlap, spacing, alignment) without changing content or design intent. Runs automatically after Programmer to ensure visual elements are properly wrapped and spaced.

Call: `Skill auditor PROJECT_DIR`

### Stage 7 — Inspector
Input: `PROJECT_DIR/index.html`, all JSON files
Output: `PROJECT_DIR/inspector.json`, `PROJECT_DIR/viewer.html`
What: Runs sentence-level traceability verification and generates an interactive viewer. Two steps:
```bash
python3 SKILL_DIR/inspector/scripts/verify.py PROJECT_DIR --log-errors
python3 SKILL_DIR/inspector/scripts/generate_viewer.py PROJECT_DIR
```
Step 1 produces `inspector.json` (sentence→evidence mapping). Step 2 produces `viewer.html` (self-contained, works on `file://` — no server needed). See `inspector/SKILL.md` for details.

## Traceability: ID flow through the pipeline

```
det_01 ──┐
det_02 ──┤
         ├──▶ ana_01 (based_on: [det_02]) ──┐
         │    ana_02 (based_on: [])          ├──▶ edt_01 (findings: [ana_01, ana_02], context: [det_01]) ──▶ des_01 (section: edt_01, data_source: ana_01)
         │    ana_03 (based_on: [det_01])    │    edt_02 (findings: [ana_03], context: [det_02])         ──▶ des_02 (section: edt_02, data_source: ana_03)
         └────────────────────────────────────┘
```

Every value in the final HTML can be traced: `HTML data-des="des_01"` → `designer.json des_01.data_source="ana_01"` → `analyst.json ana_01.calculation.code` → verifiable.

## Handoff rules

- Each artifact must be complete before the next stage starts.
- If an artifact is missing required sections, fix it before proceeding.
- **Media-richness gate (after Designer, before Programmer):** `designer.json` should exercise all five channels (chart, image, video, audio, interactive_or_map). For any channel marked `used:false`, confirm its documented fallback was genuinely tried and a data-grounded reason recorded in `meta.media_decisions`. If a channel was skipped for convenience rather than because the data can't support it, send it back to the Designer before the Programmer runs.
- All generated assets go into `PROJECT_DIR/assets/` only.
- Final deliverables: `PROJECT_DIR/index.html`, `PROJECT_DIR/detective.json`, `PROJECT_DIR/analyst.json`, `PROJECT_DIR/code/*.py`, `PROJECT_DIR/editor.md`, `PROJECT_DIR/editor.json`, `PROJECT_DIR/designer.json`, `PROJECT_DIR/inspector.json`, `PROJECT_DIR/viewer.html`.

More from QinghongLin/data2story-skill

SkillDescription
analystExhaustively profile a dataset and list ALL possible analyses — distributions, correlations, rankings, trends, group comparisons, anomalies. Reads detective.json for context. Runs after the Detective/Scout, before the Editor. Outputs analyst.json with ana_xx IDs and chart-ready data_tables.
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 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 problems back to the owning role. Use at Stage 6 after the Programmer assembles index.html and before the Critic; re-runs each revision round. Triggers: a built index.html exists, or you need to confirm charts/media/interactions actually render.
cinematographerDesign the MANDATORY cinematic scroll experience (every blog ships one): a full-bleed, scroll-driven background — primarily from the Scout's verified real imagery — plus the global motion choreography, so the narrative unfolds like a film as the reader scrolls. Owns the BACKGROUND layer + page-level motion (not the Designer's per-section visuals, not the Interaction centerpiece — it stages them inside the scroll). Outputs cinematographer.json (cin_xx scenes). There is no off path: a topic with no sourceable real imagery falls back to a generative-atmosphere or data-driven-spine background, never to a bare column.
copywriterName the piece — re-write the masthead (headline + standfirst + kicker), every section title, and every figure/photo/table caption to a research-driven titling standard, killing the AI-tell patterns (the 'flat statement. flat counter-statement.' two-beat above all) a competent default falls into. Reads editor.md/json + analyst.json + the resolved topic_profile; writes copywriter.json — STRINGS ONLY (masthead{headline,standfirst,kicker}, items{edt_xx:{title}, des_xx:{caption}}), each backed by a real ana_*. Names, never edits: it touches no finding, no number, no data-* id, no layout — so the Verify layer is untouched and the Programmer renders the masthead + figcaptions from copywriter.json verbatim. Runs at Stage 3.5, after the Editor, before the Designer.
criticReview 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.
data2story-proUse to turn a dataset into a verifiable multimedia blog (a data story / data-driven article / interactive dashboard from a dataset). Orchestrator for the Data Journalist Agent (Data2Story): a 7-team newsroom (14 agents) running detective → scout → analyst → imagineer → editor → copywriter → designer → interaction → hero → cinematographer → programmer → auditor → critic → inspector in sequence. Trigger when the user hands over a dataset (CSV/JSON/folder/path) and wants a published story, blog post, or interactive report built from it. Creates a versioned project folder per run.
dataviz-craftA shared reference library for editorial-grade data-visualization craft — Vega-Lite-first with a D3 fallback for charts Vega-Lite can't express. Read by the Designer at chart selection (intent → ranked chart type), the Programmer at implementation (editorial Vega-Lite recipes, annotation layers, axis/label de-clutter, encoding craft), and the Auditor/Critic for chart-quality review. It encodes the FT Visual Vocabulary intent taxonomy, the Cleveland–McGill channel-accuracy ordering, the BBC bbplot de-clutter ruleset, and colorblind-safe encoding rules. Not a pipeline stage — a craft source, like frontend-design.
designerRead editor.md, editor.json, and analyst.json. Make data-driven creative visual decisions for every section — teaser, charts, images, videos, audio, maps, and interactive demos when they fit the data. Generate selected assets. No HTML. Outputs designer.json with des_xx IDs.
detectiveResearch external context for a dataset — domain background, history, related studies, and why this data matters. Outputs detective.json (structured findings with det_xx IDs) before any analysis begins.
editorRead analyst.json and detective.json, make all editorial decisions — what the blog argues, which findings matter, narrative arc and section structure. Runs after the Analyst/Imagineer, before the Designer. No visual design. Outputs editor.md (prose) and editor.json (structure with edt_xx IDs).