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:
2026-09-20 10:03:50 +02:00
parent 342792df2d
commit bee6369c1d
13 changed files with 628 additions and 137 deletions
+12 -2
View File
@@ -1,6 +1,6 @@
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
import type { Finding, FindingStatus } from "./types";
import type { Finding, FindingClass, FindingStatus } from "./types";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
@@ -16,9 +16,19 @@ export function groupBy<T>(items: T[], key: (item: T) => string): Record<string,
}
const STATUS_ORDER: Record<FindingStatus, number> = { ERROR: 0, WARNING: 1, INFO: 2 };
const CLASS_ORDER: Record<FindingClass, number> = { RULE: 0, RISK: 1, REVIEW: 2, INFO: 3 };
export function sortFindings(findings: Finding[]): Finding[] {
return [...findings].sort((a, b) => STATUS_ORDER[a.status] - STATUS_ORDER[b.status]);
return [...findings].sort((a, b) => {
const status = STATUS_ORDER[a.status] - STATUS_ORDER[b.status];
if (status !== 0) return status;
const ac = CLASS_ORDER[a.finding_class ?? "INFO"] ?? 9;
const bc = CLASS_ORDER[b.finding_class ?? "INFO"] ?? 9;
if (ac !== bc) return ac - bc;
return (a.designator || "").localeCompare(b.designator || "")
|| (a.rule_id || "").localeCompare(b.rule_id || "")
|| (a.finding || "").localeCompare(b.finding || "");
});
}
export function getFindingKey(finding: Finding, index: number): string {