llm-mutation
Mutation testing for LLM prompts. Find the gaps in your eval suite before production does.
pip install llm-mutation
mutate run --prompt prompts/customer_service.txt --eval evals/test_cs.py
The Problem
You have an eval suite. It passes. You ship. Production breaks.
Your eval suite tested 50 specific cases you wrote. It was never tested itself. llm-mutation tests whether your eval suite would notice if a key constraint was removed, a clause was dropped, or a scope was expanded.
Quickstart
from llm_mutation import MutationEngine, MutantRunner, MutationReport
# 1. Generate semantic mutations of your prompt
engine = MutationEngine()
mutations = engine.generate("prompts/customer_service.txt")
# 2. Run your eval suite against each mutant
def my_eval_fn(prompt: str, test_cases: list) -> float:
# your existing eval logic — returns 0.0-1.0
...
runner = MutantRunner(eval_fn=my_eval_fn, test_cases=my_test_cases)
results = runner.run(mutations)
# 3. See your gaps
report = MutationReport.from_results(results, prompt, original_score=0.91)
print(report.summary())
# MUTATION SCORE: 71% (5/7 mutations killed)
# SURVIVING MUTATIONS:
# ✗ DropClause — "Direct pricing questions to sales@acmecorp.com." removed
# → ADD TEST CASE: "User asks 'What does the enterprise plan cost?'"
Six Deterministic Mutation Operators
| Operator | What it does |
|---|---|
NegateConstraint |
Removes a prohibitive clause ("Never X") |
DropClause |
Removes a requirement ("Always X", "You must X") |
ScopeExpand |
Widens a scope restriction ("software only" → "products and services") |
ScopeNarrow |
Narrows a permission ("any topic" → "general topics only") |
ConditionInvert |
Removes a conditional behavior ("if A, then B") |
PhraseSwap |
Swaps a style phrase ("concise" ↔ "comprehensive") |
No LLM required for mutation generation — all operators are deterministic text transforms.
Mutation Score
| Score | Verdict | Meaning |
|---|---|---|
| >= 90% | STRONG | Eval suite is comprehensive |
| 80-89% | ADEQUATE | Good for CI gate |
| 70-79% | MARGINAL | Meaningful gaps |
| 60-69% | WEAK | Significant gaps |
| < 60% | DANGEROUS | Not fit for purpose |
Recommended minimum for production CI gate: 80%
CLI
# Run mutation test
mutate run --prompt prompts/cs.txt --eval evals/test_cs.py --output report.json
# Generate report
mutate report --input report.json --format markdown
# CI gate (exit 1 if score < 80%)
mutate ci --input report.json --min-score 0.80
# Calibrate your eval suite
mutate calibrate --prompt prompts/cs.txt --eval evals/test_cs.py
GitHub Action
- run: pip install llm-mutation
- name: Run mutation tests
run: |
mutate run --prompt prompts/cs.txt --eval evals/test_cs.py --output report.json
mutate ci --input report.json --min-score 0.80
Pattern Foundation
Built on PAT-045 — Judges 6:36-40 (The Gideon Fleece Inversion Pattern).
Gideon designed a two-condition invertible test: fleece wet/ground dry, then fleece dry/ground wet. He wasn't testing God's power — he was testing whether his testing mechanism could discriminate signal from coincidence.
llm-mutation is the bowlful of water. Your mutation score is your measurement.
Supporting: PAT-046 (Acts 17:11 — Berean Null Test) → mutate calibrate
Supporting: PAT-047 (Numbers 13:25-33 — Twelve Spies Divergence) → mutate verify-judge
License
MIT
Metadata
Release files for llm-mutation 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| llm_mutation-0.1.0.tar.gz | 21.5 kB | Without provenance | Details for llm_mutation-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| llm_mutation-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for llm_mutation-0.1.0-py3-none-any.whl |
Total release size: 40.6 kB
Release files / llm_mutation-0.1.0.tar.gz
| Download URL | llm_mutation-0.1.0.tar.gz |
|---|---|
| Size | 21.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ade1908c87e7516b9f447cc50ac585443f7b55ac62c89cac60279cb22f60d4cf
|
|
BLAKE2b-256 checksum How to use checksums |
578228e0d7a24800ff205d0f2f636e34feb4473541ca29a7906f48a8cafea2f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / llm_mutation-0.1.0-py3-none-any.whl
| Download URL | llm_mutation-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8980f551cf42e003786c0f7a6f2d50f36c6ac49b2295551d13171762affb9002
|
|
BLAKE2b-256 checksum How to use checksums |
8080792fa5acdf6889d59602e95f44492cca0bbbc29d81936b2c861b1f50f1fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Security for llm-mutation 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.