Skip to content
Back to skills

Analytics Experiment Readout

ASecurity

Read out a finished A/B test — sample ratio check first, then whether it ran as planned, the primary metric's effect and interval, guardrails, and a ship, don't ship, inconclusive or invalid call. Use when a test has finished and the user asks whether the change won and can ship. Not for designing a test; see /marketing-ab-test-setup.

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
ai-agentspythonrustgobashrails

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned November 7, 2026

npx -y skills add bromso/singularskills --skill analytics-experiment-readout --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Analytics Experiment Readout?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Analytics Experiment Readout
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bromso-analytics-experiment-readout/badge)](https://www.skillsdirectory.com/skills/bromso-analytics-experiment-readout)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: analytics-experiment-readout
description: Read out a finished A/B test — sample ratio check first, then whether it ran as planned, the primary metric's effect and interval, guardrails, and a ship, don't ship, inconclusive or invalid call. Use when a test has finished and the user asks whether the change won and can ship. Not for designing a test; see /marketing-ab-test-setup.
metadata:
  argument-hint: "<results file> [project]"
---

# Experiment readout

Read out the finished test in "$ARGUMENTS" and make a call that can be trusted. The checks run in a fixed order, and a failure early in the order overrides everything after it: a significant p-value means nothing if the test is broken.

**Compute with code.** Perform every calculation (totals, balances, ratios, variances, projections) with a script — Bash, Python or a spreadsheet formula written to a file — and include the computation alongside the result. Never do arithmetic mentally.

## Prerequisites

The results: a file path or a pasted table with, per arm, the users assigned and the outcome (conversions, or a mean and spread). When `$ARGUMENTS` or the request names a project, use that name as `<project>` whether or not its folder exists yet in `.singularskills/analytics/` (create it when you write). With no project named: with exactly one folder there, use it; with several, ask which; with no folder at all, ask for a project name.

Read the test plan from the `## A/B Test:` section of `.singularskills/marketing/<project>/03-convert.md` when it exists: the planned split, primary metric, guardrails, planned sample size per arm and duration. Without a plan, ask once for those; with no answer, the planned split is unknown: say so, treat the sample size and duration as unknown, and never call the test invalid on an assumed split. If the file has more than one `## A/B Test:` section, use the one whose name matches the test in the request or the results file; with several and no match, ask which.

Append this line to `.singularskills/log.jsonl` before you write the readout (create the folder and file if missing): `{"ts":"<ISO timestamp>","skill":"analytics-experiment-readout","workflow":"analytics","phase":null,"project":"<project>","event":"started","artifact":"experiments/<date>-<slug>.md","note":""}`, where `<date>` is today as `YYYY-MM-DD` and `<slug>` is two to four words naming the test, never a person.

## Process

1. **Check the sample ratio first.** Compare the users in each arm with the **planned split** from the plan (not an assumed 50/50 when the plan says otherwise), using a chi-square goodness-of-fit test computed with a script, as `references/experiment-readout.md` shows. At p < 0.001 there is a sample ratio mismatch: the assignment or the logging is broken, the result cannot be trusted until the cause is found, and the call is **invalid** whatever the primary metric shows. List the usual causes to check: users dropped by a redirect or a crash in one arm, bots, a logging change mid-test, mis-bucketing.

   **When the planned split is unknown** (no plan and no answer), test the counts against 50/50 and against the nearest conventional split they fit (90/10, 80/20, 2:1). If they fit neither, or fit a split other than 50/50, the call is **inconclusive: planned split unknown**, naming the split the counts fit and asking for the plan; a deviation from an assumed split is never **invalid**.

   **Without a way to run code**, state no test statistic or p-value. Show the observed users per arm and their shares against the planned split, label the check `not computed`, and if the shares are plainly off the plan (several points away on thousands of users), the call is **inconclusive: suspected sample ratio mismatch** until the check is computed. Do not go on to call a winner.

2. **Check the test ran as planned:** the planned sample per arm and duration were reached, and nobody stopped it early because it looked significant. An unplanned early stop, or a test short of its planned sample or duration, makes the call **inconclusive** unless the plan used a sequential method.

3. **Compute the primary metric's effect:** absolute and relative difference with a 95% confidence interval, the sample per arm and the p-value (two-proportion z-test for a conversion metric; Welch's t-test or a bootstrap for a mean), with a script written to `.singularskills/analytics/<project>/` and included beside the result. Scripts read the user's files where they keep them and write only aggregates (counts, sums, rates and intervals): no row-level data, names, emails or raw IDs go into any file under `.singularskills/`. Without a way to run code, report the raw rates per arm as `not computed` and make no significance claim.

4. **Check the guardrails** the plan names, each with its change and interval. A significantly worse guardrail means **don't ship**, and blocks shipping even when the call is **inconclusive** for another reason: say so beside the call.

5. **Weigh the base rate:** most tests do not move their primary metric, so a surprising or very large effect needs a replication run before launch; say so when it applies.

6. **Make the call** from this table, top row first:

   | Situation | Call |
   | --- | --- |
   | Sample ratio mismatch computed at p < 0.001 | **invalid** |
   | Shares plainly off the planned split, check not computed | **inconclusive: suspected sample ratio mismatch** |
   | No plan, and the counts do not fit 50/50 | **inconclusive: planned split unknown** |
   | Unplanned early stop, or planned sample or duration not reached | **inconclusive** |
   | A guardrail significantly worse | **don't ship** |
   | Primary metric's interval entirely above zero, guardrails fine | **ship** (replicate first if surprising) |
   | Primary metric's interval entirely below zero | **don't ship** |
   | Interval spans zero | **inconclusive**, with the effect sizes it rules out |

7. **Write the readout** to `.singularskills/analytics/<project>/experiments/<date>-<slug>.md` with sections **Plan** (as read, or assumed), **Sample ratio**, **Ran as planned**, **Primary metric**, **Guardrails**, **Call** and **Next step**.

## Output

The readout written to `.singularskills/analytics/<project>/experiments/<date>-<slug>.md`. Present the call first, then the check that decided it, then the primary metric's effect with its interval or `not computed`.

After you have written the readout, append the `started` line of Prerequisites to `.singularskills/log.jsonl` with `"event":"finished"`: `{"ts":"<ISO timestamp>","skill":"analytics-experiment-readout","workflow":"analytics","phase":null,"project":"<project>","event":"finished","artifact":"experiments/<date>-<slug>.md","note":""}`.

The readout opens with this frontmatter (`agent` is the agent you run in, or `unknown`; this utility has no gate, so `phase` is `null` and `gate` is `none`):

```yaml
---
skill: analytics-experiment-readout
workflow: analytics
phase: null
project: <project>
started: <ISO timestamp>
finished: <ISO timestamp>
agent: <the agent you run in, or "unknown">
gate: none
---
```

The readout ends with `## Decisions` and `## Open questions`, in this shape:

```markdown
## Decisions
- <what was chosen> — <why> — <what was rejected>

## Open questions
- <what the next phase or a reviewer must settle>
```

Files in this skill

  • SKILL.md7.2 KB
  • references/experiment-readout.md4.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.