alterlab-test-selection-guard — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited alterlab-test-selection-guard (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.
Skill type: DISCIPLINE-ENFORCING. This is a thin discipline layer, not a stats engine. It does not run tests, fit models, or compute power — it forces the order of operations so the test is chosen by the data's shape, never by the result it produces. For the actual computation, hand off to the skills below.
REQUIRED BACKGROUND — this skill orchestrates, it does not reimplement: - `alterlab-statistical-analysis` — runs the chosen test, the assumption checks (its assumption_checks.py: Shapiro-Wilk, Levene, Q-Q), power, and APA reporting. - `alterlab-statsmodels` — fits the model (OLS/GLM/mixed/ARIMA) once the test is fixed. - `alterlab-scientific-thinking` — judges design validity, biases, confounders upstream. - `alterlab-preregistration-discipline` — the frozen analysis plan this gate presumes.>
When the user needs execution, route there. This skill's whole job is what happens before the first scipy.stats call.NO TEST CHOSEN AFTER SEEING THE P-VALUE.The test is a function of the research question and the data's structure — outcome type, number of groups, pairing, and assumption checks — fixed before any p-value is visible. Choosing or switching a test in response to its significance is p-hacking. It inflates the Type I error rate by an unknown amount and makes the reported p-value a lie.
Violating the letter of the pre-specified test is violating the spirit of the inference.
A non-significant result is not a reason to try another test. It is a finding.
Trigger this guard whenever a test is being selected, defended, or swapped:
The skill runs the decision tree, names the test, and — critically — *interrogates the timing and motive of any switch*.
Route these adjacent requests to the real sibling skill instead. This guard chooses and polices the test; it does not execute, model, design, or write.
| The request is really about… | Route to | Why not this skill |
|---|---|---|
| Actually running the chosen test, assumption checks, power, APA write-up | alterlab-statistical-analysis | This guard picks the test; that skill computes it. |
| Fitting a specific model class (OLS/GLM/mixed/ARIMA), coefficient tables, residual diagnostics | alterlab-statsmodels | Programmatic model fitting, not test selection. |
| Grading evidence quality, spotting confounders / design validity / bias (GRADE, RoB) | alterlab-scientific-thinking | Upstream judgment about the study, not which test. |
| Freezing the whole analysis plan before data; HARKing, optional-stopping, frozen-covariate discipline | alterlab-preregistration-discipline | The plan-level discipline; this guard is the test-choice slice of it. |
| Reporting every analysis run, effect sizes + CIs, deviation disclosure in the write-up | alterlab-results-transparency | Reporting discipline, downstream of test choice. |
| Choosing the study design itself (RCT vs observational vs quasi-experiment) | alterlab-scientific-thinking | Design selection precedes test selection. |
| Open-science / repository / DMP / preregistration logistics (OSF, AsPredicted, Zenodo) | alterlab-open-science | Platform/workflow guidance, not test-choice logic. |
Walk this top-down. Each branch is decided by the data's structure, not by any p-value. Normality is decided by the assumption-check gate below — not by eyeballing which test "comes out significant."
digraph test_selection {
rankdir=TB;
node [shape=box, fontname="Helvetica"];
q [shape=diamond, label="Outcome type?"];
q -> cont [label="continuous / ordinal"];
q -> cat [label="categorical (counts)"];
q -> rel [label="association between\ntwo variables"];
// --- group comparisons ---
cont [shape=diamond, label="How many groups?"];
cont -> two [label="2"];
cont -> three [label="3+"];
two [shape=diamond, label="Paired /\nrepeated?"];
two -> two_ind [label="independent"];
two -> two_pair [label="paired"];
two_ind [shape=diamond, label="Normal?\n(see gate)"];
two_ind -> tt [label="yes"];
two_ind -> mwu [label="no"];
two_pair [shape=diamond, label="Normal\ndifferences?"];
two_pair -> ptt [label="yes"];
two_pair -> wil [label="no"];
tt [label="independent t-test\n(Welch if unequal variance)"];
mwu [label="Mann-Whitney U"];
ptt [label="paired t-test"];
wil [label="Wilcoxon signed-rank"];
three [shape=diamond, label="Paired /\nrepeated?"];
three -> th_ind [label="independent"];
three -> th_pair [label="repeated"];
th_ind [shape=diamond, label="Normal?"];
th_ind -> anova [label="yes"];
th_ind -> kw [label="no"];
th_pair [shape=diamond, label="Normal?"];
th_pair -> rm [label="yes"];
th_pair -> fried [label="no"];
anova [label="one-way ANOVA\n(+ planned post-hoc)"];
kw [label="Kruskal-Wallis"];
rm [label="repeated-measures ANOVA"];
fried [label="Friedman"];
// --- categorical ---
cat [shape=diamond, label="Expected cell\ncount >= 5?"];
cat -> chi [label="yes"];
cat -> fisher [label="no / 2x2 small"];
chi [label="chi-square test"];
fisher [label="Fisher's exact"];
// --- association ---
rel [shape=diamond, label="Both continuous?"];
rel -> rel_norm [label="yes"];
rel -> reg [label="outcome + predictors"];
rel_norm [shape=diamond, label="Linear & normal?"];
rel_norm -> pearson [label="yes"];
rel_norm -> spearman [label="no / monotonic"];
pearson [label="Pearson r"];
spearman [label="Spearman rho"];
reg [shape=diamond, label="Outcome type?"];
reg -> linreg [label="continuous"];
reg -> logreg [label="binary"];
linreg [label="linear regression"];
logreg [label="logistic regression"];
}This routing mirrors the Test Selection Guide in alterlab-statistical-analysis (references/test_selection_guide.md) — the guard adds the timing and anti-shopping discipline on top of it. Full branch logic and edge cases: references/decision_tree.md. A runnable router that prints the named test from your answers: scripts/test_picker.py.
Normality and homogeneity are inputs to the decision tree, not after-the-fact excuses. The order is fixed:
alterlab-statistical-analysis (itsassumption_checks.py) — Shapiro-Wilk (normality), Levene (homogeneity of variance), residual/Q-Q and linearity for regression. Report them.
the pre-specified non-parametric fallback (e.g. t-test → Mann-Whitney; ANOVA → Kruskal-Wallis). The fallback is chosen by the assumption check, never by the p-value.
If the assumption checks were not run and reported, the test result is uninterpretable. This is the analog of "verify RED before GREEN": you cannot trust the GREEN (the p-value) until the assumptions are shown. Detail: references/assumption_gate.md.
These are the rationalizations that precede a p-value-driven test switch. When one appears — yours or the user's — name it and stop.
| Excuse | Reality |
|---|---|
| "The t-test wasn't significant, let me try Mann-Whitney." | You are choosing the test by its result. That is test-shopping. The non-parametric test is only valid if the assumption check (not the p-value) sent you there. |
| "The data suggested a better test after I looked." | You are fitting noise / HARKing. Re-run the pre-specified test; report anything else as exploratory. |
| "I'll just drop these 3 outliers and re-run." | Outlier rules must be pre-specified or reported as a sensitivity analysis — not invented to cross .05. |
| "Adding this covariate obviously improves the model." | Obvious post hoc = a researcher degree of freedom. Pre-specify it or label the result exploratory. |
| "Non-parametric is more conservative, so switching is safe." | Switching because the first test failed still conditions the choice on the outcome. The inflation is real regardless of direction. |
| "It's only exploratory anyway." | Then say so explicitly, drop the confirmatory p-value language, and do not report it as a test of the hypothesis. |
| "Everyone reports the test that worked." | Selective reporting of the significant test among several is p-hacking; report all tests run or correct for them. |
More patterns and the counters: references/rationalizations.md.
If any of these thoughts appear, STOP. You are about to condition the test on its result.
All of these mean: STOP. You are exploiting researcher degrees of freedom. Return to the pre-specified test, or label the analysis exploratory and drop the confirmatory claim.
Mirrors the "3 fixes then question the architecture" rule, applied to hypothesis testing:
Ran 3+ tests on the SAME hypothesis searching for significance? STOP.This is multiple comparisons / test-shopping. You have two honest options — never a fourth test:
less conservative FDR control (Benjamini-Hochberg) across the full family of tests actually run — including the ones that "didn't work."
confirmatory p-value language.
Do not run test #4 to find p < .05. Correction math and family definition: references/multiplicity.md.
scripts/test_picker.py can do this from your answers) to anamed test, before looking at any result.
alterlab-statistical-analysis. Take thepre-specified parametric/non-parametric branch the checks dictate.
Flags. A switch is legitimate only if an assumption check (not a p-value) drove it.
exploratory.
alterlab-statistical-analysis / alterlab-statsmodels, andreporting discipline to alterlab-results-transparency.
alterlab-results-transparency)?references/decision_tree.md — full branch logic, edge cases, Welch/post-hoc notes.references/assumption_gate.md — the pre-interpretation check order and fallback rules.references/rationalizations.md — extended Excuse-vs-Reality table with counters.references/multiplicity.md — Bonferroni / Benjamini-Hochberg FDR, defining the test family.scripts/test_picker.py — stdlib decision-tree router; prints the named test from answers.Part of the AlterLab Academic Skills suite.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.