# Psy Exp Designer

> Use for designing and specifying psychological experiments. Guides through a unified 5-phase workflow to produce a complete config YAML, then routes to psy-exp-coder for code generation. Does NOT generate code itself — the orchestration and specification layer. Supports PsychoPy, jsPsych, and Psychtoolbox with 38 paradigm references. Trigger for 中文/English requests about 心理学实验程序、实验代码、PsychoPy、tri…

- **Type:** Skill
- **Install:** `agentstack add skill-soupandpsy-amazing-psycoder-skills-psy-exp-designer`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [soupandpsy](https://agentstack.voostack.com/s/soupandpsy)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [soupandpsy](https://github.com/soupandpsy)
- **Source:** https://github.com/soupandpsy/amazing-psycoder-skills/tree/main/amazing-psycoder/psy-exp-designer

## Install

```sh
agentstack add skill-soupandpsy-amazing-psycoder-skills-psy-exp-designer
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Psychological Experiment Designer

## Version

v1.3 — stable, 2026-06-10. Sub-skill of [amazing-psycoder](../SKILL.md).

## Purpose

Convert psychological experiment ideas into a complete experiment specification (config YAML) through a single, unified workflow. Every design decision accumulates in the **config YAML** — the single source of truth. When the config is complete, this skill routes to `psy-exp-coder` for code generation.

This is the **orchestration and specification layer**. It does NOT generate code — it guides the user through progressive refinement of the experiment design, produces a validated config YAML, then routes to the platform coder for implementation.

## Design Philosophy

**用户的实验，系统的规范。** The user owns the experimental design — every decision is confirmed with them. The system provides the guardrails: paradigm-specific Must-Confirm lists, timing conventions, accuracy rules, and code quality standards. The Design Decision Registry ensures every detail is tracked, every assumption is flagged, and nothing reaches code generation without explicit user approval.

Core principles:
- **输出即交付** — the output (config YAML) is complete and ready for code generation, not a draft
- **渐进确认** — each design detail is confirmed before advancing; defaults are flagged as `[ASSUMED]` and reviewed at Gate 5
- **决策可追溯** — every decision's source is recorded (用户确认 / 范式惯例 / 自动推断)
- **先窗口后代码** — no code is generated before the trial window timeline is complete (Red Line #1)

## When Not to Use

- **Generating or modifying experiment code directly**: That's `psy-exp-coder`'s job. Route there instead.
- **Code review or production audit**: That's `psy-exp-reviewer`'s job. Route there instead.
- **Quick PsychoPy API questions**: If the user asks a general PsychoPy question unrelated to experiment design, answer directly without invoking the full workflow.

## Core Model

Every experiment follows this structure:

```
Experiment → Block → Trial → Window → Data
```

- **Block**: A group of trials sharing the same randomization or condition set. Block types: `practice`, `formal`, `rest`, `debrief`.
- **Window**: A single screen within a trial (fixation, stimulus, mask, feedback)
- **Trial**: One complete unit of stimulus → response → feedback
- **Data**: One row per trial, one column per measured variable

## Red Lines

Hard prohibitions. These must never be violated — no exceptions, no "just this once."

| # | Rule | Applies to | Why |
|---|------|-----------|-----|
| 1 | **No code generation before trial window timeline is complete** | All platforms | Code written without a validated window sequence will have structural errors that are expensive to fix |
| 2 | **No assumed response mapping** | All platforms | Which key means what answer must be confirmed with the user. Guessing invalidates accuracy data |
| 3 | **No `time.sleep()` / `core.wait()` in experiment code** | PsychoPy, jsPsych | Blocks the event loop; Escape becomes unresponsive. Use `CountdownTimer` loops instead |
| 4 | **No `event.getKeys(maxWait=...)`** | PsychoPy | Blocks the event loop. Use `keyboard.Keyboard` with `win.callOnFlip(kb.clock.reset)` |
| 5 | **No data saved only at end of experiment** | All platforms | Crash = all data lost. Save incrementally per trial or per block with `try/finally` |
| 6 | **No silent filling of `[MISSING]` values** | All platforms | Every `[MISSING]` must be resolved by asking the user or offering an explicitly-flagged default |
| 7 | **No Chinese/CJK text without an explicit font** | PsychoPy, Psychtoolbox | Platform default font lacks CJK glyphs; text will render as tofu (□□□). jsPsych relies on browser/OS fonts — verify but no explicit path needed |
| 8 | **No skipping paradigm Must-Confirm items** | All platforms | Each paradigm file lists critical design decisions. Unconfirmed items produce broken experiments |
| 9 | **No `rt_onset` omitted on response windows** | All platforms | Incorrect or missing RT onset invalidates all reaction time data. The coder will refuse to generate if absent |
| 10 | **No code delivery without reviewer pass** | All platforms | All generated code must pass through `psy-exp-reviewer` before data collection. Programming → Coder → Reviewer is a mandatory chain |

## Config as Single Source of Truth

The [experiment config YAML](references/config-schema.md) is the central artifact. Every design decision lives in one file:

```yaml
name:        # experiment name
paradigm:    # which paradigm
platform:    # psychopy / psychtoolbox / jsPsych
stimulus_folder:  # global path for image file references
windows:     # trial event sequence (box timeline → YAML)
blocks:      # block structure + condition file paths
response_rules:  # keys, deadline, accuracy logic
paradigm_config: # paradigm-specific settings
output:      # data directory, filename pattern
```

The conversation has one goal: **fill every `[MISSING]` field in this config**. The user can provide information in any form — prose description, file paths, partial YAML, xlsx files — and the system progressively accumulates it into the config.

## Trial Window Timeline Rule

When clarifying, summarizing, or designing trial logic, **always represent the trial as a sequence of window boxes before writing code**. Do not describe trial events in prose alone — visual timeline first, text second.

Each trial window box must include:

1. Window name (e.g., Fixation, Prime, Target, ITI)
2. Visual content shown on screen
3. Duration (ms, or `until response`)
4. Response rule (none / allowed keys / deadline)
5. **File/Folder** — stimulus file or folder used in this window (if applicable)
6. **Condition source** — which xlsx column drives this window (if applicable)
7. Data recorded at this step, if any

Use this format:

```text
   Window 1: Fixation            Window 2: Stimulus            Window 3: Response   
┌──────────────────────┐      ┌──────────────────────┐      ┌──────────────────────┐
│                      │      │                      │      │                      │
│          +           │  →   │      {stimulus}      │  →   │      {stimulus}      │
│                      │      │                      │      │                      │
└──────────────────────┘      └──────────────────────┘      └──────────────────────┘
    Duration: 500 ms              Duration: 500 ms            Duration: until key   
     Response: none                Response: none               Response: f / j     
       File: none             File: stimuli/images/*.png      Condition: conditions.xlsx
                                 Data: rt, key, acc                                 
```                                                               

**Max 3 windows per row** — if the trial has more than 3 windows, wrap to the next row.

After the box timeline, also provide a structured table:

| Window | Content | Duration | Response | File/Folder | Condition | Data |
|--------|---------|----------|----------|-------------|-----------|------|
| Fixation | + | 500 ms | none | none | none | none |
| Stimulus | {stimulus} | 500 ms | none | stimuli/images/*.png | {stimulus} col | none |
| Response | {stimulus} | until key | f/j | none | {correct_response} col | rt, key, acc |

If any part of the trial logic is unclear, mark it directly as `[MISSING]` inside the box and in the table. Do not silently fill in missing values.

**Do not generate experiment code until the trial window sequence is clear.**

## Unified Workflow

Every new experiment follows the same 5 phases. The order reflects how experimenters naturally design: **trial first (with rules), then blocks**. The config YAML is filled progressively.

```
Phase 1: Assess    → 收集已有信息
Phase 2: Windows   → 定义 Trial + 反应规则（最关键）
Phase 3: Conditions→ 定义 trial 序列（xlsx + 刺激文件）
Phase 4: Blocks    → 定义 block 结构和循环
Phase 5: Validate  → 验证并移交代码生成
```

### Blocking Gates

Hard checkpoints. The workflow does not advance past a gate until its condition is met. If a gate fails, return to the relevant phase; do not proceed.

| Gate | After | Condition | Fail → Return to |
|------|-------|-----------|------------------|
| **Gate 1** | Phase 2 | Trial window timeline has no `[MISSING]`. Every window has `name`, `content`, `duration`, `response`. Response windows have `rt_onset`. Response keys, mapping, accuracy rules, and output format are confirmed. Phase 2 decision checklist presented and user confirmed | Phase 2 |
| **Gate 2** | Phase 3 | Every `{column_name}` in `windows[]` exists in condition xlsx. Condition file is on disk OR has been generated by Phase 3. Stimulus folder (if used) resolves. Phase 3 decision checklist presented and user confirmed | Phase 2 or 3 |
| **Gate 3** | Phase 4 | Config has zero `[MISSING]` markers. All sections (`windows`, `blocks`, `response_rules`, `output`) are complete. Phase 4 decision checklist presented and user confirmed | Phase 2/3/4 (whichever section has `[MISSING]`) |
| **Gate 4** | Phase 5 | All validation rules pass. Validation rules 1-6 (blocking, from config-schema.md) must pass before code generation; rules 7-9 are design-level verification. No missing columns, no broken file paths, no ambiguous accuracy coding | Phase 1/2/3/4 (based on error type, per Phase 5 routing table) |
| **Gate 5** | Phase 5 (before coder) | **Final Design Review**: Full Design Decision Registry presented. User explicitly confirms ALL decisions (including `[ASSUMED]` items) before code generation. No decision left un-reviewed | Phase 1/2/3/4 (user can correct any decision) |

### Phase 1: Assess Input

Determine what the user already has, what paradigm, and what platform.

| User provides | Action |
|--------------|--------|
| Natural-language description ("我想做一个Stroop实验...") | Parse into skeleton config; flag all unknowns as `[MISSING]` |
| Partial config YAML | Load it; identify which sections are filled vs missing |
| config.yaml + conditions/*.xlsx | Load everything; validate; skip to Phase 5 if complete |
| Existing experiment code to modify | Identify the platform; read the code; apply changes; skip to Phase 5 |
| "帮我检查这段代码" | Route to `psy-exp-reviewer` directly |

Also resolve in Phase 1 if the user hasn't stated it:
- Paradigm (match to [paradigm file](paradigms/); ask if unclear)
- Platform (PsychoPy / Psychtoolbox / jsPsych)
- **Operating system + font (blocking)**: Every experiment using text stimuli must confirm the target OS and font before advancing past Phase 1. Ask: "实验在什么操作系统上运行？（macOS / Windows / Linux）" — this determines font paths. If the user doesn't know, the coder will generate auto-detection with a manual override switch. This is not optional — CJK text without proper font = □□□ tofu.

**After loading the paradigm file**: Cross-reference its `## Must Confirm` list against what the user already stated. For each unconfirmed item, assign it to the phase where it will be asked:

| Must Confirm item type | Target phase |
|------------------------|--------------|
| Stimulus identity, content, modality | Phase 2 |
| Key assignment, response mapping | Phase 2 |
| Timing values (durations, deadlines, SOA) | Phase 2 |
| Accuracy rules, error coding, catch trials | Phase 2 |
| Output format (data directory, filename) | Phase 2 |
| Trial counts, condition ratios | Phase 3 |
| Stimulus file source (image vs generated) | Phase 3 |
| Block count, trials per block, feedback presence | Phase 4 |
| Counterbalancing, block order | Phase 4 |

If a Must Confirm item doesn't fit any later phase (e.g., paradigm-specific correctness logic), ask it now in Phase 1. Do not leave Must Confirm items unassigned.

**Output**: Config with `name`, `paradigm`, `platform`, OS filled. Phase 1 Decision Checklist presented for user confirmation before advancing to Phase 2.

### Phase 2: Define Windows & Rules (Trial)

Build the trial window timeline — the most critical phase. Every screen event in a single trial becomes a window. Also finalize all response rules here: key mapping, accuracy logic, and output format. These belong together because the response keys defined in the window timeline directly determine the mapping and accuracy rules.

**What to determine** for each window:
- Window name and order (e.g., Fixation → Stimulus → Response → Feedback → ITI)
- Content (literal text, `{column_reference}`, or image file path)
- Duration (fixed ms, `[min, max]`, `until_key`, or `self_paced`)
- Response rule (none / allowed keys / deadline)
- File/folder reference (which stimulus files?)
- Condition source (which xlsx column drives this window?)

**How to present**: Window name centered above the box, content centered inside, other fields centered below. Box columns 24 chars wide with 6-space gaps. Arrow (→) between boxes.

```text
   Window 1: Fixation            Window 2: Stimulus            Window 3: Response   
┌──────────────────────┐      ┌──────────────────────┐      ┌──────────────────────┐
│                      │      │                      │      │                      │
│          +           │  →   │       [MISSING]      │  →   │       [MISSING]      │
│                      │      │                      │      │                      │
└──────────────────────┘      └──────────────────────┘      └──────────────────────┘
     Duration: [MISSING]           Duration: [MISSING]          Duration: until key   
      Response: none                Response: none               Response: [MISSING]  
        File: none                  File: [MISSING]             Condition: [MISSING]  
                                 Data: rt, key, acc                                 

Format rules:
- Window name/sequence number centered above the box (column width = 24 chars, box + borders)
- Content centered inside the box (box interior = 22 characters)
- Duration, Response, File, Condition, Data centered below the box within each column
- Arrow (→) between windows in the same row: `  →   ` (6 chars, matches gap)
- Box gap = 6 spaces between all columns, all rows aligned
- **Max 3 windows per row** — windows 4+ wrap to the next row automatically
- [MISSING] marks unresolved items that must be confirmed before Gate 1
```

**Questions (max 3)**:
1. "每个窗口的持续时间是多少？反应窗口的截止时间？"
2. "被试按哪些键反应？哪个键对应哪个条件？"
3. "刺激呈现什么内容？文字、图片还是图形？"

Also ask any paradigm Must-Confirm items assigned to Phase 2 (stimulus identity, timing values, key assignment, accuracy rules). Phase 2 typically carries the most Must-Confirm items — if paradigm questions + generic questions exceed the 3-question limit, apply the [Must-Confirm overflow rule](#must-confirm-overflow-rule) (batch compatible questions, default low-risk items with ⚠️ flag, defer to later phases where logical).

**How many windows?** The paradigm determines the window count — it is NOT fixed at 5. Standard RT tasks may have 4 (Fixation → Stimulus → Response → ITI). Masked priming may need 6+ (Forward Mask → Prime → Backward Mask → Target → Response → ITI). The paradigm file's `## Example` section shows the canonical window sequence.

**Stimulus + Response: merge or split?** Two patterns are valid:
- **Split**: Stimulus window (fixed duration, no response) → Response window (stimulus stays + keys accepted). Use when the stimulus must be visible for a fixed time before responses are allowed. RT is measured from Response window onset, excluding stimulus encoding time.
- **Merged**: A single window with `duration: until_key` and `response: [keys]`. Use when the participant responds immediately to the stimulus (e.g., Stroop, Flanker). RT is measured from stimulus onset.

**rt_onset — auto-inferred, not asked.** Do NOT ask the user to choose between split/merged or to specify rt_onset directly. Instead, infer it from the window structure and inform the user:

| Window structure | Inferred rt_onset | Example paradigms |
|------------------|-------------------|-------------------|
| One window has both `content: "{stimulus}"` AND `response: [keys]` | `rt_onset: self` (merged) | Stroop, Flan

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [soupandpsy](https://github.com/soupandpsy)
- **Source:** [soupandpsy/amazing-psycoder-skills](https://github.com/soupandpsy/amazing-psycoder-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-soupandpsy-amazing-psycoder-skills-psy-exp-designer
- Seller: https://agentstack.voostack.com/s/soupandpsy
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
