Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 2 additions & 86 deletions src/agent_code_guard/code_guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .config_validation import validate_configuration
from .file_selection import resolve_scope
from .guards import callable_size, complexity, loc, markdown_document_size, markdown_section_size, nesting
from .human_output import format_completed_analysis
from . import loc_baseline
from .result_model import GuardResult, aggregate_state, required_policies
from .skill_distribution import export_skill, skill_path as installed_skill_path
Expand Down Expand Up @@ -357,92 +358,7 @@ def _empty_markdown_facts():


def print_text(data: dict[str, object]) -> None:
scope = data["scope"]
print(
f"{str(data['overall']).upper()}: {scope['selected']} selected; {scope['analyzed']} analyzed; "
f"{scope['inapplicable']} inapplicable; {scope['excluded']} excluded."
)
loc_result = data["guards"]["loc"]
for finding in loc_result["findings"]:
if finding["nativeStatus"] == "ok" and finding.get("baselineLoc") is None:
continue
label = (
"RATCHET" if finding["nativeStatus"] == "grandfathered" else
"EXEMPT" if finding["nativeStatus"] == "exempt" else finding["state"].upper()
)
baseline_detail = ""
if finding.get("baselineLoc") is not None:
status = {
"within": "within", "exceeded": "exceeded", "notNeeded": "no longer needed",
}[finding["ratchetStatus"]]
baseline_detail = f"; baseline {finding['baselineLoc']}, {status}"
print(
f"{label}: {finding['path']} — {finding['countedLoc']} LOC "
f"(warn {finding['warnAt']}, fail {finding['failAt']}{baseline_detail})"
)
if finding["overrideIndex"] is not None:
print(f" Threshold override: {finding['overrideIndex']}")
if finding["reason"]:
print(f" Reason: {finding['reason']}")
callable_result = data["guards"].get("callableSize")
if callable_result:
for finding in callable_result["findings"]:
if finding["state"] != "review":
continue
print(
f"REVIEW: {finding['path']}:{finding['range']['startLine']}-{finding['range']['endLine']} "
f"— {finding['callable']} is {finding['measured']} LOC "
f"(review {finding['thresholds']['reviewAt']})"
)
nesting_result = data["guards"].get("nesting")
if nesting_result:
for finding in nesting_result["findings"]:
if finding["state"] != "review":
continue
deepest = finding.get("details", {}).get("deepestLine")
explanation = f"; deepest at line {deepest}" if deepest is not None else ""
print(
f"REVIEW: {finding['path']}:{finding['range']['startLine']}-{finding['range']['endLine']} "
f"— {finding['callable']} nesting depth {finding['measured']} "
f"(review {finding['thresholds']['reviewAt']}{explanation})"
)
complexity_result = data["guards"].get("complexity")
if complexity_result:
for finding in complexity_result["findings"]:
if finding["state"] != "review":
continue
print(
f"REVIEW: {finding['path']}:{finding['range']['startLine']}-{finding['range']['endLine']} "
f"— {finding['callable']} complexity {finding['measured']} "
f"(review {finding['thresholds']['reviewAt']})"
)
_print_markdown_findings(data)
policies = data["requiredPolicies"]
if policies:
print(f"Required policies: {', '.join(policies)}")
print("Required action: inspect each actionable finding using its policy guidance.")


def _print_markdown_findings(data: dict[str, object]) -> None:
markdown_document_result = data["guards"].get("markdownDocumentSize")
if markdown_document_result:
for finding in markdown_document_result["findings"]:
if finding["state"] != "review":
continue
print(
f"REVIEW: {finding['path']} — Markdown document is {finding['measured']} lines "
f"(review {finding['thresholds']['reviewAt']})"
)
markdown_section_result = data["guards"].get("markdownSectionSize")
if markdown_section_result:
for finding in markdown_section_result["findings"]:
if finding["state"] != "review":
continue
print(
f"REVIEW: {finding['path']}:{finding['range']['startLine']}-{finding['range']['endLine']} "
f"— section {json.dumps(finding['heading'], ensure_ascii=False)} is {finding['measured']} lines "
f"(review {finding['thresholds']['reviewAt']})"
)
print(format_completed_analysis(data))


def exit_code(overall: str, ci: bool) -> int:
Expand Down
122 changes: 122 additions & 0 deletions src/agent_code_guard/human_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"""Human presentation for completed normal-analysis payloads."""

from __future__ import annotations

import json


def _loc_lines(data: dict[str, object]) -> list[str]:
lines = []
loc_result = data["guards"]["loc"]
for finding in loc_result["findings"]:
if finding["nativeStatus"] == "ok" and finding.get("baselineLoc") is None:
continue
label = (
"RATCHET" if finding["nativeStatus"] == "grandfathered" else
"EXEMPT" if finding["nativeStatus"] == "exempt" else finding["state"].upper()
)
baseline_detail = ""
if finding.get("baselineLoc") is not None:
status = {
"within": "within", "exceeded": "exceeded", "notNeeded": "no longer needed",
}[finding["ratchetStatus"]]
baseline_detail = f"; baseline {finding['baselineLoc']}, {status}"
lines.append(
f"{label}: {finding['path']} — {finding['countedLoc']} LOC "
f"(warn {finding['warnAt']}, fail {finding['failAt']}{baseline_detail})"
)
if finding["overrideIndex"] is not None:
lines.append(f" Threshold override: {finding['overrideIndex']}")
if finding["reason"]:
lines.append(f" Reason: {finding['reason']}")
return lines


def _callable_size_lines(data: dict[str, object]) -> list[str]:
lines = []
result = data["guards"].get("callableSize")
if result:
for finding in result["findings"]:
if finding["state"] != "review":
continue
lines.append(
f"REVIEW: {finding['path']}:{finding['range']['startLine']}-{finding['range']['endLine']} "
f"— {finding['callable']} is {finding['measured']} LOC "
f"(review {finding['thresholds']['reviewAt']})"
)
return lines


def _nesting_lines(data: dict[str, object]) -> list[str]:
lines = []
result = data["guards"].get("nesting")
if result:
for finding in result["findings"]:
if finding["state"] != "review":
continue
deepest = finding.get("details", {}).get("deepestLine")
explanation = f"; deepest at line {deepest}" if deepest is not None else ""
lines.append(
f"REVIEW: {finding['path']}:{finding['range']['startLine']}-{finding['range']['endLine']} "
f"— {finding['callable']} nesting depth {finding['measured']} "
f"(review {finding['thresholds']['reviewAt']}{explanation})"
)
return lines


def _complexity_lines(data: dict[str, object]) -> list[str]:
lines = []
result = data["guards"].get("complexity")
if result:
for finding in result["findings"]:
if finding["state"] != "review":
continue
lines.append(
f"REVIEW: {finding['path']}:{finding['range']['startLine']}-{finding['range']['endLine']} "
f"— {finding['callable']} complexity {finding['measured']} "
f"(review {finding['thresholds']['reviewAt']})"
)
return lines


def _markdown_lines(data: dict[str, object]) -> list[str]:
lines = []
document_result = data["guards"].get("markdownDocumentSize")
if document_result:
for finding in document_result["findings"]:
if finding["state"] != "review":
continue
lines.append(
f"REVIEW: {finding['path']} — Markdown document is {finding['measured']} lines "
f"(review {finding['thresholds']['reviewAt']})"
)
section_result = data["guards"].get("markdownSectionSize")
if section_result:
for finding in section_result["findings"]:
if finding["state"] != "review":
continue
lines.append(
f"REVIEW: {finding['path']}:{finding['range']['startLine']}-{finding['range']['endLine']} "
f"— section {json.dumps(finding['heading'], ensure_ascii=False)} is {finding['measured']} lines "
f"(review {finding['thresholds']['reviewAt']})"
)
return lines


def format_completed_analysis(data: dict[str, object]) -> str:
"""Return the complete human report for an existing completed payload."""
scope = data["scope"]
lines = [
f"{str(data['overall']).upper()}: {scope['selected']} selected; {scope['analyzed']} analyzed; "
f"{scope['inapplicable']} inapplicable; {scope['excluded']} excluded."
]
lines.extend(_loc_lines(data))
lines.extend(_callable_size_lines(data))
lines.extend(_nesting_lines(data))
lines.extend(_complexity_lines(data))
lines.extend(_markdown_lines(data))
policies = data["requiredPolicies"]
if policies:
lines.append(f"Required policies: {', '.join(policies)}")
lines.append("Required action: inspect each actionable finding using its policy guidance.")
return "\n".join(lines)
50 changes: 50 additions & 0 deletions tests/test_human_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from __future__ import annotations

import json
import tempfile
from pathlib import Path

from helpers import CodeGuardTestCase


class CompletedAnalysisOutputTests(CodeGuardTestCase):
def test_formats_one_complete_mixed_report_exactly(self) -> None:
with tempfile.TemporaryDirectory() as temp:
root = Path(temp)
(root / "sample.py").write_text(
"def sample(value):\n if value:\n if value > 1:\n"
" return value\n return 0\n",
encoding="utf-8",
)
(root / "guide.md").write_text('# Hé said `"hello`"\nbody\nbody\n', encoding="utf-8")
config = root / "code-guard.config.json"
config.write_text(json.dumps({"version": 1, "guards": {
"loc": {"warnAt": 1, "failAt": 99},
"callableSize": {"reviewAt": 3},
"nesting": {"reviewAt": 1},
"cyclomaticComplexity": {"reviewAt": 1},
"markdownDocumentSize": {"reviewAt": 2},
"markdownSectionSize": {"reviewAt": 2},
}}), encoding="utf-8")

result = self.run_guard(root, ".", "--config", str(config))

self.assertEqual(result.returncode, 1)
self.assertEqual(result.stderr, "")
self.assertEqual(result.stdout, "\n".join([
"REVIEW: 3 selected; 2 analyzed; 1 inapplicable; 0 excluded.",
"REVIEW: sample.py — 5 LOC (warn 1, fail 99)",
"REVIEW: sample.py:1-5 — sample.sample is 5 LOC (review 3)",
"REVIEW: sample.py:1-5 — sample.sample nesting depth 2 (review 1; deepest at line 3)",
"REVIEW: sample.py:1-5 — sample.sample complexity 3 (review 1)",
"REVIEW: guide.md — Markdown document is 3 lines (review 2)",
'REVIEW: guide.md:1-3 — section "Hé said `\\"hello`\\"" is 3 lines (review 2)',
"Required policies: callableSize, complexity, loc, markdownDocumentSize, markdownSectionSize, nesting",
"Required action: inspect each actionable finding using its policy guidance.",
"",
]))


if __name__ == "__main__":
import unittest
unittest.main()
Loading