A domain-agnostic mutation framework for structured artifacts.
Miova is a Python framework for creating, executing, validating, composing and reporting mutations over structured artifacts.
It provides a domain-agnostic runtime for controlled transformations, with explicit contracts, invariant validation, immutable lineage tracking, mutation pipelines, exploration campaigns and payload-level reporting.
Miova is designed for use cases such as:
- mutation testing
- property-based testing
- intelligent fuzzing
- structured artifact exploration
- formal-methods-oriented validation
- DSL and IR robustness testing
- transformation analysis
GitHub topics:
python · framework · mutation-testing · property-based-testing · fuzzing · formal-methods · software-testing · invariants · developer-tools
Miova is currently released as v0.1.0 / V1 preview.
This means the framework is usable as a Python library and its core runtime is validated by automated tests, documentation builds, packaging checks and GitHub Actions.
The public API is intentionally structured and tested, but may still evolve before a formal 1.0.0 release.
Current guarantees:
- installable as a Python package
- importable from external projects
- covered by P0/P1/P2 test suites
- validated by GitHub Actions
- executable examples
- MkDocs documentation build
- payload-level mutation reporting
- multi-domain runtime support
Versioning intent:
0.1.0 — first usable V1 preview runtime
1.0.0 — stable public API release
Modern systems manipulate increasingly complex structured artifacts:
- source code
- DSL instances
- intermediate representations
- graphs
- documents
- YAML / JSON configurations
- machine learning model descriptions
- structured datasets
Testing and exploring these artifacts often requires transformation logic tightly coupled to each domain.
Miova introduces a generic mutation architecture based on a few core concepts:
- Artifact — the universal unit manipulated by the framework
- Adapter — the bridge between Miova and a domain-specific representation
- Mutation — an executable transformation operator
- Mutation Contract — the semantic description of a mutation
- Invariant — a rule defining what must remain valid
- Pipeline — a sequence of mutations
- Campaign — automated exploration through generated pipelines
- Reporting — human-readable payload-level change reports
The goal is to separate:
- domain representation
- transformation logic
- validation rules
- execution orchestration
- reporting and observability
flowchart LR
A[Artifact]
--> B[Adapter]
B
--> C[Domain Object]
C
--> D[Mutation]
D
--> E[Mutated Domain Object]
E
--> F[Adapter]
F
--> G[New Artifact]
G
--> H[Invariant Engine]
H
--> I[Mutation Result]
I
--> J[Payload Report]
Miova does not assume a specific artifact type.
The same runtime can operate on different domains as long as each domain provides an adapter.
An Artifact is the universal immutable unit manipulated by Miova.
It contains:
kind— domain identifierpayload— domain-specific contentid— generated artifact identitymetadata— additional informationlineage— transformation ancestry
Example:
from miova import Artifact
artifact = Artifact(
kind="yaml",
payload={
"site_name": "Miova",
"theme": {
"name": "material",
},
},
)Miova treats the payload as opaque. Domain-specific interpretation belongs to adapters.
An adapter bridges Miova artifacts and domain objects.
The execution flow is:
Artifact
|
v
Adapter.extract()
|
v
Domain Object
|
v
Mutation
|
v
Domain Object
|
v
Adapter.build()
|
v
Artifact
Adapters allow Miova to remain domain-agnostic.
A mutation is a small executable transformation.
It receives a domain object and a runtime context, then returns a new domain object.
A mutation does not manage:
- artifact identity
- lineage
- validation
- reporting
- adapter resolution
Those responsibilities belong to the framework runtime.
A mutation contract describes the semantic purpose of a mutation.
It defines:
- intent
- expected outcome
- applicability
- rationale
Example:
from miova import MutationContract
contract = MutationContract(
intent="Add a summary section",
expected_outcome="The document contains a Summary section",
applicability=lambda artifact, context: artifact.kind == "document",
rationale="Used to explore valid document variants",
)Contracts describe why a mutation exists and when it may run.
Invariants define properties that must remain valid.
Miova supports two kinds of invariants.
State invariants validate a single artifact.
Examples:
- document has a title
- YAML payload is a mapping
- graph has at least one node
- DSL property is syntactically valid
Transition invariants validate a transformation.
Examples:
- artifact kind is preserved
- required metadata is preserved
- a mutation only changes the expected field
- a transformation preserves semantic consistency
A MutationPipeline executes a sequence of mutation definitions.
Artifact
|
v
Mutation A
|
v
Artifact A'
|
v
Mutation B
|
v
Artifact B'
|
v
Final Artifact
The pipeline stops as soon as a mutation returns a non-success status.
A campaign runs multiple generated pipelines over the same initial artifact.
Initial Artifact
|
+-- Generated Pipeline 1
|
+-- Generated Pipeline 2
|
+-- Generated Pipeline 3
|
+-- Campaign Result
Campaigns are useful for:
- automated exploration
- mutation-based testing
- property-based testing
- fuzzing-like workflows
- robustness analysis
Miova includes generic payload-level reporting.
Instead of only displaying artifact objects before and after a mutation, Miova can report what changed inside the payload.
Example output:
Mutation: yaml_add_version
Status: SUCCESS
Payload changes:
+ version:
'0.1.0'
Pipeline and campaign reports can also display step-by-step mutation changes.
A mutation execution follows this lifecycle:
sequenceDiagram
participant User
participant Engine
participant Contract
participant InvariantEngine
participant Adapter
participant Mutation
participant Reporter
User->>Engine: apply(artifact, mutation definition)
Engine->>Contract: check applicability
Contract-->>Engine: applicable
Engine->>InvariantEngine: validate initial state
InvariantEngine-->>Engine: valid
Engine->>Adapter: extract domain object
Adapter-->>Engine: domain object
Engine->>Mutation: execute mutation
Mutation-->>Engine: mutated domain object
Engine->>Adapter: build new artifact
Adapter-->>Engine: new artifact
Engine->>InvariantEngine: validate generated artifact and transition
InvariantEngine-->>Engine: valid
Engine-->>User: MutationResult
User->>Reporter: render result
Reporter-->>User: payload-level report
Possible mutation statuses:
SUCCESSSKIPPEDREJECTEDFAILED
A complete Miova runtime usually contains:
- an artifact
- an adapter
- one or more mutations
- contracts
- invariants
- a context
- an engine
- optional reporting
Conceptual usage:
from miova import Artifact, MiovaEngine
from miova.reporting import print_mutation_result
artifact = Artifact(
kind="example",
payload={
"name": "Miova",
},
)
context = create_context_with_adapters_mutations_and_invariants()
definition = context.mutation_registry.get(
"example_mutation"
)
engine = MiovaEngine()
result = engine.apply(
artifact=artifact,
definition=definition,
context=context,
)
print_mutation_result(
result,
context,
)For complete executable examples, see:
python -m examples.document.run_engine
python -m examples.document.run_pipeline
python -m examples.document.run_campaign
python -m examples.yaml.run_engine
python -m examples.yaml.run_pipeline
python -m examples.yaml.run_campaignMiova supports declarative registration through decorators.
from miova import (
MutationContract,
MutationNature,
MutationStrategy,
PreservationLevel,
PreservationProfile,
mutation,
)
contract = MutationContract(
intent="Add a summary section",
expected_outcome="The document contains a Summary section",
applicability=lambda artifact, context: artifact.kind == "document",
rationale="Used to explore valid document variants",
)
preservation = PreservationProfile(
structure=PreservationLevel.PARTIAL,
behavior=PreservationLevel.FULL,
semantics=PreservationLevel.FULL,
information=PreservationLevel.FULL,
)
@mutation(
name="add_summary_section",
nature=MutationNature.INSERTION,
strategy=MutationStrategy.PRESERVING,
contract=contract,
preservation=preservation,
severity=0.2,
)
def add_summary_section(document, context):
return document.with_section("Summary")The mutation is registered when the module is imported.
This enables a simple user workflow:
declare mutations
declare invariants
register adapter
create context
run engine / pipeline / campaign
render report
For local development:
python -m pip install -e ".[dev]"Run the test suite:
python -m pytestBuild the documentation:
mkdocs build --strictCheck package import:
python -c "from miova import Artifact, MiovaEngine"The documentation is available in the /docs directory and can be served locally with:
mkdocs serveThe documentation covers:
- architecture
- core concepts
- adapters
- registries
- reporting
- examples
- ADRs
- roadmap
Miova currently includes example domains:
Demonstrates:
- dataclass payloads
- document adapter
- declarative mutations
- state invariants
- transition invariants
- engine execution
- pipeline execution
- campaign execution
- payload-level reporting
Run:
python -m examples.document.run_engine
python -m examples.document.run_pipeline
python -m examples.document.run_campaignDemonstrates:
- YAML-like structured payloads
- nested dictionary/list mutation
- reportable adapter hook
- payload diff reporting
- pipeline and campaign reporting
Run:
python -m examples.yaml.run_engine
python -m examples.yaml.run_pipeline
python -m examples.yaml.run_campaignMiova is built around the following principles.
The framework does not assume a specific artifact type.
Domain logic belongs to adapters.
Mutations are described through contracts.
The framework can reason about intent, applicability and expected outcomes.
Transformations are checked through state and transition invariants.
Invalid transformations are rejected.
Mutations create new artifacts instead of modifying existing ones.
Each artifact keeps track of its ancestry.
Mutation, pipeline and campaign results can be rendered as human-readable reports showing payload-level changes.
Small mutations can be composed into pipelines.
Pipelines can be generated and executed as campaigns.
Miova is covered by three levels of tests.
Core framework behavior:
- artifact model
- engine statuses
- pipeline execution
- registries
- decorators
- invariants
- reporting
- examples
- regression tests
Framework integration quality:
- public imports
- multi-domain runtime
- mutation filtering
- mutation selection
- pipeline generation
- documentation build
- no domain leakage
Robustness:
- property-based tests
- serializer and differ properties
- engine result properties
- reporting smoke tests
- campaign reporting limits
Run all tests:
python -m pytestPossible future directions:
- richer mutation generation strategies
- weighted mutation selection
- optimization-driven exploration
- distributed mutation campaigns
- advanced campaign analytics
- additional domain adapters
- FORML adapter
- Python AST adapter
- graph adapter
- JSON adapter
- ML model configuration adapter
Miova is licensed under the Apache License 2.0.
See the LICENSE file for details.