Interprets product data and metrics in context, classifying analysis type and producing calibrated insights. Use when asked to "analyze this data", "what does this metric mean", "interpret these numbers", "help me understand this trend", or "analyze this funnel drop-off".
Answer a data question in product context. The skill's job is to turn a product question and data into an insight — not to restate numbers, but to interpret what they mean and what to do about them. The analysis type adapts to the question: metric interpretation, funnel analysis, cohort comparison, or anomaly investigation.
For numeric analyses, the output is not final until it has been bundled and replay-verified. This skill now requires a reproducibility bundle (inputs, derived tables, calculation log, saved code, charts, manifest) and a replay pass using .claude/skills/data-analysis/analysis_runner.py.
Any combination of a question and data:
The input does not need to be clean or complete. This skill works with what's provided and names what's missing.
The most common failure in data analysis is answering the wrong question precisely. Confirm the actual question and what decision it informs before analyzing.
Rich input (specific question stated, decision context clear, data provided): Restate the question and proceed. Example: "Question: why did [metric] drop [X%] last [period]. This informs whether to [decision]. Analyzing the provided data now."
Moderate input (data provided but question vague, or clear question but no decision context): Ask 1-2 targeted questions. Examples:
Thin input (data dump with no question, or a vague "look at this"): Present a structured interpretation:
Here's what I think the question is — correct me:
- Question: [Inferred from the data and context — e.g., "Why did activation drop 15% week-over-week?"]
- Analysis type: [Metric interpretation / Funnel analysis / Cohort analysis / Anomaly investigation]
- Decision this informs: [Best inference — e.g., "Whether to investigate further or treat as normal variance"]
Is that the right question? I want to make sure I'm answering the thing you actually need to know.
Understand the question being asked and what data is available. Separate the question (what the PM wants to know) from the data (what evidence exists). If the question is implicit in the data ("here's our funnel, what's going on?"), make the question explicit before analyzing.
Read these files:
references/data-interpretation.md — Metric interpretation heuristics, funnel analysis standards, cohort patterns, anomaly investigation framework, correlation vs. causation guardrails, data quality flags, confidence levelsreferences/pm-smell-test.md — Check for smells 2 (no way to measure success) and 5 (false precision)references/agent-readable-output.md — Agent Block format and shared enum vocabularyreferences/visualization-standards.md — Chart selection by analysis type, insight-first titling, annotation standards, comparison anchors, label discipline, style rules, technical save patternIf company/facts/product.md exists and is substantive, read it for product areas and feature landscape. This helps interpret metrics in context (e.g., a drop in "activation" means something different depending on what activation means for this product).
If company/facts/customers.md exists and is substantive, read it for customer segment definitions. This helps frame cohort analysis using actual segment definitions rather than inferred ones.
If company/interfaces/data-sources.md exists and is substantive, read it for data infrastructure context — what tools track what, known limitations, key dashboards.
If any of these files exist but are still stub templates, treat them as unavailable and say so in the context note.
Determine the analysis type from the question and data:
| Type | Triggered by |
|---|---|
| Metric interpretation | "What does this number mean?" "Why did X change?" "Is this good or bad?" |
| Funnel analysis | Funnel data provided, or question about conversion/drop-off |
| Cohort analysis | Comparison between user groups, or question about how different segments behave |
| Anomaly investigation | Something unexpected happened — a spike, drop, or unusual pattern |
State the classification at the top of the output. If the question spans multiple types (e.g., "our funnel conversion dropped — investigate the anomaly"), name the primary type and note the secondary.
If data is provided, assess whether it's sufficient to answer the question:
If only a question is provided without data, describe:
When numeric data is provided, run calculations programmatically. Do not estimate arithmetic. For funnel math, growth rate deltas, percentage changes, cohort comparisons, and statistical computations — execute the calculation in code (Python) and show the result. Estimation introduces exactly the false precision that Smell 5 flags. If the data is too messy to compute directly, name what's wrong with it before approximating.
Every calculation that supports a key numeric claim must be logged with a stable calc_id. In the markdown report, cite the supporting calculation inline using the format [calc:your-calc-id]. Numeric analyses without calc citations are incomplete.
Run the analysis appropriate to the type. Follow the standards in references/data-interpretation.md:
For metric interpretation:
For funnel analysis:
For cohort analysis:
For anomaly investigation:
When numeric data is provided, always produce 1–3 charts as PNG files. The chart is not decoration — it should make the key finding visually obvious without requiring the reader to parse the prose. Run programmatically in Python (matplotlib). Do not sketch or estimate.
Load and apply references/visualization-standards.md for all chart decisions: type selection, titling, annotation, comparison anchors, label placement, color, and save pattern.
Before writing any chart code: Identify which narrative role each chart will play — Context (establish the baseline or landscape), Tension (reveal the finding), Resolution (explain why or what to do). State each role in a code comment at the top of that chart's block. The order of charts in the Visualizations section must follow Context → Tension → Resolution.
Chart type by analysis type:
| Analysis type | Primary chart | Secondary (if a second finding warrants it) |
|---|---|---|
| Metric interpretation | Line/time-series with the key movement annotated | Bar showing magnitude vs. baseline |
| Funnel analysis | Horizontal waterfall — absolute users at each stage | Segmented bar at the biggest drop-off step |
| Cohort analysis | Grouped bar (cohorts × metric, same time window) | Dot plot or heatmap for retention over time |
| Anomaly investigation | Time series with the anomaly window highlighted | Breakdown bar showing which segment drives the scope |
Save pattern and naming convention: see references/visualization-standards.md.
For every numeric analysis, save the computational basis alongside the prose:
report.md — the human-readable reportanalysis.py — the exact replayable code used to generate calculations, derived tables, and chartsinputs/ — copies of every raw input file or normalized inline-input dumpderived/ — every transformed table used in the analysiscalc-log.jsonl — one JSON object per calculation with calc_id, label, formula, inputs, result, units, source_artifacts, and derived_artifactsmanifest.yaml — run metadata, file inventory, dependencies, rerun command, and verification statusanalysis.py must support this replay interface:
--input-dir--derived-dir--chart-dir--calc-logThe same values are also passed via environment variables during verification:
PM_AGENT_INPUT_DIRPM_AGENT_DERIVED_DIRPM_AGENT_CHART_DIRPM_AGENT_CALC_LOGFor numeric analyses, do not treat the work as final until replay verification passes.
Use .claude/skills/data-analysis/analysis_runner.py:
python3 .claude/skills/data-analysis/analysis_runner.py finalize --spec /path/to/spec.jsonverification.json existsmanifest.yaml has verification_status: Passedreplay/If replay verification fails:
Check for:
Name every meaningful limitation of the analysis:
This is not a formality. An analysis without stated limitations is an analysis the PM can't properly evaluate.
Based on the analysis, recommend what to do next:
Sort the Hypotheses table by Rank (1 = most likely) before output. If the data doesn't clearly distinguish likelihood between hypotheses, state the tied ranks and explain in the Limitations section rather than forcing an ordering.
Populate the Agent Block:
analysis_type: from the classification in step 4finding: the key finding in one sentence (the first sentence of the Key Finding section)confidence: the categorical confidence level from the Key Finding sectiontop_hypothesis: the row number of the Rank 1 hypothesisrecommended_action: one of Pull more data / Run experiment / Act on finding / Monitor — the primary next step from step 9sample_size_adequate: Yes if sample size was assessed as sufficient in step 5; No if a size constraint was identified; Unknown if size wasn't determinablerun_dir: the run folder under knowledge/data-analyses/report: workspace-relative path to report.mdcode_artifact: workspace-relative path to analysis.pycalc_log_artifact: workspace-relative path to calc-log.jsonlsource_artifacts: workspace-relative paths to files in inputs/derived_artifacts: workspace-relative paths to files in derived/manifest_artifact: workspace-relative path to manifest.yamlverification_artifact: workspace-relative path to verification.jsonverification_status: Passed / Failed / Not Required## Data Analysis: [Question or Topic]
**Analysis type:** [Metric interpretation / Funnel analysis / Cohort analysis / Anomaly investigation]
<!-- AGENT BLOCK -->
```yaml
agent_block:
skill: data-analysis
analysis_type: [Metric interpretation / Funnel analysis / Cohort analysis / Anomaly investigation]
finding: "[One sentence summary of the key finding]"
confidence: [High / Medium / Low]
top_hypothesis: [integer — rank 1 hypothesis number]
recommended_action: [Pull more data / Run experiment / Act on finding / Monitor]
sample_size_adequate: [Yes / No / Unknown]
run_dir: knowledge/data-analyses/YYYY-MM-DD-analysis-slug
report: knowledge/data-analyses/YYYY-MM-DD-analysis-slug/report.md
code_artifact: knowledge/data-analyses/YYYY-MM-DD-analysis-slug/analysis.py
calc_log_artifact: knowledge/data-analyses/YYYY-MM-DD-analysis-slug/calc-log.jsonl
source_artifacts:
- knowledge/data-analyses/YYYY-MM-DD-analysis-slug/inputs/source_01.csv
derived_artifacts:
- knowledge/data-analyses/YYYY-MM-DD-analysis-slug/derived/table_01.csv
manifest_artifact: knowledge/data-analyses/YYYY-MM-DD-analysis-slug/manifest.yaml
verification_artifact: knowledge/data-analyses/YYYY-MM-DD-analysis-slug/verification.json
verification_status: [Passed / Failed / Not Required]
charts:
- knowledge/data-analyses/YYYY-MM-DD-analysis-slug/chart.png
```
<!-- /AGENT BLOCK -->
---
### Question
[Restate the question clearly. If the question was implicit, make it explicit.]
---
### Key Finding
**Finding:** [1-2 sentences. The answer, stated directly. Cite key numeric claims with `[calc:calc_id]`.]
**Confidence:** [High / Medium / Low] — [One sentence on what drives this confidence level — sample size, data quality, or evidence strength]
**Top Hypothesis:** Hypothesis #[N] — [brief label from the Hypotheses table below]
**Recommended Action:** [Pull more data / Run experiment / Act on finding / Monitor]
---
### Analysis
[Structured analysis appropriate to the type.
For metric interpretation: context (baseline, variance, seasonality), the movement, candidate explanations.
For funnel analysis: stage-by-stage data, drop-off analysis, segmentation findings.
For cohort analysis: cohort definitions, comparison table, divergence analysis.
For anomaly investigation: characterization (timing, magnitude, scope, shape), hypotheses.
Show the work. Include tables, calculations, and comparisons as appropriate.]
---
### Visualizations

