Replace findings list with a tree; filter ESD/PI false positives.
PE-ESD-001 only on J* connector–IC nets (skip NC, unconnected, VSYS/GND/3V3). PE-PI-001 treats any capacitor on the rail, including KiCad slash prefixes, as decoupling. Sort findings ERROR then WARNING then INFO, then RULE/RISK/REVIEW/INFO. Report sidebar is a collapsed expand-on-click tree instead of an all-open list. GET /report and complete_findings fail-soft and sort the same way.
This commit is contained in:
@@ -7,6 +7,7 @@ never becomes ERROR. LLM output is REVIEW, never RULE.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Iterable, Literal
|
||||
|
||||
@@ -14,6 +15,11 @@ from pydantic import BaseModel
|
||||
|
||||
from backend.periscopex.models import Finding
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
_STATUS_ORDER = {"ERROR": 0, "WARNING": 1, "INFO": 2}
|
||||
_CLASS_ORDER = {"RULE": 0, "RISK": 1, "REVIEW": 2, "INFO": 3}
|
||||
|
||||
Provenance = Literal["MANDATORY", "RECOMMENDED", "TYPICAL", "EXAMPLE"]
|
||||
FindingClass = Literal["RULE", "RISK", "REVIEW", "INFO"]
|
||||
EvidenceStatus = Literal["SUFFICIENT", "INSUFFICIENT"]
|
||||
@@ -256,9 +262,31 @@ def complete_finding(f: Finding) -> Finding:
|
||||
return f
|
||||
|
||||
|
||||
def sort_findings(findings: list[Finding]) -> list[Finding]:
|
||||
"""ERROR then WARNING then INFO; within that RULE > RISK > REVIEW > INFO."""
|
||||
findings.sort(
|
||||
key=lambda f: (
|
||||
_STATUS_ORDER.get(f.status or "INFO", 9),
|
||||
_CLASS_ORDER.get(f.finding_class or "INFO", 9),
|
||||
f.designator or "",
|
||||
f.rule_id or "",
|
||||
f.finding or "",
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
|
||||
def complete_findings(findings: list[Finding]) -> None:
|
||||
for f in findings:
|
||||
complete_finding(f)
|
||||
try:
|
||||
complete_finding(f)
|
||||
except Exception:
|
||||
log.exception(
|
||||
"complete_finding failed for %s/%s",
|
||||
getattr(f, "designator", "?"),
|
||||
getattr(f, "rule_id", None),
|
||||
)
|
||||
sort_findings(findings)
|
||||
|
||||
|
||||
def apply_decisions(
|
||||
|
||||
Reference in New Issue
Block a user