"It feels good enough" is not a launch decision. This playbook has you define explicit ship/no-ship eval thresholds for your AI feature — the launch bar — and wire the eval suite into CI so no prompt or model change can merge below the bar. You own the bar; engineering owns the pipe.
Workflow area: Evals & AI Quality · Tier: Advanced · Hands-on time: ~45 minutes
Traditional features ship when the acceptance criteria pass. AI features have no binary pass: quality is a distribution, and every prompt tweak, model upgrade, or retrieval change reshuffles it. Without a numeric bar and an automated gate, launch decisions collapse into whoever tried the demo last. The launch bar turns "is it good enough?" from a meeting into a metric — and the CI gate makes the metric enforceable.
Name the quality dimensions that would block launch. Not "quality" — dimensions: factual accuracy, instruction-following, refusal correctness, tone, latency, harmful-output rate. Pick the three to five where failure genuinely blocks shipping. For each, decide the metric (pass rate on graded cases, mean judge score, p95 latency) and who signs off.
Draft the launch-bar table with AI, then argue with it. Paste this into Claude:
You are helping a PM set launch bars for an AI feature.
Feature: [ONE PARAGRAPH — what it does, who uses it, what a bad
output costs the user]
Quality dimensions we track: [LIST — e.g. factual accuracy,
refusal correctness, tone, p95 latency]
Current eval results: [PASTE — e.g. "accuracy 91% on 120 golden
cases, refusal correctness 84%, p95 4.2s"]
For each dimension produce a table row:
DIMENSION | METRIC | LAUNCH BAR (ship threshold) | REGRESSION BAR
(max allowed drop post-launch) | RATIONALE | OWNER
Rules: propose bars justified by user cost, not by our current
scores. Where our current score is below your proposed bar, say so
explicitly. Flag any dimension where a single catastrophic failure
matters more than the average — those need a zero-tolerance case
list, not a percentage.
Sample output row:
Refusal correctness | % of 40 out-of-scope probes correctly
declined | ship ≥ 95% | regression: any drop below 95% blocks
merge | a wrong answer to a medical question is a trust incident,
not a quality miss | PM: you · zero-tolerance list: cases R-01..R-08
The model will propose bars flattering to your current scores. Push back: the bar comes from the cost of failure, and if your feature is below the bar, the honest output of this exercise is "don't ship yet."
Encode the bar as promptfoo assertions. Each dimension becomes a test suite with a threshold. In promptfooconfig.yaml, your golden cases assert per-case checks, and the suite-level evaluateOptions threshold encodes the bar — e.g. the run fails if pass rate drops below 0.95 on the refusal suite. Zero-tolerance cases get individual assert blocks so one failure fails the run regardless of averages.
Hand engineering the gate spec, not the implementation. Write a half-page: which suites run on which triggers (every PR touching prompts/, nightly against the pinned model, on model-version bumps), what blocks merge versus what warns, and where results post (PR comment plus a channel). A GitHub Actions job running promptfoo eval with --fail-on-threshold is a one-day task for engineering — but the trigger matrix and block-versus-warn policy are product decisions. Make them explicitly.
Run the ritual once before trusting it. Deliberately worsen a prompt on a branch and confirm the gate blocks the PR with a readable diff of which cases regressed. Then check the failure report answers the PM question — which user-visible behavior got worse — not just "score 0.91 → 0.88." If the report can't name the regressed cases, fix the reporting before the first real incident.
Your golden eval set often contains real user inputs — treat it as production data: store it in your approved tenant, strip identifiers before cases enter the repo, and never paste customer content into consumer AI tools while drafting bars.
A launch bar you can't enforce is an opinion. Bars in a doc, thresholds in the eval config, and a CI gate on every prompt and model change — that trio is what lets you say "no-ship" once, in writing, instead of arguing it in every review.