*Chart 1: [One sentence — what the chart shows and what the reader should conclude. Cite the reference line or comparison anchor used.]*

*Chart 2: [Caption.] — Omit this entry if only one chart was produced.*
---
### Hypotheses
| Rank | # | Hypothesis | Evidence For | Evidence Against | Likelihood |
|------|---|-----------|-------------|-----------------|------------|
| 1 | [#] | [Most likely hypothesis] | [What supports it] | [What contradicts it] | [High / Medium / Low] |
| 2 | [#] | [Second most likely] | [Evidence for] | [Evidence against] | [Likelihood] |
---
### Limitations
- [Named limitation with explanation of how it affects the analysis]
- [Named limitation]
---
### Recommended Next Steps
1. [What to do next — additional data, experiment, action, or monitoring]
2. [Second recommendation]
---
### Reproducibility
- **Verification:** [Passed / Failed / Not Required]
- **Runner command:** `python3 .claude/skills/data-analysis/analysis_runner.py verify --run-dir knowledge/data-analyses/YYYY-MM-DD-analysis-slug`
- **Important calc IDs:** [List the critical `calc_id`s cited in the report]
- **Bundle contents:** `report.md`, `analysis.py`, `inputs/`, `derived/`, `calc-log.jsonl`, `manifest.yaml`, `verification.json`, charts, and `replay/`
---
### Smell Test
- **Smell 2 (No Way to Measure):** [Can the available data actually answer the question? Finding or "Clear — data is sufficient for the question asked"]
- **Smell 5 (False Precision):** [Is confidence calibrated to sample size and data quality? Finding or "Clear — confidence levels match the evidence"]
> **Context note:** [State which substantive company files were loaded, which were absent, and which were stub templates. Note what the analysis might miss without product context or data source context.]
Create a run folder in knowledge/data-analyses/ using the naming convention: YYYY-MM-DD-analysis-slug/, where YYYY-MM-DD is today's date and analysis-slug is a lowercase hyphenated slug derived from the question or topic.
Inside that folder, save:
report.mdanalysis.pycalc-log.jsonlmanifest.yamlverification.jsoninputs/derived/replay/chart.png and chart_2.png / chart_3.png when additional charts existFor numeric analyses, finalize the run with:
python3 .claude/skills/data-analysis/analysis_runner.py finalize --spec /path/to/spec.json
Report the run directory, verification status, and all saved artifact paths in the conversation.