Skill: /experiment — OpenXP Experimentation Platform
Purpose
Multi-mode skill for the full experiment lifecycle — from design through analysis to ship/no-ship decision. Orchestrates experiment agents and calls coded statistical helpers from helpers/stats/experiment_stats/ instead of improvising Python.
When to Use
Invoke as /experiment [mode] or trigger on experiment-related intents:
- "I want to run an experiment"
- "Analyze this A/B test"
- "Did this experiment work?"
- "What's the power for this test?"
Modes
/experiment design
Purpose: Create a pre-registered experiment config.
Agent: agents/experiments/experiment-designer.md
Flow:
- Run Experiment Brief skill to capture hypothesis, north star, guardrails
- Invoke Experiment Designer agent
- Output:
experiments/{slug}/experiment.yaml (from templates/experiment.yaml)
Checkpoint: Config review (Type B — skippable with --just-do-it)
/experiment power
Purpose: Power analysis + duration estimation.
Flow:
- Read
experiments/{slug}/experiment.yaml for metric type, baseline, MDE
- Call
helpers/stats/experiment_stats/power.py:
- Proportion metric →
power_proportion(baseline_rate, mde)
- Continuous metric →
power_mean(baseline_mean, baseline_std, mde)
- Call
duration_estimate(total_sample, daily_traffic, allocation)
- Update
experiment.yaml with computed values (sample_size, duration, viable)
- If NOT_VIABLE → suggest
/causal select as alternative
Checkpoint: Power viability (Type C — NOT_VIABLE fires mandatory checkpoint)
/experiment analyze
Purpose: Run statistical tests on experiment data.
Agent: agents/experiments/experiment-analyzer.md
Flow:
- Read
experiments/{slug}/experiment.yaml for pre-registered config
- SRM Gate (mandatory first step):
from helpers.stats.experiment_stats import srm_check
# Positional lists ONLY — do not pass dicts.
# First arg: observed counts per variant (order must match expected_ratios).
# Second arg: expected allocation ratios, summing to 1.0.
result = srm_check([4218, 4196], [0.5, 0.5])
# result = {"chi2_stat": 0.058, "p_value": 0.81, "verdict": "PASS", ...}
if result["verdict"] == "BLOCK":
# HALT — do not proceed to treatment effect analysis
- Treatment effect analysis using coded helpers:
from helpers.stats.experiment_stats import welch_test, proportion_test, ratio_metric_test
# Select based on metric type from experiment.yaml
if metric_type == "proportion":
result = proportion_test(c_success, c_n, t_success, t_n)
elif metric_type == "continuous":
result = welch_test(control_values, treatment_values)
elif metric_type == "ratio":
result = ratio_metric_test(num_c, den_c, num_t, den_t)
- Effect size:
cohens_d(control, treatment)
- Multiple comparisons:
adjust_pvalues(all_p_values, method="holm")
- Guardrail checks against thresholds from experiment.yaml
- Segment analysis (Simpson's paradox check)
- Output:
experiments/{slug}/working/analysis_results.json
Checkpoint: SRM gate (Type C — BLOCK halts everything)
/experiment interpret
Purpose: Walk the Result Interpretation Tree and classify the outcome.
Agent: agents/experiments/experiment-interpreter.md
Flow:
- Read analysis results from
experiments/{slug}/working/analysis_results.json
- Walk the Result Interpretation Tree:
- Positive result + clean guardrails → SHIP
- Positive result + degraded guardrails → INVESTIGATE (Mixed Results Framework)
- Null result (powered) → ABORT (no evidence of benefit)
- Null result (underpowered) → LEARN (extend or re-design)
- Negative result → ABORT
- SRM or data quality issue → INVALID
- Apply Spotify's EwL classification: Ship / Abort / Learn / Invalid
- Reference pre-registered decision rules from experiment.yaml
- Output: classification + rationale
Checkpoint: Ship decision (Type C — always fires); INVALID → refuse to proceed
/experiment report
Purpose: Generate markdown report from analysis results.
Agent: agents/experiments/experiment-readout.md
Flow:
- Read analysis results (structured JSON, not re-computing)
- Read experiment.yaml for context
- Fill report template (
templates/experiment-report.md)
- Adapt to audience (executive/technical/cross-functional)
- Output:
experiments/{slug}/reports/experiment_report_{{DATE}}.md
/experiment monitor
Purpose: SRM check + guardrail status + sample tracking during a running experiment.
Agent: agents/experiments/experiment-monitor.md
Flow:
- Read experiment.yaml for expected allocation and guardrail thresholds
- Run
srm_check() with p < 0.0005 threshold (Microsoft production standard)
- Run guardrail tests (one-sided where appropriate)
- Track sample accumulation vs. required sample size
- Output:
experiments/{slug}/working/monitoring_update.md
- Traffic light status: GREEN (on track) / YELLOW (watch) / RED (halt)
Checkpoint: RED guardrail (Type C — triggers halt)
/experiment status
Purpose: Show experiment lifecycle state.
Flow:
- Read
experiments/{slug}/experiment.yaml
- Display: current status, key metrics, timeline, any blockers
- No agent needed — direct YAML read and format
/experiment full
Purpose: End-to-end: design → power → analyze → interpret → report.
Flow: Runs design, power, analyze, interpret, report in sequence.
Checkpoints: All Type C checkpoints fire. Type B skipped with --just-do-it.
State Management
experiments/{slug}/
├── experiment.yaml # Pre-registered config (tracked)
├── working/ # Intermediates (gitignored)
│ ├── analysis_results.json
│ ├── monitoring_update.md
│ └── ...
└── reports/ # Final reports (tracked)
└── experiment_report_{{DATE}}.md
Helper Function Reference
All statistical work uses coded helpers from helpers/stats/experiment_stats/:
| Function |
Module |
Use For |
welch_test() |
ab_tests |
Continuous metric A/B test |
proportion_test() |
ab_tests |
Binary metric A/B test |
ratio_metric_test() |
ab_tests |
Ratio metric (delta method) |
winsorize() |
ab_tests |
Outlier-robust pre-processing |
power_proportion() |
power |
Sample size for proportions |
power_mean() |
power |
Sample size for means |
detectable_effect() |
power |
MDE from fixed sample |
duration_estimate() |
power |
Timeline planning |
srm_check() |
srm |
Sample ratio mismatch |
srm_diagnose() |
srm |
Segmented SRM root cause |
cohens_d() |
effect_size |
Standardized effect size |
relative_lift() |
effect_size |
Percentage change |
adjust_pvalues() |
corrections |
Multiple comparison correction |
cuped_adjust() |
variance_reduction |
CUPED variance reduction |
confidence_sequence() |
sequential |
Always-valid CI (peeking ok) |
bayesian_proportion() |
bayesian |
Bayesian A/B (proportions) |
bayesian_mean() |
bayesian |
Bayesian A/B (means) |
Cross-Product Handoffs
/experiment power → NOT_VIABLE → suggest /causal select (quasi-experimental)
/causal select → "Can you randomize? YES" → suggest /experiment design
/experiment analyze → SRM BLOCK → suggest investigating assignment logic
1---2name: experiment3description: >-4 The analysis and lifecycle owner for experiments. Full experiment lifecycle: design, power analysis,5 statistical analysis, interpretation, reporting, and monitoring of A/B tests. Invoke as /experiment.6 Trigger on "A/B test", "experiment", "treatment vs control", "sample size", "MDE", "statistical7 significance", "ship decision", "test readout", "is this result significant?". Runs the SRM gate8 first.9---1011# Skill: /experiment — OpenXP Experimentation Platform1213## Purpose14Multi-mode skill for the full experiment lifecycle — from design through analysis to ship/no-ship decision. Orchestrates experiment agents and calls coded statistical helpers from `helpers/stats/experiment_stats/` instead of improvising Python.1516## When to Use17Invoke as `/experiment [mode]` or trigger on experiment-related intents:18- "I want to run an experiment"19- "Analyze this A/B test"20- "Did this experiment work?"21- "What's the power for this test?"2223## Modes2425### `/experiment design`26**Purpose:** Create a pre-registered experiment config.27**Agent:** `agents/experiments/experiment-designer.md`28**Flow:**291. Run Experiment Brief skill to capture hypothesis, north star, guardrails302. Invoke Experiment Designer agent313. Output: `experiments/{slug}/experiment.yaml` (from `templates/experiment.yaml`)32**Checkpoint:** Config review (Type B — skippable with --just-do-it)3334### `/experiment power`35**Purpose:** Power analysis + duration estimation.36**Flow:**371. Read `experiments/{slug}/experiment.yaml` for metric type, baseline, MDE382. Call `helpers/stats/experiment_stats/power.py`:39 - Proportion metric → `power_proportion(baseline_rate, mde)`40 - Continuous metric → `power_mean(baseline_mean, baseline_std, mde)`413. Call `duration_estimate(total_sample, daily_traffic, allocation)`424. Update `experiment.yaml` with computed values (sample_size, duration, viable)435. If NOT_VIABLE → suggest `/causal select` as alternative44**Checkpoint:** Power viability (Type C — NOT_VIABLE fires mandatory checkpoint)4546### `/experiment analyze`47**Purpose:** Run statistical tests on experiment data.48**Agent:** `agents/experiments/experiment-analyzer.md`49**Flow:**501. Read `experiments/{slug}/experiment.yaml` for pre-registered config512. **SRM Gate (mandatory first step):**52 ```python53 from helpers.stats.experiment_stats import srm_check54 # Positional lists ONLY — do not pass dicts.55 # First arg: observed counts per variant (order must match expected_ratios).56 # Second arg: expected allocation ratios, summing to 1.0.57 result = srm_check([4218, 4196], [0.5, 0.5])58 # result = {"chi2_stat": 0.058, "p_value": 0.81, "verdict": "PASS", ...}59 if result["verdict"] == "BLOCK":60 # HALT — do not proceed to treatment effect analysis61 ```623. Treatment effect analysis using coded helpers:63 ```python64 from helpers.stats.experiment_stats import welch_test, proportion_test, ratio_metric_test65 # Select based on metric type from experiment.yaml66 if metric_type == "proportion":67 result = proportion_test(c_success, c_n, t_success, t_n)68 elif metric_type == "continuous":69 result = welch_test(control_values, treatment_values)70 elif metric_type == "ratio":71 result = ratio_metric_test(num_c, den_c, num_t, den_t)72 ```734. Effect size: `cohens_d(control, treatment)`745. Multiple comparisons: `adjust_pvalues(all_p_values, method="holm")`756. Guardrail checks against thresholds from experiment.yaml767. Segment analysis (Simpson's paradox check)778. Output: `experiments/{slug}/working/analysis_results.json`78**Checkpoint:** SRM gate (Type C — BLOCK halts everything)7980### `/experiment interpret`81**Purpose:** Walk the Result Interpretation Tree and classify the outcome.82**Agent:** `agents/experiments/experiment-interpreter.md`83**Flow:**841. Read analysis results from `experiments/{slug}/working/analysis_results.json`852. Walk the Result Interpretation Tree:86 - Positive result + clean guardrails → **SHIP**87 - Positive result + degraded guardrails → **INVESTIGATE** (Mixed Results Framework)88 - Null result (powered) → **ABORT** (no evidence of benefit)89 - Null result (underpowered) → **LEARN** (extend or re-design)90 - Negative result → **ABORT**91 - SRM or data quality issue → **INVALID**923. Apply Spotify's EwL classification: Ship / Abort / Learn / Invalid934. Reference pre-registered decision rules from experiment.yaml945. Output: classification + rationale95**Checkpoint:** Ship decision (Type C — always fires); INVALID → refuse to proceed9697### `/experiment report`98**Purpose:** Generate markdown report from analysis results.99**Agent:** `agents/experiments/experiment-readout.md`100**Flow:**1011. Read analysis results (structured JSON, not re-computing)1022. Read experiment.yaml for context1033. Fill report template (`templates/experiment-report.md`)1044. Adapt to audience (executive/technical/cross-functional)1055. Output: `experiments/{slug}/reports/experiment_report_{{DATE}}.md`106107### `/experiment monitor`108**Purpose:** SRM check + guardrail status + sample tracking during a running experiment.109**Agent:** `agents/experiments/experiment-monitor.md`110**Flow:**1111. Read experiment.yaml for expected allocation and guardrail thresholds1122. Run `srm_check()` with p < 0.0005 threshold (Microsoft production standard)1133. Run guardrail tests (one-sided where appropriate)1144. Track sample accumulation vs. required sample size1155. Output: `experiments/{slug}/working/monitoring_update.md`116 - Traffic light status: GREEN (on track) / YELLOW (watch) / RED (halt)117**Checkpoint:** RED guardrail (Type C — triggers halt)118119### `/experiment status`120**Purpose:** Show experiment lifecycle state.121**Flow:**1221. Read `experiments/{slug}/experiment.yaml`1232. Display: current status, key metrics, timeline, any blockers1243. No agent needed — direct YAML read and format125126### `/experiment full`127**Purpose:** End-to-end: design → power → analyze → interpret → report.128**Flow:** Runs design, power, analyze, interpret, report in sequence.129**Checkpoints:** All Type C checkpoints fire. Type B skipped with --just-do-it.130131## State Management132133```134experiments/{slug}/135├── experiment.yaml # Pre-registered config (tracked)136├── working/ # Intermediates (gitignored)137│ ├── analysis_results.json138│ ├── monitoring_update.md139│ └── ...140└── reports/ # Final reports (tracked)141 └── experiment_report_{{DATE}}.md142```143144## Helper Function Reference145146All statistical work uses coded helpers from `helpers/stats/experiment_stats/`:147148| Function | Module | Use For |149|----------|--------|---------|150| `welch_test()` | `ab_tests` | Continuous metric A/B test |151| `proportion_test()` | `ab_tests` | Binary metric A/B test |152| `ratio_metric_test()` | `ab_tests` | Ratio metric (delta method) |153| `winsorize()` | `ab_tests` | Outlier-robust pre-processing |154| `power_proportion()` | `power` | Sample size for proportions |155| `power_mean()` | `power` | Sample size for means |156| `detectable_effect()` | `power` | MDE from fixed sample |157| `duration_estimate()` | `power` | Timeline planning |158| `srm_check()` | `srm` | Sample ratio mismatch |159| `srm_diagnose()` | `srm` | Segmented SRM root cause |160| `cohens_d()` | `effect_size` | Standardized effect size |161| `relative_lift()` | `effect_size` | Percentage change |162| `adjust_pvalues()` | `corrections` | Multiple comparison correction |163| `cuped_adjust()` | `variance_reduction` | CUPED variance reduction |164| `confidence_sequence()` | `sequential` | Always-valid CI (peeking ok) |165| `bayesian_proportion()` | `bayesian` | Bayesian A/B (proportions) |166| `bayesian_mean()` | `bayesian` | Bayesian A/B (means) |167168## Cross-Product Handoffs169170- `/experiment power` → NOT_VIABLE → suggest `/causal select` (quasi-experimental)171- `/causal select` → "Can you randomize? YES" → suggest `/experiment design`172- `/experiment analyze` → SRM BLOCK → suggest investigating assignment logic