CtrlK
BlogDocsLog inGet started
Tessl Logo

smart-mutation-operator-generator

Generates domain-specific mutation operators beyond the standard arithmetic/relational set — mutations tailored to your codebase's idioms, APIs, and bug history that standard tools don't try. Use when generic mutation testing plateaus, when your domain has specific failure modes, or when mining bug history reveals patterns standard operators miss.

Install with Tessl CLI

npx tessl i github:santosomar/general-secure-coding-agent-skills --skill smart-mutation-operator-generator
What are skills?

90

Quality

88%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SKILL.md
Review
Evals

Smart Mutation Operator Generator

Standard mutation (+-, <<=) tests generic arithmetic. Your bugs aren't generic. If your last three bugs were "forgot to check .is_expired()," no standard operator catches that. Write one that does.

Why standard operators plateau

Standard operatorCatchesMisses
+-Arithmetic errorsAPI misuse, resource leaks, protocol errors
<<=Off-by-oneWrong method called on similar API
Remove statementUnchecked side effectsWrong order of operations on stateful API
Negate conditionUntested branchesMissing check entirely (not wrong check)

Past 80% mutation score on standard operators, the survivors are mostly equivalent mutants. The real bugs live elsewhere.

Mining mutation operators from bug history

Your git log is a mutation operator database:

git log --all --grep="fix\|bug" -p --since="2 years ago" > fix-commits.txt

For each fix diff, ask: what's the inverse? The inverse of the fix is the mutation.

Bug fixInverse = mutation operator
Added if session.is_expired(): raise ...Delete is_expired() checks
Changed json.loads(s)json.loads(s, parse_float=Decimal)Drop parse_float kwarg
Changed .get(k).get(k, default)Drop the default from dict.get
Added conn.commit() before returnDelete commit calls before return
Swapped list.pop()list.pop(0)Swap pop index (LIFO ↔ FIFO)
Added @transaction.atomicRemove @transaction.atomic decorators

Each of these is a mutation your standard tool doesn't try. Each of them represents a real past bug — if it slips in again, will tests catch it?

Domain-specific operator catalog

DomainOperatorBug it simulates
Web/HTTPSwap status codes: 200↔201, 400↔404, 401↔403Wrong status → client mishandles
Web/HTTPDrop a response headerMissing CORS/cache header
AsyncRemove await (Python) / .await (Rust)Fire-and-forget bug
AsyncSwap asyncio.gather ↔ sequential loopLost concurrency, or race introduced
DB/ORMRemove .select_for_update()Lost locking → race condition
DB/ORMSwap .filter().exclude()Inverted query
DB/ORMDrop .distinct()Duplicate rows
LockingRemove with lock: wrapperUnprotected critical section
ResourceRemove .close() / drop with blockResource leak
SerializationSwap field order in tuple unpackingMisaligned deserialization
Retry logicSet max_attempts=1Retry logic never exercised
AuthReplace check_permission(user) with TrueAuth bypass — does any test notice?

Implementing a custom operator

Most mutation tools accept custom operators. mutmut example:

# mutmut_config.py

def pre_mutation(context):
    line = context.current_source_line

    # Custom operator: remove `parse_float=Decimal` from json.loads calls
    # (Simulates bug #4521 — float precision loss in financial fields)
    if "json.loads" in line and "parse_float=Decimal" in line:
        context.mutations.append(
            line.replace(", parse_float=Decimal", "")
        )

    # Custom operator: remove `@transaction.atomic` decorator
    # (Simulates bug #3390 — partial writes on exception)
    if line.strip() == "@transaction.atomic":
        context.mutations.append("")   # delete the decorator line

    # Custom operator: swap `.get(k, default)` → `.get(k)`
    # (Simulates bug #2817 — KeyError on missing config)
    import re
    m = re.search(r"\.get\(([^,]+),\s*[^)]+\)", line)
    if m:
        context.mutations.append(
            line[:m.start()] + f".get({m.group(1)})" + line[m.end():]
        )

Each operator cites the bug it came from. When a mutant from operator X survives, you know: "the test suite wouldn't catch bug #4521 if it recurred."

Validating a new operator

Before adding an operator permanently:

  1. Does it produce compileable/runnable mutants? An operator that always makes syntax errors is useless — those get killed trivially by "the test file doesn't import."
  2. Does it produce non-equivalent mutants? Try it on a few locations. Can you imagine a test that distinguishes?
  3. Is it killable in principle? Removing a log line might be a valid operator, but if your policy is "don't test logs," every mutant survives — noise.
  4. Is it targeted? Replace any string with "" produces thousands of mutants, mostly noise. Replace auth token with "" produces a few, all meaningful.

Do not

  • Do not add operators for bugs your tests shouldn't catch. If the policy is "logging is best-effort," a "remove log call" operator generates noise.
  • Do not make operators so specific they apply once. Delete line 47 of auth.py is a test, not an operator. Operators are patterns.
  • Do not add operators without citing the bug class. Six months later you won't remember why swap pop index is in the list.
  • Do not let custom operators explode the mutant count. Mutation testing is already slow. Target: each operator applies to 10–100 sites, not 10,000.

Output format

## Bug history mined
| Bug # | Fix summary | Inverse mutation |
| ----- | ----------- | ---------------- |

## Proposed operators
### OP-<N>: <name>
Pattern: <what it matches>
Mutation: <what it changes>
Bug class: <cites bug # or CWE>
Expected sites: ~<N> in current codebase
Equivalence risk: <low | medium | high — and why>

## Operator implementation
<tool-specific config — mutmut_config.py, pitest plugin, stryker plugin>

## Dry run
| Operator | Mutants generated | Killed | Survived | Equivalent (est.) |
| -------- | ----------------- | ------ | -------- | ----------------- |

## Recommended for adoption
<subset with good kill/survive/equivalent ratio>
Repository
santosomar/general-secure-coding-agent-skills
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.