Trace → Regression Tests + Minimizer
Overview
The trace2tests module converts runtime execution traces into deterministic regression tests. It also provides a delta-debugging minimizer that shrinks failing traces to minimal reproducing sequences.
Trace Schema
Version 1, stable JSON format.
{
"version": 1,
"source_file": "path/to/app.ax",
"source_hash": "<64 hex chars>",
"cycles": [
{
"cycle": 1,
"message": { "tag": "increment", "payload": {"Int": 0} },
"state_before_hash": "<64 hex chars>",
"state_after_hash": "<64 hex chars>",
"state_after": {"Record": {"type_id": 0, "fields": [{"Int": 1}]}},
"effects": [
{ "kind": "http_request", "payload_hash": "<64 hex chars>", "callback_tag": "on_response" }
],
"ui_tree_hash": "<64 hex chars>"
}
],
"final_state_hash": "<64 hex chars>",
"trace_hash": "<64 hex chars>"
}
Fields
| Field | Type | Description |
|---|---|---|
version | u32 | Schema version (always 1) |
source_file | string | Path to source .ax file |
source_hash | string | SHA-256 of source text |
cycles | array | Ordered cycle records |
final_state_hash | string | SHA-256 of final state |
trace_hash | string | SHA-256 of canonical fingerprint |
Hashing
All hashes are written as bare lowercase hex (64 characters, no sha256: prefix), for example "bfac1732d6113f3165fb8ef4c21230def6da9bc40af020c72e7a2461a7b1c99c". They use SHA-256 of canonical JSON serialization:
- Values are serialized via serde (deterministic for BTreeMap)
- The trace fingerprint concatenates all cycle data in stable format
- Same inputs always produce identical hashes
Test Spec Format
Generated test specifications are self-contained JSON:
{
"version": 1,
"name": "counter_regression",
"source_file": "examples/counter.ax",
"source_hash": "<64 hex chars>",
"messages": [
{ "tag": "increment", "payload": {"Int": 0} },
{ "tag": "decrement", "payload": {"Int": 0} }
],
"assertions": [
{ "kind": "final_state_hash", "expected": "<64 hex chars>", "description": "..." },
{ "kind": "trace_hash", "expected": "<64 hex chars>", "description": "..." },
{ "kind": "cycle_count", "expected": "2", "description": "..." }
]
}
Assertion Kinds
| Kind | Description |
|---|---|
final_state_hash | SHA-256 of final state matches |
trace_hash | SHA-256 of full trace fingerprint matches |
cycle_count | Number of cycles matches |
Delta Debugging Minimizer
Implements the ddmin algorithm to shrink failing message sequences:
- Chunk removal: Split into n chunks, try removing each
- Granularity increase: If no chunk removal works, try finer splits
- 1-minimal pass: Try removing each individual message
- Result is guaranteed 1-minimal (removing any single message stops the failure)
Predicates
Built-in predicates:
panic: Failure = runtime error during message processing. This is the CLI default.- State mismatch: Failure = final state hash differs from expected. This one exists only in the library (
trace2tests::make_state_mismatch_predicate); the CLI has no flag for it.
External predicates: Any command that receives, as its last argument, the path of a temp JSON file ({"source_file": ..., "messages": [...]}) and returns non-zero on failure.
The CLI --predicate accepts only panic or an external command. Any value other than panic is run as a command. To minimize against a state mismatch from the CLI, wrap the check in an external command.
CLI Usage
Record
boruna trace2tests record <file.ax> --messages "tag:payload,..." --out trace.json
Generate
boruna trace2tests generate --trace trace.json --out test_spec.json [--name test_name]
Run
boruna trace2tests run --spec test_spec.json [--source app.ax]
Minimize
boruna trace2tests minimize --trace trace.json --source app.ax [--predicate panic]
boruna trace2tests minimize --trace trace.json --source app.ax --predicate "my_check.sh"
Determinism Guarantees
- Same source + same messages = identical trace hash
- Generated tests are deterministic regression gates
- Minimizer produces deterministic output (same input → same minimal trace)
- All hashes use SHA-256 with canonical serialization
Integration
- Trace files are compatible with the framework’s CycleRecord format
- Test specs can be version-controlled alongside source
- Minimized traces export as regression tests via
generate - The full pipeline: record → minimize → generate → run