Test protection evidence schema¶
This page documents the protection payloads returned by Python and exposed by
ordeal audit --json. Values are JSON-compatible unless noted.
MutationResult.test_protection_view¶
result = ordeal.mutate("myapp.scoring.compute", preset="standard")
view = result.test_protection_view()
| Field | Type | Meaning |
|---|---|---|
status |
str |
weak, inconclusive, or protective_within_measured_scope |
protects |
bool | null |
Scoped Boolean decision; null when inconclusive |
summary |
str |
Human-readable reason for the verdict |
mutation_score |
str | null |
Exact killed/total (percent) text |
surviving_mutants |
int |
Tested mutants that escaped |
kill_attribution |
list[object] |
Killer, kill count, and operator names |
property_strength |
list[object] |
Observations and kills per property |
tautological_or_weak_properties |
list[str] |
Exercised properties with zero kills |
unexercised_properties |
list[str] |
Declared properties with zero observations |
Each kill-attribution row has test, kills, and operators. Property killers
use the prefix property:.
Each property-strength row has name, holds, total, mutants_killed,
mutants_tested, and status.
ModuleAudit.test_protection_view¶
This view combines the migrated coverage measurement with aggregated mutation validation.
| Field | Type | Meaning |
|---|---|---|
label |
str |
resulting test protection |
status |
str |
Combined verdict |
protects |
bool | null |
Scoped decision |
summary |
str |
Decisive evidence in one sentence |
mutation_score |
str | null |
Aggregated score text |
killed_mutants |
int |
Aggregated killed count |
tested_mutants |
int |
Aggregated tested count |
surviving_mutants |
int |
Aggregated survivors |
kill_attribution |
list[object] |
Weakest observed killers |
line_coverage_percent |
float | null |
Verified migrated line coverage |
coverage_gaps |
list[int] |
Exact missing executable lines |
coverage_gap_count |
int |
Missing statement count |
property_strength |
list[object] |
Rows include their mutation target |
tautological_or_weak_properties |
list[object] |
Full weak-property rows |
unexercised_properties |
list[object] |
Full unexercised-property rows |
The Python mutation view returns property names in its two convenience lists; the module audit view returns full rows because it aggregates multiple targets.
CLI JSON path¶
The envelope includes:
Each row adds module to the ModuleAudit.test_protection_view() fields. The
same module serialization also contains evidence_views.test_protection.
Decision order¶
For a mutation result:
- any survivor →
weak; - any unexercised declared property →
weak; - no tested mutants →
inconclusive; - otherwise →
protective_within_measured_scope.
For a module audit, surviving mutants win first, then unexercised properties,
coverage gaps, missing mutation evidence, and unverified coverage. Only complete
measured evidence reaches protective_within_measured_scope.
Interpretation boundaries¶
- Mutation score depends on target, preset, filters, and available operators.
- Equivalent-mutant filtering reduces noise but cannot solve equivalence in all cases.
- Coverage gaps are executable line gaps, not a complete branch-coverage model.
- Kill attribution identifies observed killers, not every redundant test.
- A scoped protective verdict is evidence, not a universal correctness proof.