Scientific Analysis
Run one bounded, reproducible computational analysis — only when a question genuinely needs code (a statistic, a model fit, a plot, a data transform). Work in one self-contained directory, and make every artifact traceable so someone can re-run and get the same numbers. You do not write the surrounding report, and you leave other analyses alone.
First: is code actually needed?
Do not run code reflexively. Code is warranted when the question needs a computed result from data — a statistic, a fit, a transform, a figure. It is not warranted when the answer is a literature or database fact, or when a one-line reasoning step settles it.
If code is not needed, finalize immediately with status: "success" and a conclusion stating why no computation was required. An honest "no analysis needed" beats busywork.
Working directory
Create one analysis directory for the task and work only inside it. Name it after the analysis (e.g. analysis/treatment-effect/), and use this layout:
analysis/<analysis-name>/
├── run.py your script — re-runnable, no hidden state
├── inputs/ input data, or a stable reference to it
├── outputs/ tables, figures, computed artifacts
├── run.log stdout+stderr of the run
├── environment.json written by the finalize helper
└── result.json written by the finalize helper
Workflow
- Set up. Create the analysis directory with
inputs/andoutputs/. Put the input data (or a small file recording a stable URL/reference to it) ininputs/so the run is reproducible. - Write
run.py. Re-runnable from scratch: read frominputs/, write every artifact tooutputs/, no dependence on interactive state. Python is the standard runtime; pandas/numpy/matplotlib are commonly available. Keep it readable — someone must re-run it to reproduce your numbers. - Run it, capturing the log:
bash cd analysis/<analysis-name> && python run.py > run.log 2>&1; echo "exit=$?" - Handle failure honestly. If the run fails, do not invent a result. Read
run.log; if the cause is yours, fixrun.pyand retry a bounded number of times. If it still fails, finalize withstatus: "failed"and put the real cause (a stderr summary) inwarnings. A failed run recorded truthfully is a valid outcome; a fabricated number is not. - Finalize. Call the bundled helper (below) to capture the environment and write
environment.jsonandresult.json. - Report, then stop. Read
result.jsonand give a short summary of the finding plus the result path. Do not echo large outputs back into the conversation.
Finalizing
The helper scripts/finalize_analysis.py ships inside this skill, next to this SKILL.md. Resolve its path relative to this skill's directory — never a hard-coded absolute path — then run it from the analysis directory (or point --analysis-dir at it):
python <this-skill-dir>/scripts/finalize_analysis.py \
--task-id <analysis-name> \
--analysis-dir analysis/<analysis-name> <<'JSON'
{
"status": "success",
"conclusion": "IL-6 knockout reduced mean fibrosis area from 12.4% to 7.1% (t-test p=0.003, n=8/group).",
"script": "run.py",
"inputs": ["inputs/fibrosis_areas.csv"],
"outputs": [
{"path": "outputs/boxplot.png", "type": "figure", "description": "Fibrosis area by genotype"},
{"path": "outputs/stats.csv", "type": "table", "description": "Group means and t-test result"}
],
"warnings": [],
"limitations": ["Single cohort; no multiple-testing correction."]
}
JSON
The helper writes environment.json (python version, platform, installed packages) and result.json, both atomically. Every path you list in inputs/outputs is an artifact others will trace numbers back to — only list files that actually exist.
If code was not needed (first section), finalize the same way with status: "success" and the explanatory conclusion — the helper still records the environment and a valid result.
Guardrails
- Reproducibility is the point. Inputs, script, environment, and outputs must let someone re-run and get the same numbers. If an input cannot be bundled, record a stable reference to it in
inputs/. - Never present a failed or fabricated run as a result. Numbers in
conclusion/outputsmust come from an actual successful run recorded inrun.log. - Stay self-contained. One analysis, one
analysis/<analysis-name>/directory. Do not reach into other directories. - No Jupyter dependency. Plain scripts only; do not require a notebook server to reproduce the work.