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: The analysis and lifecycle owner for experiments. Full experiment lifecycle: design, power analysis, statistical analysis, interpretation, reporting, and monitoring of A/B tests. Invoke as /experiment. Trigger on "A/B test", "experiment", "treatment vs control", "sample size", "MDE", "statistical significance", "ship decision", "test readout", "is this result significant?". Runs the SRM gate first.4---56# Skill: /experiment — OpenXP Experimentation Platform78## Purpose9Multi-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.1011## When to Use12Invoke as `/experiment [mode]` or trigger on experiment-related intents:13- "I want to run an experiment"14- "Analyze this A/B test"15- "Did this experiment work?"16- "What's the power for this test?"1718## Modes1920### `/experiment design`21**Purpose:** Create a pre-registered experiment config.22**Agent:** `agents/experiments/experiment-designer.md`23**Flow:**241. Run Experiment Brief skill to capture hypothesis, north star, guardrails252. Invoke Experiment Designer agent263. Output: `experiments/{slug}/experiment.yaml` (from `templates/experiment.yaml`)27**Checkpoint:** Config review (Type B — skippable with --just-do-it)2829### `/experiment power`30**Purpose:** Power analysis + duration estimation.31**Flow:**321. Read `experiments/{slug}/experiment.yaml` for metric type, baseline, MDE332. Call `helpers/stats/experiment_stats/power.py`:34 - Proportion metric → `power_proportion(baseline_rate, mde)`35 - Continuous metric → `power_mean(baseline_mean, baseline_std, mde)`363. Call `duration_estimate(total_sample, daily_traffic, allocation)`374. Update `experiment.yaml` with computed values (sample_size, duration, viable)385. If NOT_VIABLE → suggest `/causal select` as alternative39**Checkpoint:** Power viability (Type C — NOT_VIABLE fires mandatory checkpoint)4041### `/experiment analyze`42**Purpose:** Run statistical tests on experiment data.43**Agent:** `agents/experiments/experiment-analyzer.md`44**Flow:**451. Read `experiments/{slug}/experiment.yaml` for pre-registered config462. **SRM Gate (mandatory first step):**47 ```python48 from helpers.stats.experiment_stats import srm_check49 # Positional lists ONLY — do not pass dicts.50 # First arg: observed counts per variant (order must match expected_ratios).51 # Second arg: expected allocation ratios, summing to 1.0.52 result = srm_check([4218, 4196], [0.5, 0.5])53 # result = {"chi2_stat": 0.058, "p_value": 0.81, "verdict": "PASS", ...}54 if result["verdict"] == "BLOCK":55 # HALT — do not proceed to treatment effect analysis56 ```573. Treatment effect analysis using coded helpers:58 ```python59 from helpers.stats.experiment_stats import welch_test, proportion_test, ratio_metric_test60 # Select based on metric type from experiment.yaml61 if metric_type == "proportion":62 result = proportion_test(c_success, c_n, t_success, t_n)63 elif metric_type == "continuous":64 result = welch_test(control_values, treatment_values)65 elif metric_type == "ratio":66 result = ratio_metric_test(num_c, den_c, num_t, den_t)67 ```684. Effect size: `cohens_d(control, treatment)`695. Multiple comparisons: `adjust_pvalues(all_p_values, method="holm")`706. Guardrail checks against thresholds from experiment.yaml717. Segment analysis (Simpson's paradox check)728. Output: `experiments/{slug}/working/analysis_results.json`73**Checkpoint:** SRM gate (Type C — BLOCK halts everything)7475### `/experiment interpret`76**Purpose:** Walk the Result Interpretation Tree and classify the outcome.77**Agent:** `agents/experiments/experiment-interpreter.md`78**Flow:**791. Read analysis results from `experiments/{slug}/working/analysis_results.json`802. Walk the Result Interpretation Tree:81 - Positive result + clean guardrails → **SHIP**82 - Positive result + degraded guardrails → **INVESTIGATE** (Mixed Results Framework)83 - Null result (powered) → **ABORT** (no evidence of benefit)84 - Null result (underpowered) → **LEARN** (extend or re-design)85 - Negative result → **ABORT**86 - SRM or data quality issue → **INVALID**873. Apply Spotify's EwL classification: Ship / Abort / Learn / Invalid884. Reference pre-registered decision rules from experiment.yaml895. Output: classification + rationale90**Checkpoint:** Ship decision (Type C — always fires); INVALID → refuse to proceed9192### `/experiment report`93**Purpose:** Generate markdown report from analysis results.94**Agent:** `agents/experiments/experiment-readout.md`95**Flow:**961. Read analysis results (structured JSON, not re-computing)972. Read experiment.yaml for context983. Fill report template (`templates/experiment-report.md`)994. Adapt to audience (executive/technical/cross-functional)1005. Output: `experiments/{slug}/reports/experiment_report_{{DATE}}.md`101102### `/experiment monitor`103**Purpose:** SRM check + guardrail status + sample tracking during a running experiment.104**Agent:** `agents/experiments/experiment-monitor.md`105**Flow:**1061. Read experiment.yaml for expected allocation and guardrail thresholds1072. Run `srm_check()` with p < 0.0005 threshold (Microsoft production standard)1083. Run guardrail tests (one-sided where appropriate)1094. Track sample accumulation vs. required sample size1105. Output: `experiments/{slug}/working/monitoring_update.md`111 - Traffic light status: GREEN (on track) / YELLOW (watch) / RED (halt)112**Checkpoint:** RED guardrail (Type C — triggers halt)113114### `/experiment status`115**Purpose:** Show experiment lifecycle state.116**Flow:**1171. Read `experiments/{slug}/experiment.yaml`1182. Display: current status, key metrics, timeline, any blockers1193. No agent needed — direct YAML read and format120121### `/experiment full`122**Purpose:** End-to-end: design → power → analyze → interpret → report.123**Flow:** Runs design, power, analyze, interpret, report in sequence.124**Checkpoints:** All Type C checkpoints fire. Type B skipped with --just-do-it.125126## State Management127128```129experiments/{slug}/130├── experiment.yaml # Pre-registered config (tracked)131├── working/ # Intermediates (gitignored)132│ ├── analysis_results.json133│ ├── monitoring_update.md134│ └── ...135└── reports/ # Final reports (tracked)136 └── experiment_report_{{DATE}}.md137```138139## Helper Function Reference140141All statistical work uses coded helpers from `helpers/stats/experiment_stats/`:142143| Function | Module | Use For |144|----------|--------|---------|145| `welch_test()` | `ab_tests` | Continuous metric A/B test |146| `proportion_test()` | `ab_tests` | Binary metric A/B test |147| `ratio_metric_test()` | `ab_tests` | Ratio metric (delta method) |148| `winsorize()` | `ab_tests` | Outlier-robust pre-processing |149| `power_proportion()` | `power` | Sample size for proportions |150| `power_mean()` | `power` | Sample size for means |151| `detectable_effect()` | `power` | MDE from fixed sample |152| `duration_estimate()` | `power` | Timeline planning |153| `srm_check()` | `srm` | Sample ratio mismatch |154| `srm_diagnose()` | `srm` | Segmented SRM root cause |155| `cohens_d()` | `effect_size` | Standardized effect size |156| `relative_lift()` | `effect_size` | Percentage change |157| `adjust_pvalues()` | `corrections` | Multiple comparison correction |158| `cuped_adjust()` | `variance_reduction` | CUPED variance reduction |159| `confidence_sequence()` | `sequential` | Always-valid CI (peeking ok) |160| `bayesian_proportion()` | `bayesian` | Bayesian A/B (proportions) |161| `bayesian_mean()` | `bayesian` | Bayesian A/B (means) |162163## Cross-Product Handoffs164165- `/experiment power` → NOT_VIABLE → suggest `/causal select` (quasi-experimental)166- `/causal select` → "Can you randomize? YES" → suggest `/experiment design`167- `/experiment analyze` → SRM BLOCK → suggest investigating assignment logic