Flamehaven Initiative commited on
Commit
dd357f4
·
1 Parent(s): f8e03dc

feat: compact repeated html evidence rows

Browse files
Files changed (1) hide show
  1. stem_ai/render_html.py +65 -1
stem_ai/render_html.py CHANGED
@@ -24,6 +24,60 @@ from .render_html_components import (
24
  from .render_html_styles import build_css, JS
25
 
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  def _calibration_effect_note(calibration: dict[str, Any]) -> str | None:
28
  if calibration.get("profile_read_mode") != "mirror_only":
29
  return None
@@ -517,6 +571,8 @@ def _section5(evidence_ledger: list) -> str:
517
  f'No evidence entries collected.</div></section>'
518
  )
519
  n = len(evidence_ledger)
 
 
520
  chips = " ".join(
521
  f'<span class="filter-chip{" active" if i == 0 else ""}" data-sev="{s}" onclick="filterEv(\'{s}\')">{l}</span>'
522
  for i, (s, l) in enumerate(
@@ -529,16 +585,24 @@ def _section5(evidence_ledger: list) -> str:
529
  ]
530
  )
531
  )
532
- rows = "".join(evidence_row(ev) for ev in evidence_ledger[:200])
533
  hint = tip_icon(
534
  "Full evidence ledger from all detectors. Filter by severity. Capped at 200 entries in HTML view."
535
  )
 
 
 
 
 
 
 
536
  th = f'style="padding:8px 5px;font-size:11px;text-align:left;color:{_C["dgray"]}"'
537
  return (
538
  f'<section id="s5">'
539
  f'<h2 class="s-title">Evidence Detail {hint}</h2>'
540
  f'<div class="panel">'
541
  f'<div class="toggle-row" style="margin-bottom:14px">{chips}</div>'
 
542
  f'<div style="overflow-x:auto">'
543
  f'<table style="width:100%;border-collapse:collapse">'
544
  f'<thead><tr style="background:{_C["lgray"]}">'
 
24
  from .render_html_styles import build_css, JS
25
 
26
 
27
+ def _compress_evidence_for_html(evidence_ledger: list[dict[str, Any]], limit: int = 200) -> list[dict[str, Any]]:
28
+ compact: list[dict[str, Any]] = []
29
+ grouped: dict[tuple[str, str, str], dict[str, Any]] = {}
30
+ grouped_order: list[tuple[str, str, str]] = []
31
+
32
+ for ev in evidence_ledger[:limit]:
33
+ severity = str(ev.get("severity", ev.get("status", "INFO"))).upper()
34
+ detector = str(ev.get("detector", ev.get("check", "")))
35
+ file_path = str(ev.get("file", ev.get("path", "")))
36
+ line = int(ev.get("line", 0) or 0)
37
+ message = str(ev.get("message") or ev.get("detail") or ev.get("explanation") or "").strip()
38
+
39
+ if severity in {"INFO", "WARN", "PASS"} and detector and file_path and file_path != "." and message:
40
+ key = (severity, detector, file_path, message)
41
+ if key not in grouped:
42
+ grouped[key] = {
43
+ "severity": severity.lower(),
44
+ "status": severity.lower(),
45
+ "detector": detector,
46
+ "file": file_path,
47
+ "line": line,
48
+ "snippet": ev.get("snippet", ""),
49
+ "message": message,
50
+ "aggregate_count": 1,
51
+ "aggregate_lines": [line] if line else [],
52
+ }
53
+ grouped_order.append(key)
54
+ else:
55
+ grouped[key]["aggregate_count"] += 1
56
+ if line and line not in grouped[key]["aggregate_lines"]:
57
+ grouped[key]["aggregate_lines"].append(line)
58
+ continue
59
+
60
+ compact.append(ev)
61
+
62
+ for key in grouped_order:
63
+ group = grouped[key]
64
+ count = int(group.get("aggregate_count", 1))
65
+ lines = sorted(group.get("aggregate_lines", []))
66
+ if count > 1:
67
+ base = str(group.get("message") or "Repeated informational evidence detected.").strip()
68
+ if lines:
69
+ line_preview = ", ".join(str(n) for n in lines[:6])
70
+ if len(lines) > 6:
71
+ line_preview += ", ..."
72
+ group["message"] = f"{base} Aggregated {count} matches from one file (lines: {line_preview})."
73
+ else:
74
+ group["message"] = f"{base} Aggregated {count} matches from one file."
75
+ group["snippet"] = ""
76
+ compact.append(group)
77
+
78
+ return compact
79
+
80
+
81
  def _calibration_effect_note(calibration: dict[str, Any]) -> str | None:
82
  if calibration.get("profile_read_mode") != "mirror_only":
83
  return None
 
571
  f'No evidence entries collected.</div></section>'
572
  )
573
  n = len(evidence_ledger)
574
+ display_rows = _compress_evidence_for_html(evidence_ledger, limit=200)
575
+ shown = len(display_rows)
576
  chips = " ".join(
577
  f'<span class="filter-chip{" active" if i == 0 else ""}" data-sev="{s}" onclick="filterEv(\'{s}\')">{l}</span>'
578
  for i, (s, l) in enumerate(
 
585
  ]
586
  )
587
  )
588
+ rows = "".join(evidence_row(ev) for ev in display_rows)
589
  hint = tip_icon(
590
  "Full evidence ledger from all detectors. Filter by severity. Capped at 200 entries in HTML view."
591
  )
592
+ compact_note = ""
593
+ if shown < min(n, 200):
594
+ compact_note = (
595
+ f'<div class="muted" style="margin:0 0 10px 0">'
596
+ f'Showing {shown} compact rows from the first {min(n, 200)} evidence entries.'
597
+ f'</div>'
598
+ )
599
  th = f'style="padding:8px 5px;font-size:11px;text-align:left;color:{_C["dgray"]}"'
600
  return (
601
  f'<section id="s5">'
602
  f'<h2 class="s-title">Evidence Detail {hint}</h2>'
603
  f'<div class="panel">'
604
  f'<div class="toggle-row" style="margin-bottom:14px">{chips}</div>'
605
+ f'{compact_note}'
606
  f'<div style="overflow-x:auto">'
607
  f'<table style="width:100%;border-collapse:collapse">'
608
  f'<thead><tr style="background:{_C["lgray"]}">'