Top-level structure
{
"schema_version": 1,
"summary": {
"status": "PASSED" | "FAILED",
"total": 10,
"passed": 9,
"failed": 1
},
"files": [...]
}
| Field |
Type |
Description |
schema_version | integer | Report schema version (currently 1) |
summary.status | string | "PASSED" or "FAILED" |
summary.total | integer | Total test count |
summary.passed | integer | Passed test count |
summary.failed | integer | Failed test count |
files | array | Array of file results |
File object
| Field |
Type |
Description |
file | string | Path to the test file |
tests | array | Array of test results |
Test object
| Field |
Type |
Description |
name | string | Test name (or "flat" for unnamed steps) |
status | string | "PASSED" or "FAILED" |
steps | array | Array of step results |
Step object
{
"name": "Create user",
"status": "PASSED" | "FAILED",
"failure_category": "assertion_failed",
"assertions": {
"failures": [{
"assertion": "status",
"expected": "201",
"actual": "400",
"message": "Expected status 201, got 400"
}]
},
"request": { "method": "POST", "url": "..." },
"response": { "status": 400, "body": {...} }
}
| Field |
Type |
Description |
name | string | Step name |
status | string | "PASSED" or "FAILED" |
failure_category | string | Category of failure (see Failure Categories) |
error_code | string | Stable machine-readable subtype for routing |
remediation_hints | array | Next-step guidance hints |
assertions.failures | array | Array of assertion failure details |
assertions.failures[].assertion | string | The assertion that failed |
assertions.failures[].expected | string | Expected value |
assertions.failures[].actual | string | Actual value |
assertions.failures[].message | string | Human-readable failure description |
request | object | Request details (included for failed executed steps) |
response | object|null | Response details (omitted when no HTTP response exists) |
When request/response are included
request is included for failed executed steps
response is included when an HTTP response was received
response is null for connection errors, DNS failures, TLS errors
- Non-JSON responses are preserved as JSON strings
JSON output modes
| Mode |
Flag |
Description |
| Verbose | --json-mode verbose | Full assertion details, all passed/failed assertions included |
| Compact | --json-mode compact | Drops passed assertion details, truncates response bodies (~200 chars) |
| LLM | --format llm | LLM-friendly grep-friendly text (auto on pipe; no ANSI when piped) |
| Agent | --agent | Compact root-cause-first AgentReport JSON for MCP/automation |
Example failed report
{
"schema_version": 1,
"summary": { "status": "FAILED", "total": 1, "passed": 0, "failed": 1 },
"files": [{
"file": "tests/users.tarn.yaml",
"tests": [{
"name": "User API",
"status": "FAILED",
"steps": [{
"name": "Create user",
"status": "FAILED",
"failure_category": "assertion_failed",
"assertions": {
"failures": [{
"assertion": "body.$.name",
"expected": "Jane Doe",
"actual": "Jane Smith",
"message": "Body assertion failed for $.name: expected 'Jane Doe', got 'Jane Smith'"
}]
},
"request": { "method": "POST", "url": "http://api.example.com/users" },
"response": { "status": 201, "body": { "name": "Jane Smith", "id": "abc123" } }
}]
}]
}]
}
How CI / agents parse the report
- Check
summary.status: "PASSED" means all tests passed
- Iterate
files[].tests[].steps[]
- Check
failure_category first (not the assertion message)
- Read
response.body to fix assertions against real payload
- Use
request.url to check for unresolved {{ ... }} interpolation