Interpret Results
AuditResult Object
Every audit returns an AuditResult with these properties:
| Property | Type | Description |
|---|---|---|
project_path |
str \| None |
Path of the audited project |
checks |
list[CheckResult] |
Individual check results |
success |
bool |
True if all checks passed |
total |
int |
Total number of checks |
failed |
int |
Number of failed checks |
quality_score |
float \| None |
Composite score 0–100 (10-category weighted). None when auditing a single category with --category |
grade |
str \| None |
Letter grade A–F. None when quality_score is None |
CheckResult Object
Each individual check returns:
| Property | Type | Description |
|---|---|---|
rule_id |
str |
Unique identifier (QUALITY_LINT, DEPS_AUDIT, etc.) |
passed |
bool |
Whether the check passed |
message |
str |
Human-readable description |
severity |
Severity |
error, warning, or info |
details |
dict \| None |
Tool-specific structured data (counts, lists) |
text |
str \| None |
Pre-rendered detail text for display (bullet lines) |
fix_hint |
str \| None |
Suggested fix |
score |
int \| None |
Numeric score in [0, 100] for scored categories |
Formatters
Human-Readable Report
JSON Output
from axm_audit.formatters import format_json
import json
data = format_json(result)
print(json.dumps(data, indent=2))
Agent Output
format_agent minimizes tokens for AI agent consumption. Passed checks are compact strings — unless they carry actionable detail (e.g. missing docstrings, complexity top offenders), in which case they become dicts. For failed checks, text and details are mutually exclusive — text takes priority when truthy, otherwise details is included:
For a compact text representation optimised for token count, pass the
agent dict through format_agent_text:
from axm_audit.formatters import format_agent_text
text = format_agent_text(data, category="lint")
print(text)
# audit lint | B 85 | 3 pass · 1 fail
# ✓ QUALITY_LINT QUALITY_TYPES QUALITY_SECURITY
# ✗ QUALITY_COMPLEXITY 3 functions exceed CC threshold
# src/mod.py:10 func_a CC=15
# fix: Extract helpers to reduce CC
Example agent dict structure:
{
"score": 85.0,
"grade": "B",
"passed": [
"QUALITY_LINT: Lint score: 100/100 (0 issues)",
{
"rule_id": "PRACTICE_DOCSTRING",
"message": "Docstring coverage: 95% (19/20)",
"details": {"coverage": 0.95, "missing": ["module.py:func"]},
"fix_hint": "Add docstrings to public functions"
}
],
"failed": [
{
"rule_id": "QUALITY_TYPE",
"message": "Type score: 70/100 (6 errors)",
"text": "\u2022 mod.py:10: Incompatible types in assignment",
"fix_hint": "Run: mypy src/"
}
]
}
Test Report Text
format_audit_test_text renders a TestReport as compact text for LLM consumption (~27 tokens green, ~240 tokens with failures):
from axm_audit.tools.audit_test_text import format_audit_test_text
from axm_audit.core.test_runner import TestReport
text = format_audit_test_text(report)
print(text)
# audit_test | ✅ 42 passed | 1.2s | cov 95.0%
The output includes:
| Section | When shown | Format |
|---|---|---|
| Header | Always | audit_test \| {icon} {counts} \| {duration}s [\| cov {pct}%] |
| Failure blocks | failures is non-empty |
✗ {test} ({file}:{line}) + error + traceback |
| Coverage | Files below 95% exist | cov< {basename} {pct}% |
When coverage is None (targeted/files runs), the coverage section is omitted entirely.
Scoring
The quality_score is computed from 8 weighted categories:
| Category | Weight |
|---|---|
| Linting (Ruff) | 20% |
| Type Safety (mypy) | 15% |
| Complexity (radon) | 15% |
| Security (Bandit) | 10% |
| Dependencies (pip-audit + deptry) | 10% |
| Testing (pytest-cov) | 15% |
| Architecture (AST analysis) | 10% |
| Practices (AST analysis) | 5% |
For details, see Scoring & Grades.
Severity Levels
| Severity | Effect | Example |
|---|---|---|
error |
Blocks audit pass | Missing pyproject.toml |
warning |
Non-blocking | High complexity function |
info |
Informational only | Docstring coverage stats |