Psy ana reviewer
Skill soupandpsy/amazing-psycoder-skills/amazing-psycoder/psy-ana-reviewer
AI skills for psychology experiment programming and data analysis, from task design and code generation to reproducible statistical workflows.
npx -y skills add soupandpsy/amazing-psycoder-skills --skill psy-ana-reviewerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Use for reviewing data analysis scripts at any stage — from analysis plan through completed script. Performs reproducible-research checks: seed, effect size, multiple comparison correction, assumption testing, exclusion logging, and session info. Detects analysis anti-patterns and outputs a graded audit report with readiness label. Does NOT generate or fix analysis code. Trigger for 检查分析代码、analysis review、统计方法审查、分析脚本有没有问题、check analysis script / 分析コードレビュー、分析監査 / Analyse-Code-Review, Analyse-Audit / revue de code analyse, audit analyse.
SKILL.md
14.2 KB, as published. Nobody here has run it
Analysis Code Reviewer
Version
v1.3 — stable, 2026-06-10. Sub-skill of amazing-psycoder.
Purpose
Audit data analysis scripts for statistical correctness, reproducibility, and reporting completeness. The reviewer detects statistical anti-patterns, verifies assumption checking, and ensures the analysis is ready for publication or sharing.
This is the analysis audit layer. It evaluates code generated by psy-ana-coder, identifies issues, and works with the coder to fix them. The reviewer enters a check → fix → re-check loop — each audit round identifies remaining issues, the coder applies fixes, and the reviewer re-audits. This cycle repeats until zero Critical and zero Major issues remain. Only then is the final file delivered.
Review Modes
| Mode | Input | Maximum Label |
|---|---|---|
analysis-audit | Complete analysis script + data | ready_for_publication |
plan-review | Analysis config YAML | analysis_plan_ready |
triage-only | Research question | None (missing-info list only) |
blocked | Insufficient input | None |
Readiness Labels
| Label | Meaning |
|---|---|
ready_for_publication | Zero Critical + zero Major — analysis is reproducible and complete |
ready_after_minor_fixes | Only Minor issues remain |
not_ready | Critical or Major issues exist |
analysis_plan_ready | Analysis design complete, ready for code generation |
blocked | Input insufficient for any review |
Severity Classification
| Severity | Definition |
|---|---|
| Critical | Invalidates all results; must fix before sharing |
| Major | Reduces reproducibility; fix before publication |
| Minor | Does not affect correctness; fix when convenient |
Intake Protocol
Before any review, confirm the input:
| Mode | Intake Action |
|---|---|
analysis-audit | > "Please provide the analysis script file path (e.g., output/analysis.R) and the data file path." Verify the file exists and is readable. |
plan-review | > "Please provide the analysis config YAML (paste content or provide file path)." Verify the YAML structure is complete. |
triage-only | > "Please describe your research question, experimental design, and data type." |
blocked | > "The information provided is currently insufficient for any review. Please provide at least a research question description." |
Mode auto-detection: has script + data → analysis-audit, has only config → plan-review, has only question description → triage-only, has none → blocked.
Review Checklist — analysis-audit
Gate 0: Quality Gate (minimum bar)
For analysis-audit mode: Re-run the 10-item Post-Generation Quality Gate from psy-ana-coder against the provided script. If any fail, stop and return not_ready. Do not proceed.
For plan-review mode: Skip Gate 0 (no script to check). Proceed directly to design-level review.
1. Statistical Validity
| # | Check | Verify by |
|---|---|---|
| 1 | Model matches design | Read the design_type field. Does the statistical model match? Within-subjects → paired t-test or repeated-measures ANOVA. Between-subjects → independent t-test or between-subjects ANOVA. Mixed → mixed-effects model. |
| 2 | Random effects justified | For mixed models: is the random effects structure reasonable given the design? |
| 3 | Contrasts specified correctly | Are contrast weights orthogonal? Are planned comparisons justified? |
| 4 | Post-hoc method appropriate | Tukey (all pairwise), Bonferroni (selected pairs), or none? |
| 5 | Effect size correct | t-test → Cohen's d, ANOVA → η²p or η²g, categorical → OR. Verify formula. |
2. Reproducibility
| # | Check | Verify by |
|---|---|---|
| 1 | Seed set and recorded | grep "set\.seed|random_state|rng(" |
| 2 | Session info output | grep "sessionInfo|session_info|version" |
| 3 | Package versions | Are package versions recorded? sessionInfo() output present |
| 4 | Data path configurable | No hardcoded paths. Acceptable: relative paths from project root (data/subject.csv), here::here(), or path from config. Unacceptable: absolute paths (/Users/..., C:\...), setwd() |
| 5 | Exclusion log complete | Every excluded trial/subject documented with reason |
| 6 | Parameter provenance | Are analysis parameters (cutoffs, thresholds) referenced to config or literature? |
3. Assumption Checking
| # | Check | Verify by |
|---|---|---|
| 1 | Normality | Shapiro-Wilk or QQ-plot per condition |
| 2 | Sphericity | Mauchly's test for repeated measures with >2 levels |
| 3 | Homogeneity of variance | Levene's test for between-subjects factors |
| 4 | Violation handling | What happens if assumptions fail? Non-parametric alternative? Greenhouse-Geisser correction? Documented? |
Check adaptation rules: Adjust assumption checks based on model type:
lmer/glmer→ skip Mauchly's sphericity (not applicable); check convergence warnings + singular fit + random effects variancet.testwithin-subjects → check normality of differences (not normality of raw data)aovwithin-subjects → check Mauchly's sphericity + Greenhouse-Geisser correctionglmer(binomial)→ check overdispersion
4. Reporting Completeness
| # | Check | Verify by |
|---|---|---|
| 1 | All conditions reported | Every condition from design has descriptive stats |
| 2 | Effect sizes for all tests | Every p-value has a corresponding effect size |
| 3 | Confidence intervals | Effect sizes reported with CI, not just point estimates |
| 4 | n reported per analysis | After cleaning, how many subjects/trials per condition? |
| 5 | Exclusion documented | Are excluded subjects/trials listed with reasons? Counts and percentages reported? |
5. Figure Quality
| # | Check | Verify by |
|---|---|---|
| 1 | Error bars defined | SE or CI stated in caption or code |
| 2 | Individual data shown | For within-subjects designs, individual data points visible |
| 3 | Axes labeled | Clear axis titles with units |
| 4 | Color-safe | Colorblind-friendly palette? |
R Anti-Patterns
attach()— don't; usewith()ordplyr::verbssetwd()— don't; use relative paths orhere::here()save.image()— don't; save specific objects withsaveRDS()options(stringsAsFactors = TRUE)— don't; modern R defaults to FALSE- Loop without pre-allocation — use
vector("list", n)orpurrr::map() summary(model)$r.squaredfor mixed models — wrong R²; useperformance::r2()aov()for unbalanced designs — usecar::Anova(type = "III")instead- Running
rm(list = ls())at top of script — defeats reproducibility
R Anti-Pattern Grep Patterns
When auditing R scripts, scan for these patterns:
| # | Anti-Pattern | Grep | Why |
|---|---|---|---|
| 1 | attach( | grep -q "attach(" script.R | Namespace pollution |
| 2 | setwd( | grep -q "setwd(" script.R | Non-reproducible |
| 3 | save.image() | grep -q "save\.image" script.R | Non-reproducible |
| 4 | rm(list=ls()) | grep -q "rm(list.*ls" script.R | Defeats reproducibility |
| 5 | aov() within-subjects | grep -q "aov(" script.R + check design | Wrong for within-subjects |
| 6 | summary(lmer.*r.squared | grep -q "summary.*lmer.*r\.sq" script.R | Doesn't exist |
| 7 | aov() for within-subjects | grep -q "aov(" script.R + check design | Wrong for within-subjects; use lmer |
| 8 | Absolute paths | `grep -qE "/Users/ | /home/ |
Python Anti-Patterns
import *— don't; useimport pandas as pdor explicit imports- Hardcoded paths — don't; use
pathlib.Pathor config-driven paths df.apply()row-by-row loop — avoid; use vectorized operations ordf.transform()- Missing
random_state— all stochastic functions must passrandom_state={config.seed} print(df)without.head()— floods output; usedf.info()orprint(df.head())- No column existence check — use
assert set(expected).issubset(df.columns) pd.set_option('mode.chained_assignment', None)— hides warnings; use.loc[]insteaddf.iterrows()for row ops — extremely slow; vectorize- No effect size — every test must output effect size via pingouin
- Figure not saved —
plt.savefig()required, not justplt.show() scipy.stats.f_oneway()for within-subjects designs — usepingouin.rm_anova()insteadstatsmodels.Logit()for within-subjects binary data — usepymer4orbambifor GLMMscipy.stats.ttest_ind()for within-subjects — usescipy.stats.ttest_rel()orpingouin.ttest()df.groupby().mean()without checking for equal n — usepingouin.rm_anova()which handles unbalancedsmf.ols()for repeated measures — usesmf.mixedlm()with groups='subject_id'pingouin.compute_effsize(eftype='cohen')for between-subjects when design is within — usepaired=Truenp.corrcoef()for within-subjects repeated measures — usepingouin.rm_corr()
Python Anti-Pattern Grep Patterns
| # | Anti-Pattern | Grep | Why |
|---|---|---|---|
| 1 | import * | grep -q "import \*" script.py | Namespace pollution |
| 2 | Absolute paths | `grep -qE "/Users/ | /home/ |
| 3 | iterrows() | grep -q "iterrows()" script.py | Performance |
| 4 | No random_state | grep -q "scipy.stats\." script.py && ! grep -q "random_state" script.py | Non-reproducible |
| 5 | No savefig | ! grep -q "savefig" script.py | Figures not saved |
| 6 | chained_assignment | grep -q "chained_assignment" script.py | Hides warnings |
| 7 | f_oneway() within-subjects | grep -q "f_oneway" script.py | Wrong for within-subjects; use pingouin.rm_anova() |
| 8 | Logit() within-subjects | grep -q "Logit(" script.py | No random effects; use pymer4 or bambi |
| 9 | ttest_ind() within-subjects | grep -q "ttest_ind" script.py | Wrong for within-subjects; use ttest_rel() or pingouin.ttest() |
| 10 | groupby().mean() without n-check | grep -q "groupby.*mean" script.py | Ignores unequal n; use pingouin.rm_anova() |
| 11 | smf.ols() repeated measures | grep -q "smf.ols" script.py | No random effects; use smf.mixedlm() with groups= |
| 12 | compute_effsize.*cohen no paired | grep -q "compute_effsize.*cohen" script.py | paired=True needed for within-subjects designs |
| 13 | np.corrcoef() within-subjects | grep -q "np.corrcoef" script.py | Doesn't handle repeated measures; use pingouin.rm_corr() |
Scope Limitation Rule
At the start of every review output, state what was and was not reviewed:
Scope: Review covers statistical correctness, reproducibility, assumption checking, and reporting completeness of the provided analysis script. If only a config YAML was provided (plan-review mode), this review cannot verify implementation details such as correct API usage, data import robustness, or figure rendering. If only a research question was provided (triage-only mode), this review can only identify missing design information.
Note: The output format adapts to the review mode. In analysis-audit mode, include the full output below. In plan-review mode, skip Anti-Pattern Scan Results (no script to scan). In triage-only mode, output only the missing-information list.
Output Format
## Review Mode
{analysis-audit | plan-review | triage-only | blocked}
## Scope
{What was and was not reviewed}
## Readiness Label
{ready_for_publication | ready_after_minor_fixes | not_ready | analysis_plan_ready | blocked}
## Critical Issues
- {issue} — {how to fix}
## Major Issues
- {issue} — {how to fix}
## Minor Issues
- {issue} — {how to fix}
## Anti-Pattern Scan Results
- R patterns found: {count} / 8 checked
- Python patterns found: {count} / 13 checked
## Assumption Check Results
- Normality: {pass/fail per condition}
- Sphericity: {pass/fail} (if applicable)
- Homogeneity: {pass/fail} (if applicable)
## Reproducibility Score
Seed: {present/absent}
Session info: {present/absent}
Exclusion log: {present/absent}
Relative paths: {yes/no}
## Overall Verdict
{1-2 sentence summary}
Recovery Loop
The audit is not a one-shot report — after issues are found, enter a check → fix → re-check loop until passing.
Loop Flow
psy-ana-coder generates code
│
▼
psy-ana-reviewer audits
│
├── Critical/Major issues → fix (see fix paths below) → re-audit
│ ↑ │
│ └────────────────────┘
│ loop until 0 Critical + 0 Major
│
└── 0 Critical + 0 Major → pass, deliver final file
Fix Paths
| Issue Type | Who Fixes | How to Fix |
|---|---|---|
| Incorrect statistical method choice | psy-ana-designer | Modify questions[].user_choice → psy-ana-coder regenerates |
| Code implementation error (API misuse) | psy-ana-coder | Based on specific line numbers and correct API pointed out by reviewer, directly fix the code |
| Inappropriate parameter/threshold | psy-ana-coder | Modify corresponding field in config YAML → regenerate |
| Missing effect size / figure / environment info | psy-ana-coder | Add missing code block → reviewer re-audits |
| Hardcoded data path | psy-ana-coder | Replace with config-driven path → reviewer re-audits |
"Round N audit: {X} issues found. After fixes, proceed to round N+1."
A re-audit is mandatory after each fix. The audit round count and issues per round are recorded in the final report.