psy-ana-designer — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited psy-ana-designer (Agent Skill) and scored it 92/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 2 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 2 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
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.
v1.3 — stable, 2026-06-10. Sub-skill of amazing-psycoder.
Transform experimental data and scientific questions into a complete analysis plan. Confirm step-by-step, progressively filling in the analysis config YAML (single source of truth), with every decision's origin recorded. Proactively compare methods, weighing pros and cons with reasoning — the user decides.
Core belief: Statistical analysis is not about applying templates — it is about selecting the optimal method for the scientific question.
psy-ana-coderpsy-ana-reviewerpsy-exp-designer[ASSUMED], reviewed at Gate 5用户确认 / 范式惯例 / 通用默认 / 自动推断| # | Rule |
|---|---|
| 1 | Do not recommend analysis methods until the scientific question is understood |
| 2 | Do not finalize method selection until fundamental data characteristics are confirmed |
| 3 | Every method selection must include a 12-dimension comparison rationale |
| 4 | All data exclusion rules must be confirmed by the user |
| 5 | Never recommend a method unsuitable for the data structure |
version: "1.0" # Config schema version, used for coder compatibility validation
experiment: # Reference to experiment config + data file organization
config_path:
data_path: # Data file directory
file_pattern: # File naming pattern, e.g. "sub-{subject_id}_stroop.csv"
file_format: # csv / tsv / txt / xlsx
multi_file: # true (one file per subject) / false (all subjects in one file)
n_subjects: # Total number of subjects
design: # Extracted from experiment config
ivs: # Independent variables (name, type, number of levels)
dvs: # Dependent variables (name, type, unit)
design_type: # within / between / mixed
questions: # Scientific questions and analysis methods for each DV
- id: Q1
question: # Scientific question (natural language)
dv: # Dependent variable
method_a: # Method A (user's inclination / common practice)
method_b: # Method B (recommended / superior)
rationale: # Selection rationale
user_choice: # User's final decision
model_formula:# R model formula
cleaning: # Data cleaning rules
rt_lower: # RT lower bound (ms)
rt_upper: # RT upper bound (ms)
accuracy_min: # Minimum accuracy
trial_exclusion:# Trial exclusion rule (SD multiplier)
missing_policy: # listwise / mice
model: # Statistical model global settings
seed: # Random seed
contrast: # Contrast scheme (treatment / sum / helmert) — controls how factor levels are coded, affecting main effect interpretation
correction: # Multiple comparison correction (Bonferroni / FDR / Tukey / none) — controls p-value adjustment method
output: # Output settings
save_path:
report_format: # RMarkdown / Quarto
figures: # Figure list
effect_sizes: # Cohen's d / η²pThe sole goal of the conversation: fill every item in this config. Each phase fills its corresponding section.
Each phase follows:
Fill config: design · experiment.config_path
Goal: Understand what the experiment did and what questions it aims to answer.
First confirm the location of the experiment config YAML:
"请提供实验的 config YAML 文件路径。这个文件通常是 psy-exp-designer 生成的。如果没有,也可以直接描述你的实验设计。"
When a config file exists: Auto-extract after reading — do not ask:
When no config file: Collect core information via 3 questions:
1. "你的实验有几个自变量(IV)?每个叫什么名字、几个水平?" 2. "你的因变量(DV)是什么?测量什么?(RT/准确率/分数)" 3. "实验设计是被试内(同一批人做所有条件)还是被试间(不同组做不同条件)?"
After collection, fill the design section, annotating source as 用户确认.
# Auto-filled
design:
ivs: [{name: condition, type: categorical, levels: [congruent, incongruent]}]
dvs: [{name: rt, type: continuous, unit: ms}, {name: acc, type: binary}]
design_type: within"你的核心研究问题是什么?不是'我要用什么方法',是'我要回答什么科学问题'。"
If the user says "I want to do ANOVA," follow up: "ANOVA 是方法。你具体想检验什么?"
Guiding example: "Stroop 一致 vs 不一致条件 RT 是否有显著差异?"
If the experiment config has multiple DVs, confirm the corresponding scientific question for each one.
| DV | Scientific Question | Expected Direction |
|---|---|---|
| rt | 一致 vs 不一致 RT 差异? | 不一致更慢 |
| acc | 条件间错误率差异? | 探索性 |
Gate 1: Every DV corresponds to at least one clear scientific question. Questions are recorded in natural language in config questions[].question.
Phase 1 Decision Checklist (example):
| # | Decision Item | Value | Source |
|---|---|---|---|
| 1 | Experiment paradigm | Stroop | 自动推断 |
| 2 | Design type | Within-subject | 自动推断 |
| 3 | DV: rt | Continuous, ms | 自动推断 |
| 4 | DV: acc | Binary | 自动推断 |
| 5 | Scientific question Q1 | 一致 vs 不一致 RT 差异 | 用户确认 |
| 6 | Scientific question Q2 | 条件间准确率差异 | 用户确认 |
Fill config: experiment.data_path · design (confirmation)
Goal: Confirm what the data looks like — do not assume. This is the critical foundation for code generation — data structure determines all downstream data import and cleaning logic.
"你的实验数据是怎么存储的?"
Confirm the following step by step — order cannot be skipped:
#### 2.1.1 File Hierarchy
"有多少个被试?每个被试一个数据文件,还是所有被试在一个文件里?"
| Common Scenario | Example | Subsequent Handling |
|---|---|---|
| One file per subject | sub-001.csv, sub-002.csv … | Batch read + merge, or process per file |
| All subjects in one file | all_data.csv | Group by subject_id column |
| One file per subject per condition | sub-001_congruent.csv, sub-001_incongruent.csv | Need to understand filename encoding rules |
#### 2.1.2 File Naming Rules
If one file per subject, must confirm naming rules to enable batch reading:
"数据文件是怎么命名的?例如 sub-001_stroop.csv?被试编号在文件名什么位置?"Example confirmations:
sub-{subject_id}_{task}.csv or P{number}_session{1/2}.txt?control/sub-001.csv vs experimental/sub-001.csv?Record in config:
experiment:
data_path: "data/" # Data directory
file_pattern: "sub-{subject_id}_stroop.csv" # File naming pattern
file_format: "csv" # csv / tsv / txt / xlsx
multi_file: true # Whether multi-file#### 2.1.3 File Format and Reading Method
"数据文件是什么格式?"
| Format | Confirmation Items | R Read | Python Read |
|---|---|---|---|
| CSV | Delimiter (, ; \t)? Has header? | readr::read_csv() | pd.read_csv() |
| TSV/TXT | Delimiter (\t space)? Encoding? | readr::read_tsv() | pd.read_csv(sep='\t') |
| Excel | Which sheet? Which row does data start? | readxl::read_excel() | pd.read_excel() |
| Special format | e.g. Psychopy csv + log mixed | Need to confirm skip rows / extraction rules | Same as above |
If raw data files are available, ask the user to show the first few rows or str() output of at least two subjects' files to verify structural consistency.
Confirm the internal data structure of individual files:
#### 2.2.1 Column Names and Variable Mapping
Confirm column names one by one — do not ask irrelevant questions:
"确认以下列名:被试 ID 列名?条件列名?几个水平?RT 列名?单位 ms/s?正确性列?编码方式?"
For column names inferable from the experiment config, present them directly and only ask about what is uncertain.
"除了这些核心列,数据文件里还有其他列吗?(如 trial 序号、block 编号、stimulus 文件名等)有的话也告诉我——后续分析可能需要用到。"
#### 2.2.2 Data Structure Verification
Ask the user to show the first few rows of at least 1-2 subjects' files:
"方便展示一下某个被试数据文件的前几行吗?我确认一下结构。" or "在 R 里跑一下 str(read_csv('sub-001.csv')) 给我看。"Verify:
Confirm (infer from config as much as possible; only ask what cannot be inferred):
Gate 2: Data file organization confirmed (file hierarchy + naming rules + format); variable mapping table confirmed; design type confirmed. If multi-file naming rules are not confirmed, do not proceed to Phase 3.
Phase 2 Decision Checklist (example):
| # | Decision Item | Value | Source |
|---|---|---|---|
| 1 | Data file organization | One file per subject, 30 subjects | 用户确认 |
| 2 | File naming pattern | sub-{subject_id}_stroop.csv | 用户确认 |
| 3 | File format | CSV, comma-delimited, with header | 用户确认 |
| 4 | subject_id column name | subject_id | 用户确认 |
| 5 | Condition column + levels | condition, 2 levels (congruent/incongruent) | 用户确认 |
| 6 | RT column + unit | rt, ms | 用户确认 |
| 7 | Accuracy column + coding | acc, 1=correct/0=incorrect | 用户确认 |
| 8 | Trials per subject per condition | ~60 | 用户确认 |
| 9 | Design type | Within-subject | 自动推断 |
| 10 | Additional columns | trial_id, block | 用户确认 |
Fill config: questions[].method_* · questions[].rationale · model.correction · model.seed
Goal: Confirm fundamental data characteristics first, then match analysis methods. This is the core phase.
"在确定方法之前,先确认几个关于数据的问题:"
>
1. "RT 分布大概什么样?严重右偏还是大致对称?各条件准确率有没有接近 100% 或 0%?" 2. "不同被试之间波动大吗?有没有表现特别异常的(准确率很低/RT 特别快或慢)?" 3. "有缺失试次吗?大概比例是多少?"
If the user is unsure: Have the user do a quick check and come back —
"在 R 里跑一下summary(data)和hist(data$rt),一分钟。告诉我分布大概什么样。"
Adjust subsequent method selection based on responses:
| User Feedback | Method Adjustment |
|---|---|
| RT severely right-skewed | → Prefer Gamma GLMM or log(RT) for Option B |
| Some condition accuracy ~95% | → ANOVA prohibited, must use logistic model |
| Large between-subject variance | → Prefer mixed model for Option B |
| ~3% missing, random | → Listwise deletion acceptable |
Auto-match candidates from experiment config design type + data characteristics from Phase 3.1. See methods/ for detailed descriptions of each method.
Method Selection Decision Tree:
DV type?
├── Continuous (RT/Score)
│ ├── Within-subject → 2 groups: paired t-test / lmer
│ │ 3+ groups: repeated measures ANOVA / lmer
│ │ Non-normal: Wilcoxon / Friedman
│ │ Severely right-skewed: Gamma GLMM
│ ├── Between-subject → 2 groups: Welch t-test
│ │ 3+ groups: one-way ANOVA / Kruskal-Wallis
│ └── Mixed design → Mixed ANOVA / lmer
│
├── Binary (correct/incorrect)
│ ├── Any condition accuracy >90% or <10% → **force glmer(binomial)**
│ └── Accuracy 10-90% → glmer recommended, ANOVA acceptable (note limitations)
│
├── Categorical → Chi-square test / Fisher's exact test
├── Ordinal (Likert) → Ordinal logistic regression
├── Two continuous variables → Pearson/Spearman correlation / rmcorr (within-subject)
├── Count (error count) → Poisson/NB regression
├── Proportion (accuracy %) → Beta regression
├── Time-to-event (Stop-signal) → Cox regression / Log-Rank test
└── Mechanism test → Mediation analysis / Moderation analysis / SEM| Question Type | Design | Candidate A (Common) | Candidate B (Potentially Superior) |
|---|---|---|---|
| Two-group comparison | Within | paired t-test | lmer + random effects |
| Two-group comparison | Between | independent t-test | — |
| Multi-group comparison | Within | repeated measures ANOVA | lmer + random effects |
| Multi-group comparison | Between | one-way ANOVA | Kruskal-Wallis (non-normal) |
| Interaction | Within | two-way ANOVA | lmer + maximal random effects |
| Binary DV | Within | repeated measures ANOVA (%) | glmer(binomial) |
| Non-normal RT | Within | traditional ANOVA | Gamma GLMM / log(RT)+lmer |
For each scientific question, compare A vs B across 12 dimensions:
| Dimension | What to Examine |
|---|---|
| Statistical power | Which detects effects more easily? Sample size requirements? |
| False positive control | False positive inflation when assumptions violated? |
| Data utilization | Aggregate to means or use all trials? |
| Outlier sensitivity | Do extreme values distort results? |
| Assumption robustness | When normality/homoscedasticity/sphericity violated? |
| Interpretability | Can reviewers understand it? |
| Field acceptance | Recognition level in the field? |
| Effect size comparability | Standardized? Meta-analyzable? |
| Replicability | Method standardized? |
| Extensibility | Easy to add covariates / change design? |
| Sample size constraints | Minimum N? Reliable with small samples? |
| Computational feasibility | Can the user run it? Learning cost? |
Format: Dimension table + comprehensive recommendation ("侧重 X 选 B,侧重 Y 选 A"), user makes final decision.
Record decision in config:
questions:
- id: Q1
question: "一致 vs 不一致条件 RT 差异"
dv: rt
method_a: paired t-test
method_b: lmer(rt ~ condition + (1+condition|subject))
rationale: "每被试每条件 60 试次,EDA 未发现严重偏态。混合模型利用全部数据+可扩展"
user_choice: method_b
model_formula: "rt ~ condition + (1 + condition | subject_id)"When multi-group comparisons are involved, confirm: Bonferroni (conservative) / FDR (exploratory) / Tukey HSD (pairwise) / No correction (pre-registered single hypothesis).
"Set a random seed for reproducibility. Any integer works — 20240610, 42, etc. ⚠️ Default: current date in YYYYMMDD format."
The seed is recorded in model.seed and injected into the generated code as set.seed() / np.random.seed(). This ensures the analysis produces identical results on every run.
Gate 3: Methods selected for every scientific question (with 12-dimension comparison rationale), multiple comparison scheme confirmed, seed set.
Phase 3 Decision Checklist: Each question's A vs B choice and rationale, multiple comparison scheme. All annotated with source.
Fill config: cleaning · output · model.contrast
Goal: Confirm cleaning standards, missing data handling, effect sizes, and figures.
About `model.contrast` (contrast scheme) vs `model.correction` (multiple comparison correction): - contrast controls how factor levels are coded (treatment = compared to reference level, sum = compared to grand mean, helmert = compared to mean of previous levels), affecting coefficient interpretation in summary() output - correction controls p-value adjustment method for post-hoc pairwise comparisons (Bonferroni/FDR/Tukey) - Default: contrast = treatment ⚠️, correction = Bonferroni ⚠️ (unless specific needs arise)
| Cleaning Item | Common Default | Why |
|---|---|---|
| RT lower bound | 100-150ms ⚠️ | Below this, response cannot be genuine |
| RT upper bound | 2000-3000ms ⚠️ | Depends on task difficulty |
| Correct trials only | Analyze only correct RTs ⚠️ | RTs from incorrect trials are unreliable |
| Subject exclusion | acc < 60-70% ⚠️ | Exclude inattentive subjects |
| Trial exclusion | ±2.5 SD, per subject per condition ⚠️ | Standard practice |
Each comes with rationale. Default values marked ⚠️, uniformly reviewed at Gate 5.
Missing <5% and random → listwise deletion ⚠️. >5% or patterned → multiple imputation (mice). Non-random → sensitivity analysis.
APA 7th defaults, marked ⚠️: t→Cohen's d+CI, ANOVA→η²p, mixed model→conditional differences+CI.
Figure Selection Decision Tree:
What do you want to show?
├── Distribution
│ └── Within-subject two groups → Raincloud plot (preferred) / Individual connecting lines
│ Multi-group comparison → Violin plot / Boxplot+scatter / Ridge plot (3+ groups)
│ Univariate → Histogram / Density plot
│ Normality check → QQ plot
│
├── Correlation
│ └── Two continuous variables → Scatter+regression / Correlation ellipse / Marginal distribution
│ Multi-variable (4+) → Correlation heatmap / Correlogram (3-8)
│ Large sample >5000 → Hexbin
│
├── Comparison
│ └── Between-subject multi-group → Bar chart / Lollipop chart / Cleveland dot plot
│ Pre-post → Dumbbell chart / Slope chart / Individual connecting lines
│ Multi-variable profile → Radar chart / Parallel coordinates
│ Interaction → Interaction plot + significance annotation
│
├── Evolution
│ └── Time series → Line chart / Time series plot (individual+mean)
│ Categorical change → Alluvial plot / Stacked area chart
│
├── Composition
│ └── Proportions → Donut chart / Waffle chart / Treemap
│ Categorical cross → Mosaic plot / Upset plot
│
└── Special
└── Meta-analysis → Forest plot + Funnel plot
Diagnostic → ROC curve
Survival → Kaplan-Meier
Agreement → Bland-Altman
Network → Network graph / Chord diagram
Clustering → Dendrogram
Dimensionality reduction → BiplotSee plots/ directory for details.
ggplot(data, aes(x,y,fill,color,group)) + geom_xxx() + scale_xxx() + facet_xxx() + labs() + theme_xxx()
| geom | Use | geom | Use |
|---|---|---|---|
geom_point() | Scatter | geom_line() | Line |
geom_boxplot() | Boxplot | geom_violin() | Violin |
geom_histogram() | Histogram | geom_density() | Density |
geom_col() | Bar | geom_smooth() | Fitted line |
geom_qq()+geom_qq_line() | QQ plot | geom_jitter() | Jittered scatter |
geom_errorbar() | Error bar | geom_tile() | Heatmap |
geom_segment() | Segment | geom_ribbon() | Confidence band |
Common: scale_fill_brewer(palette="Set2"), scale_fill_viridis_d(), facet_wrap(~var), theme_minimal(), ggsave("path",dpi=300)
| R (ggplot2) | Python | R (ggplot2) | Python |
|---|---|---|---|
geom_violin() | sns.violinplot() | geom_boxplot() | sns.boxplot() |
geom_point() | sns.scatterplot() | geom_line() | sns.lineplot() |
geom_histogram() | sns.histplot() | geom_density() | sns.kdeplot() |
geom_bar() | sns.barplot() | geom_smooth() | sns.regplot() |
facet_wrap() | sns.catplot(col=) | geom_jitter() | sns.stripplot() |
geom_tile() | sns.heatmap() | theme_minimal() | sns.set_theme(style="whitegrid") |
ggsave() | plt.savefig(dpi=300) |
Gate 4: Cleaning standards, missing data strategy, effect sizes, figure types confirmed. All default values marked ⚠️.
Phase 4 Decision Checklist: Each default value marked ⚠️, confirmed or modified by user.
Goal: Summarize all decisions; user gives final confirmation. Do not display YAML — only display the decision registry.
| # | Phase | Decision Item | Value | Source |
|---|---|---|---|---|
| 1 | Phase 1 | Scientific question Q1 | 一致 vs 不一致 RT | 用户确认 |
| 2 | Phase 1 | DV: rt | Continuous, ms | 自动推断 |
| 3 | Phase 2 | RT column name | rt | 用户确认 |
| 4 | Phase 3 | Q1 Method A | paired t-test | 用户倾向 |
| 5 | Phase 3 | Q1 Method B | lmer | 推荐 |
| 6 | Phase 3 | Q1 Final choice | lmer | 用户确认 |
| 7 | Phase 3 | Multiple comparison | FDR | 用户确认 |
| 8 | Phase 4 | RT lower bound | 150ms | 通用默认 ⚠️ |
| 9 | Phase 4 | RT upper bound | 2000ms | 通用默认 ⚠️ |
| 10 | Phase 4 | Missing data handling | Listwise deletion | 通用默认 ⚠️ |
| ... | ... | ... | ... | ... |
⚠️ = Default item, please confirm with special attention. Each decision annotated with source.
"以上所有分析决策确认无误?默认项(标 ⚠️)如需修改请指定编号和新值。"
| Assumption | Test | Fallback if Violated |
|---|---|---|
| Normality | Shapiro-Wilk / QQ | Wilcoxon / Gamma GLMM |
| Homoscedasticity | Levene | Welch correction |
| Sphericity | Mauchly | Greenhouse-Geisser |
□ Scientific question → Method mapping (with comparison rationale) □ Multiple comparison scheme □ Cleaning standards + Missing data strategy (⚠️ default items reviewed) □ Effect sizes + Figures □ Assumption checks + Fallbacks □ Sensitivity analysis plan □ Analysis config complete (can serve as pre-registration analysis plan)
Gate 5: User explicitly confirms all decisions. Save analysis config YAML to analysis_config.yaml (in working directory). Route to psy-ana-coder.
Next step: Analysis plan is complete. Enter/psy-ana-coderand provide theanalysis_config.yamlto that skill to start generating analysis code. You may also enter/psy-ana-reviewerfirst and selectplan-reviewmode for a pre-audit of the analysis plan.
Analysis config YAML complete
│
▼
psy-ana-coder (R script generation)
│
▼
psy-ana-reviewer (audit)Do not skip steps.
| Dimension | A: Paired t | B: lmer | Advantage |
|---|---|---|---|
| Statistical power | 🔴 30 subjects×1 mean=30 points | 🟢 30 subjects×60 trials=1800 points | B |
| False positive control | 🔴 Good when assumptions met | 🟢 Random effects more stable | B |
| Data utilization | 🔴 60 trials→1 mean | 🟢 All trials | B |
| Outlier sensitivity | 🔴 High | 🟢 Naturally weighted | B |
| Assumption robustness | 🔴 Non-normal unreliable | 🟢 Robust SE available | B |
| Interpretability | 🟢 d=0.5 universally understood | 🔴 Must explain fixed+random effects | A |
| Field acceptance | 🟢 Broad | 🔴 Some reviewers demand explanation | A |
| Effect size comparability | 🟢 Cohen's d standard | 🔴 Requires extra computation | A |
| Extensibility | 🔴 Adding covariates = redo | 🟢 +age+gender extends directly | B |
| Computation | 🟢 t.test() | 🔴 Requires lme4+convergence checks | A |
Comprehensive recommendation: Only need condition main effect → A; later add covariates or methodologically rigorous journal → B.
| Dimension | A: ANOVA | B: glmer(binomial) | Advantage |
|---|---|---|---|
| Statistical power | 🔴 Moderate | 🟢 Binomial naturally efficient | B |
| False positive control | 🔴 Proportion violates normality→inflation | 🟢 Binomial distribution self-adapting | B |
| Ceiling effect | 🔴 Ignored, ~100% false positive spikes | 🟢 Naturally handles probability boundaries | B |
| Assumption robustness | 🔴 Proportions inherently non-normal | 🟢 Good | B |
| Interpretability | 🟢 % difference intuitive | 🔴 Odds ratio requires explanation | A |
| Field acceptance | 🟢 Very high | 🔴 Rapidly growing | A→B transitioning |
Comprehensive recommendation: Accuracy 70-90% → either works; near ceiling → must use B.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.