CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/mutant-survival-triage

Normalizes a surviving-mutant record across StrykerJS, PIT, mutmut, and Mull into one shape, classifies why it survived (missing case, weak assertion, equivalent mutant, unreachable code, flaky killer), applies per-mutator heuristics for conditional-boundary, arithmetic-operator, statement-removal, and constant mutations, and drafts the specific test that would kill it. Treats equivalence as a judgment call, because deciding whether a mutant is equivalent to the original is undecidable in general, so a residual survivor rate is expected rather than a defect. Use when a mutation run has finished and the report lists surviving mutants that nobody has yet explained or turned into concrete test cases.

75

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

tool-normalization.mdreferences/

Tool normalization reference

Per-tool field mapping, status vocabularies, and operator-name-to-family tables for mutant-survival-triage. Linked inline from that skill's SKILL.md. Flatten each survivor into the SurvivedMutant record (see SKILL.md Step 1), then use these tables to fill the fields (Step 1) and match the mutator family (Step 3).

Where each field comes from

FieldStrykerJSPITmutmutMull
mutatormutatorName in the JSON reportmutator name from the mutator set, for example CONDITIONALS_BOUNDARYoperator implied by the diff shown in mutmut browseoperator id in brackets, for example [cxx_ge_to_gt]
file / linelocation (start and end line and column)source file and line number in the HTML or XML reportthe mutated function in the mutants/ directorypath:line:column prefix on the survivor line
mutatedreplacementrendered on the report linediff shown in mutmut browsetext after Survived: on the survivor line
coveredBycoveredBy (and killedBy when killed)the covering tests PIT ran for that linethe tests mutmut selected for that functionnot reported per mutant

StrykerJS field names above are the properties the mutation testing report schema defines for a mutant result: id, mutatorName, replacement, description, location, status, statusReason, testsCompleted, static, coveredBy, killedBy, duration (report schema JSON). Mull's console format is exactly /tmp/sc-tTV8a84lL/main.cpp:2:11: warning: Survived: Replaced >= with > [cxx_ge_to_gt] under a [info] Survived mutants (1/4): heading (Mull hello-world tutorial). mutmut's documented workflow is mutmut run then mutmut browse, with mutants kept "in the mutants/ directory" and written back with mutmut apply <mutant> (mutmut docs); it publishes no machine-readable report format, so the mutmut record is filled in from the browse UI rather than parsed.

Do not merge the status vocabularies

"Survived" is not the only non-killed outcome, and the neighbouring statuses change the classification in Step 2. Keep the tool's own status word:

ToolStatuses that are not "killed"
StrykerJSSurvived, NoCoverage, Timeout, RuntimeError, CompileError, Ignored, Pending (mutant states)
PITsurvived, no coverage, timed out, non viable, memory error, run error (PIT basic concepts)
mutmutsurvived, plus timeout and suspicious outcomes surfaced in mutmut browse (mutmut docs)
Mullsurvived, listed under [info] Survived mutants (n/total): (Mull tutorial)

Two of these decide a class on their own. StrykerJS defines NoCoverage as "the mutant isn't covered by one of your tests and survived as a result" (mutant states), and PIT states "No coverage is the same as Survived except there were no tests that exercised the line of code where the mutation was created" (PIT basic concepts). A no-coverage mutant is never a weak-assertion finding: no assertion ran.

Per-mutator operator names by tool

Match on the family, not the string:

FamilyStrykerJSPITmutmutMull
Conditional boundaryGreaterThanBoundary (a > b to a >= b), LessThanBoundary (a < b to a <= b) under the Equality Operator mutatorCONDITIONALS_BOUNDARY, a default mutator that "replaces the relational operators <, <=, >, >= with their boundary counterpart"documented example: "< is changed to <="cxx_lt_to_le, cxx_ge_to_gt, group cxx_boundary
Arithmetic operatorArithmetic Operator: AdditionNegation (a + b to a - b), MultiplicationNegation (a * b to a / b)MATH, a default mutator that replaces binary arithmetic operationsnot documented as a named operatorcxx_add_to_sub, cxx_sub_to_add, cxx_mul_to_div, group cxx_arithmetic
Statement or call removalBlock Statement: BlockRemoval "removes the content of every block statement"VOID_METHOD_CALLS, a default mutator that removes calls to void methodsnot documented as a named operatorcxx_remove_void_call, group cxx_calls
Constant or literalString Literal ("foo" to ""), Boolean Literal (true to false)EMPTY_RETURNS, FALSE_RETURNS, TRUE_RETURNS, NULL_RETURNS, PRIMITIVE_RETURNS (defaults); INLINE_CONSTS (optional)documented example: "Integer literals are changed by adding 1. So 0 becomes 1, 5 becomes 6"cxx_assign_const, cxx_init_const, cxx_replace_scalar_call

Sources for that table: StrykerJS operator names and replacements from supported mutators; PIT operator names, quoted definitions, and default-set membership from PIT mutation operators; mutmut's documented example mutations from mutmut docs, which point at node_mutation.py for the complete list rather than enumerating it; Mull operator identifiers and groups from Mull supported mutations. mutmut is left blank in two rows on purpose: its public docs do not name those operators, so do not assert them.

SKILL.md

tile.json