domain-check
Use whenever you write or run scientific analysis code (physics, earth/geo, biology, chemistry, or social science) in this workspace — before executing it and again after generating results. Runs a deterministic domain-correctness gate that catches code which runs but is scientifically wrong (unit/dimension mismatch, Euclidean distance on lat/lon without a CRS, 0-based/1-based coordinate and strand errors, impossible SMILES valence, uncorrected multiple comparisons, averaging a categorical code). Surfaces structured findings; never claims the code is correct.
git clone --depth 1 https://github.com/ai4s-research/open-science /tmp/domain-check && cp -r /tmp/domain-check/runtime/skills/core/domain-check ~/.claude/skills/domain-checkSKILL.md
# Domain-correctness gate
Across every field the top complaint is code that **executes cleanly but is
scientifically wrong**. This gate intercepts that field's classic error classes
**deterministically** — by analysing the code you actually wrote, not by
recalling rules. It verifies specific error classes; it never proves correctness.
Run it as a normal step of any analysis — it is fast, offline, and stdlib-only.
## When to run
- **Before executing** analysis code you generated (catch the bug before it
produces a plausible-but-wrong number).
- **After generating results**, as a final gate before you report figures or
numbers to the user.
- Whenever the user asks to check, validate, or audit an analysis for
correctness.
## How to run
The gate ships beside this SKILL.md. Run it on the code files in play (or with
no arguments to scan the workspace):
```bash
python "$XDG_CONFIG_HOME/opencode/skills/domain-check/domain_check.py" <file.py|notebook.ipynb|analysis.R ...>
```
It prints exactly one ` ```review ` fenced JSON block on stdout.
## What it catches (one rule set per discipline)
- **physics · units** — adding/subtracting/comparing quantities of different
dimensions (e.g. `t_seconds + d_meters`); trig on a degree-valued angle.
- **earth · crs** — Euclidean/Pythagorean distance on latitude/longitude
(`sqrt((lat1-lat2)**2 + (lon1-lon2)**2)`); a geopandas geometric op with no
CRS ever set.
- **biology · coords / strand** — off-by-one on BED intervals (0-based
half-open, so length is `end - start`, never `+1`); a sequence sliced from a
stranded feature file (GFF/GTF/BED) with no reverse-complement for the `-`
strand.
- **chem · valence** — a SMILES string literal (assigned to a `smiles`/`smi`
variable, or passed to `MolFromSmiles`/`MolFromSmarts`) that cannot be a real
molecule. **If RDKit is installed it is used as the authoritative judge** —
`Chem.MolFromSmiles` sanitizes the parse, so it catches far more than a
five-bond carbon (bad ring closures, impossible aromaticity, over-valent
N/O/S) and, being authoritative, clears molecules a heuristic would
wrongly flag. Without RDKit it falls back to a stdlib bond-counter (carbon
>4, over-bonded halogen; bails on bracket atoms for precision).
- **social · multiple-comparisons** — a significance test (`ttest_ind`,
`pearsonr`, `f_oneway`, `chi2_contingency`, …) run inside a loop or ≥3 times
with no `multipletests`/FDR/Bonferroni correction anywhere — the inflated
family-wise false-positive rate that silent p-hacking produces.
- **social · categorical** — a numeric reduction (`.mean()`/`.median()`/`.std()`
…) taken directly on a nominal category code (`gender`, `race`, `region`,
`condition`, …), treating an unordered label as an interval quantity. A
`groupby('gender')` key is correct usage and is not flagged.
Rules favour precision: an unrecognized unit, arithmetic with no discipline
signal, a SMILES using bracket atoms (which carry their own valence/charge), a
single significance test, or a categorical used only as a groupby key is left
silent rather than flagged.
## Reporting findings
Copy the ` ```review ` block the tool prints as the **last thing** in your
message — the app renders it as dismissible reviewer cards. Do not paraphrase
the findings into prose and drop the block; the structured block is the
contract. If the gate found nothing, say so plainly and keep the block (its
`note` states that no findings is not a guarantee of correctness).
Never tell the user the code is "correct" or "error-free" — the gate checks
known error classes only.
## Adding a discipline
Add a `check_<field>(ctx)` function in `domain_check.py` and append it to
`VALIDATORS`. No other change is needed — the review contract and the app's
rendering are discipline-agnostic (each finding carries its own `tag`).A test skill that says hello. Use when you want to test skill loading or verify that the skill system is working.
Verify apps/desktop frontend changes visually without launching the Tauri app or a live model
Use BEFORE reading any data file that could be large (CSV/TSV, Parquet, HDF5, FITS, NetCDF, NDJSON, genomics FASTQ/FASTA/VCF/BAM, GRIB, ROOT, or big text/simulation logs like VASP OUTCAR). Returns a compact memory pointer — header/schema/shape/sample/key numbers — by introspection and sampling in bounded memory, so you never load a file bigger than the context window into the model. Reference data via the pointer; read specific ranges deterministically.
Use when the user asks to run heavy or GPU work on Modal (the cloud compute platform) — writing a Modal function in the workspace, running it with the user's own `modal` CLI + token, and bringing results back. Data-to-compute for jobs too big for the laptop, without a Slurm cluster.
Use whenever you generate or review a chart, plot, table, or paper figure in this workspace, including work delegated by paper-writing, literature-survey, and experiment skills. Applies the Open Science publication style, enforces readable final-size layout for figures and tables, and rejects generic diagram-tool output as a publication figure. Interactive Plotly/HTML may be used for exploration, but paper delivery requires a static publication-ready export.
Use when the user asks to run, submit, monitor, or cancel a job on a remote machine over SSH — their own GPU/CPU server, a workstation, or a Slurm cluster ("the cluster", a login node, "my 3090 box", "the compute server"). Picks a saved machine, runs the work directly over SSH (or via Slurm when present), tracks it, and fetches results back into the workspace.
Use whenever you run statistical analysis for the social sciences (regression, hypothesis tests, econometrics) or read Stata (.dta) / SPSS (.sav) data in this workspace. Enforces an execute-don't-interpret boundary (surface estimates, don't volunteer causal claims), checks the analysis against a preregistration plan for HARKing, verifies reproducible seeds, and reproduces .dta/.sav estimates via R. Flags integrity risks; never certifies the analysis is sound.
Use when the user asks to review, verify, or audit a report, manuscript, or analysis in the workspace for traceability — resolving citations, flagging numbers with no source, and checking figures against the code that generated them. Emits a structured review block the app renders as reviewer findings. Verifies traceability, never "correctness".