mne-stats — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited mne-stats (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Statistical inference on neurophysiology data via the MNE MCP server. This is the cross-cutting skill: it consumes the outputs of mne-erp, mne-timefreq, mne-connectivity, and mne-source and decides what can actually be claimed from them. It is skeptical by design: most statistical mistakes (conflating cluster-level with point inference, an incomplete correction family, asserting normality at small n) run without any error — so the discipline is to grill before testing and critique before believing.
Companion skills:mne-mcp-guardfor technical execution safety;mne-methodology-criticfor Phase 3. Loaded objects (evoked / TFR / connectivity / stc arrays) persist in one MNE session.
Do not run a test until these are answered. If the user can't answer one, propose a sensible default and explicitly flag the open risk — never silently choose.
Design & claim
pre × post, vs a baseline / vs zero)
The two questions that decide validity
channels × times × freqs × ROIs × conditions. The correction must cover the entire family, including exploratory tests you ran but won't headline. An undercounted family is the single most common fatal error here.
cluster (a contiguous blob in space/time/freq), not about any specific channel, time, or frequency inside it. You may NOT say "Cz at 320 ms is significant" from a cluster test. If you need point/peak inference, you need a different, pre-specified test. Decide which claim you're making before you run.
Assumptions & correction
just asserted? At small n (≲ 15–20) normality is not establishable → prefer permutation / non-parametric.
hold? FDR-BH assumes independence / positive dependence; neighbouring channels/times/freqs are correlated, so per-point FDR can be both invalid and underpowered → cluster permutation / TFCE.
tail=0/1/-1), not chosen after seeing the sign.Inference plan (pin this down NOW, not after seeing results)
independent → build channel adjacency and use spatio-temporal clustering.
variance and pseudo-replicates → plan a linear mixed model (LMM).
mne_check_status; gather the contrast array from the priorskill's output. Cluster tests want an array shaped (n_observations, …) — e.g. (n_subjects, n_times, n_channels) for spatio-temporal — where the observation axis is what gets permuted. Confirm the axis order matches the adjacency.
adjacency, ch_names = mne.channels.find_ch_adjacency(epochs.info, ch_type="eeg")(Combine with a time/freq lattice via mne.stats.combine_adjacency for spatio-temporal-spectral.)
mne_run_code, prefer non-parametric at small n): from mne.stats import (permutation_cluster_1samp_test, permutation_cluster_test,
spatio_temporal_cluster_test, fdr_correction)
# 1-sample (within-subject difference vs 0): X = (n_subj, n_times, n_chan) of conditionA - conditionB
T_obs, clusters, p_vals, H0 = permutation_cluster_1samp_test(
X, adjacency=adjacency, n_permutations=5000, tail=0, seed=42)
# Independent groups: [X_group1, X_group2]
T_obs, clusters, p_vals, H0 = spatio_temporal_cluster_test(
[Xg1, Xg2], adjacency=adjacency, n_permutations=5000, seed=42)Significant clusters are clusters[i] where p_vals[i] < .05.
T_obs, clusters, p_vals, H0 = permutation_cluster_1samp_test(
X, adjacency=adjacency, threshold=dict(start=0, step=0.2), # TFCE
n_permutations=5000, tail=0, seed=42) from scipy import stats
t, p = stats.ttest_1samp(X_roi, 0) # one value per pre-registered ROI/window
reject, p_fdr = fdr_correction(p, alpha=0.05) # Benjamini-Hochberg
p_bonf = np.minimum(p * len(p), 1.0) # Bonferroni (conservative, independent only)(channels and time/freq span), its cluster p-value, and an effect size with a bootstrap CI — not just p. Plot the significant clusters (mask the topomap / TFR to the cluster mask).
import statsmodels.formula.api as smf
md = smf.mixedlm("amp ~ condition", df, groups=df["subject"]).fit() # random intercept per subjectmne-analyst archiving convention).Best-practice reminders: permute the correct (observation) axis; fix a seed; prefer non-parametric at small n; keep the cluster mask and report cluster extent, never an interior point.
Hand the design + result to `mne-methodology-critic` (invoke the skill, or dispatch it as a subagent with references/methodology-checklist.md). For statistical work it will specifically check:
significant from a cluster test — you may not);
Report its BLOCK / REVISE / PASS verdict to the user and act on it before stating conclusions.
See references/stats-methods.md for deeper recipes (cluster permutation variants, adjacency construction, TFCE, FDR vs Bonferroni, LMM, bootstrap CIs, and the inference-choice decision tree).
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.