"""Bulk scan report rendering for Cursor and other consumers.""" from __future__ import annotations from typing import Any _SEVERITY_ORDER = ("critical", "high", "medium", "low", "info") _PHASE_OUTPUT_MAX = 4000 def _sort_findings(findings: list[dict[str, Any]]) -> list[dict[str, Any]]: order = {s: i for i, s in enumerate(_SEVERITY_ORDER)} return sorted(findings, key=lambda f: order.get(str(f.get("severity", "")).lower(), 99)) def _truncate(text: str, limit: int = _PHASE_OUTPUT_MAX) -> str: text = (text or "").strip() if len(text) <= limit: return text return text[: limit - 40] + "\n\n… (truncated)" def render_bulk_markdown(payload: dict[str, Any], *, for_cursor: bool = False) -> str: bulk = payload["bulk"] scans = payload["scans"] lines: list[str] = [] if for_cursor: lines.extend( [ "", "", "You are reviewing authorized security scan results from Talos.", "Prioritize critical/high findings, then failed phases that may hide issues.", "", ] ) lines.extend( [ f"# Talos bulk report", "", f"- **Bulk ID:** `{bulk['id']}`", f"- **Profile:** {bulk['profile']}", f"- **Status:** {bulk['status']}", f"- **Progress:** {bulk['complete']}/{bulk['total']} complete" + (f", {bulk['failed']} failed" if bulk.get("failed") else "") + (f", {bulk['running']} running" if bulk.get("running") else "") + (f", {bulk['queued']} queued" if bulk.get("queued") else ""), "", ] ) # Cross-target finding rollup (severity >= low with issues) all_findings: list[tuple[str, dict[str, Any]]] = [] for entry in scans: target = entry["scan"]["target"] for f in entry.get("findings") or []: if f.get("severity") in ("critical", "high", "medium", "low"): all_findings.append((target, f)) if all_findings: lines.append("## Findings rollup (all targets)") lines.append("") for target, f in sorted( all_findings, key=lambda x: _SEVERITY_ORDER.index(x[1]["severity"]) if x[1]["severity"] in _SEVERITY_ORDER else 99, ): sev = f["severity"].upper() lines.append(f"- **[{sev}]** `{target}` — {f['title']}") lines.append("") for entry in scans: scan = entry["scan"] phases = entry.get("phases") or [] findings = _sort_findings(entry.get("findings") or []) lines.append(f"## {scan['target']}") lines.append("") lines.append(f"- Scan ID: `{scan['id']}`") lines.append(f"- Status: **{scan['status']}**") if scan.get("llm_unavailable"): lines.append("- LLM analysis was unavailable for some phases") lines.append("") lines.append("### Phases") lines.append("") lines.append("| Phase | Status | Tool |") lines.append("|-------|--------|------|") for p in phases: lines.append(f"| {p['name']} | {p['status']} | {p.get('tool', '')} |") lines.append("") failed_phases = [p for p in phases if p["status"] in ("failed", "blocked", "inconclusive")] if failed_phases: lines.append("### Phase notes (non-complete)") lines.append("") for p in failed_phases: snippet = _truncate(p.get("raw_output") or "", 800) lines.append(f"**{p['name']}** ({p['status']})") if snippet: lines.append("") lines.append("```") lines.append(snippet) lines.append("```") lines.append("") if findings: lines.append("### Findings") lines.append("") for f in findings: sev = str(f["severity"]).upper() lines.append(f"#### [{sev}] {f['title']}") lines.append("") lines.append(f["description"]) lines.append("") if f.get("evidence"): lines.append(f"**Evidence:** `{_truncate(str(f['evidence']), 500)}`") lines.append("") lines.append(f"**Recommendation:** {f['recommendation']}") lines.append("") else: lines.append("_No LLM findings recorded._") lines.append("") lines.append("---") lines.append("") return "\n".join(lines).rstrip() + "\n" def render_bulk_json(payload: dict[str, Any]) -> dict[str, Any]: """JSON export with truncated phase output to keep size reasonable.""" out = dict(payload) scans_out: list[dict[str, Any]] = [] for entry in payload.get("scans") or []: entry = dict(entry) phases = [] for p in entry.get("phases") or []: p = dict(p) if p.get("raw_output"): p["raw_output"] = _truncate(str(p["raw_output"])) phases.append(p) entry["phases"] = phases scans_out.append(entry) out["scans"] = scans_out return out