mirror of
https://github.com/usestrix/strix.git
synced 2026-10-19 04:53:46 +00:00
Merge 42264b219e into 956a26715b
This commit is contained in:
commit
bb8239d53f
2 changed files with 88 additions and 15 deletions
|
|
@ -806,22 +806,27 @@ class ReportState:
|
|||
self.save_run_data(status=status)
|
||||
|
||||
def _format_final_scan_result(self, scan_results: dict[str, Any]) -> str:
|
||||
return f"""# Executive Summary
|
||||
def section(heading: str, content: object) -> str:
|
||||
# The agent is asked for section prose and often prepends the very
|
||||
# heading this template already emits (e.g. "# Executive Summary"),
|
||||
# which doubled every H1 in penetration_test_report.md. Strip a
|
||||
# leading heading line from the content when it duplicates the
|
||||
# template heading. Case-insensitive; only the FIRST line is
|
||||
# examined, so a repeated heading later in the body is untouched.
|
||||
text = str(content or "").strip()
|
||||
first_line, _, rest = text.partition("\n")
|
||||
if first_line.strip().lstrip("#").strip().lower() == heading.lstrip("#").strip().lower() and first_line.lstrip().startswith("#"):
|
||||
text = rest.strip()
|
||||
return f"{heading}\n\n{text}"
|
||||
|
||||
{str(scan_results.get("executive_summary", "")).strip()}
|
||||
|
||||
# Methodology
|
||||
|
||||
{str(scan_results.get("methodology", "")).strip()}
|
||||
|
||||
# Technical Analysis
|
||||
|
||||
{str(scan_results.get("technical_analysis", "")).strip()}
|
||||
|
||||
# Recommendations
|
||||
|
||||
{str(scan_results.get("recommendations", "")).strip()}
|
||||
"""
|
||||
return "\n\n".join(
|
||||
[
|
||||
section("# Executive Summary", scan_results.get("executive_summary", "")),
|
||||
section("# Methodology", scan_results.get("methodology", "")),
|
||||
section("# Technical Analysis", scan_results.get("technical_analysis", "")),
|
||||
section("# Recommendations", scan_results.get("recommendations", "")),
|
||||
]
|
||||
) + "\n"
|
||||
|
||||
def _coverage_document(self) -> dict[str, Any] | None:
|
||||
"""Assemble the coverage record, or None when it can't be built.
|
||||
|
|
|
|||
|
|
@ -265,3 +265,71 @@ def test_render_vulnerability_md_surfaces_calibration_metadata() -> None:
|
|||
assert "## Confidence Rationale" in md
|
||||
assert "## What Would Change This Severity" in md
|
||||
assert "## Fix Verification" in md
|
||||
|
||||
|
||||
def test_format_final_scan_result_strips_duplicated_section_headings() -> None:
|
||||
"""The agent is asked for section prose and often prepends the same heading
|
||||
the template already emits, doubling every H1 (# Executive Summary followed
|
||||
by # Executive Summary). The formatter must strip the duplicated leading
|
||||
heading while leaving the body — and any legitimately repeated heading later
|
||||
in the body — intact."""
|
||||
from strix.report.state import ReportState
|
||||
|
||||
state = ReportState(run_name="t")
|
||||
result = state._format_final_scan_result(
|
||||
{
|
||||
"executive_summary": "# Executive Summary\n\nThe app is broadly sound.",
|
||||
"methodology": "# Methodology\n\nBlack-box, GET/HEAD only.",
|
||||
"technical_analysis": "# Technical Analysis\n\n## Target Profile\n\nDetails.",
|
||||
"recommendations": "# Recommendations\n\n## Immediate\n\nFix CSP.",
|
||||
}
|
||||
)
|
||||
# Each template heading appears exactly once.
|
||||
for heading in (
|
||||
"# Executive Summary",
|
||||
"# Methodology",
|
||||
"# Technical Analysis",
|
||||
"# Recommendations",
|
||||
):
|
||||
assert result.count(heading) == 1, f"{heading} doubled:\n{result}"
|
||||
# Bodies and genuine sub-headings survive.
|
||||
assert "The app is broadly sound." in result
|
||||
assert "## Target Profile" in result
|
||||
assert "## Immediate" in result
|
||||
|
||||
|
||||
def test_format_final_scan_result_keeps_content_without_headings() -> None:
|
||||
"""Content that does not repeat the heading is left alone."""
|
||||
from strix.report.state import ReportState
|
||||
|
||||
state = ReportState(run_name="t")
|
||||
result = state._format_final_scan_result(
|
||||
{
|
||||
"executive_summary": "The app is broadly sound.",
|
||||
"methodology": "Black-box.",
|
||||
"technical_analysis": "Some analysis.",
|
||||
"recommendations": "Fix things.",
|
||||
}
|
||||
)
|
||||
assert result.count("# Executive Summary") == 1
|
||||
assert "The app is broadly sound." in result
|
||||
|
||||
|
||||
def test_format_final_scan_result_keeps_later_repeated_heading() -> None:
|
||||
"""Only the FIRST line is examined: a heading repeated later in the body is
|
||||
legitimate content (e.g. a quoted section) and must be preserved."""
|
||||
from strix.report.state import ReportState
|
||||
|
||||
state = ReportState(run_name="t")
|
||||
body = "Intro.\n\n# Executive Summary\n\nA quoted recap below.\n"
|
||||
result = state._format_final_scan_result(
|
||||
{
|
||||
"executive_summary": body,
|
||||
"methodology": "m",
|
||||
"technical_analysis": "t",
|
||||
"recommendations": "r",
|
||||
}
|
||||
)
|
||||
# Template heading + the in-body repeat = two occurrences, not three.
|
||||
assert result.count("# Executive Summary") == 2
|
||||
assert "A quoted recap below." in result
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue