rezabarkhordary commited on
Commit
1a3f0e5
·
verified ·
1 Parent(s): f9e7441

Create severeign_false_positive_report.py

Browse files
Files changed (1) hide show
  1. severeign_false_positive_report.py +190 -0
severeign_false_positive_report.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # sovereign_false_positive_report.py
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ import os
6
+ from datetime import datetime, timezone
7
+ from typing import Any, Dict, List, Optional
8
+
9
+ from sovereign_false_positive_suite import run_false_positive_suite
10
+
11
+
12
+ FALSE_POSITIVE_OUTPUT_DIR = "sovereign_validation_outputs"
13
+
14
+
15
+ def _utc_now() -> str:
16
+ return datetime.now(timezone.utc).isoformat()
17
+
18
+
19
+ def _ensure_dir(path: str) -> None:
20
+ os.makedirs(path, exist_ok=True)
21
+
22
+
23
+ def _safe(v: Any, default: Any = "") -> Any:
24
+ return v if v is not None else default
25
+
26
+
27
+ def _pct(v: Any) -> str:
28
+ try:
29
+ return f"{float(v):.2f}%"
30
+ except Exception:
31
+ return "0.00%"
32
+
33
+
34
+ def _render_summary(report: Dict[str, Any]) -> str:
35
+ metrics = report.get("metrics", {})
36
+
37
+ return f"""# Sovereign Validation Report
38
+ Generated at: {_safe(report.get("generated_at"), _utc_now())}
39
+
40
+ ## 1. Validation Identity
41
+ - Suite Name: {_safe(report.get("suite_name"), "Sovereign Validation Suite")}
42
+
43
+ ## 2. Executive Summary
44
+ - Total Cases: {_safe(metrics.get("total_cases"), 0)}
45
+ - Matched Cases: {_safe(metrics.get("matched_cases"), 0)}
46
+ - Accuracy: {_pct(metrics.get("accuracy_pct", 0))}
47
+ - False Positive Count: {_safe(metrics.get("false_positive_count"), 0)}
48
+ - False Positive Rate: {_pct(metrics.get("false_positive_rate_pct", 0))}
49
+ - False Negative Count: {_safe(metrics.get("false_negative_count"), 0)}
50
+ - False Negative Rate: {_pct(metrics.get("false_negative_rate_pct", 0))}
51
+ - Block Precision: {_pct(metrics.get("block_precision_pct", 0))}
52
+ - Block Recall: {_pct(metrics.get("block_recall_pct", 0))}
53
+ - Freeze Recall: {_pct(metrics.get("freeze_recall_pct", 0))}
54
+ """
55
+
56
+
57
+ def _render_operational_breakdown(report: Dict[str, Any]) -> str:
58
+ metrics = report.get("metrics", {})
59
+ expected = metrics.get("decision_distribution_expected", {})
60
+ actual = metrics.get("decision_distribution_actual", {})
61
+
62
+ return f"""## 3. Operational Breakdown
63
+
64
+ ### Expected Distribution
65
+ - ALLOW: {_safe(expected.get("ALLOW"), 0)}
66
+ - FREEZE: {_safe(expected.get("FREEZE"), 0)}
67
+ - BLOCK: {_safe(expected.get("BLOCK"), 0)}
68
+
69
+ ### Actual Distribution
70
+ - ALLOW: {_safe(actual.get("ALLOW"), 0)}
71
+ - FREEZE: {_safe(actual.get("FREEZE"), 0)}
72
+ - BLOCK: {_safe(actual.get("BLOCK"), 0)}
73
+ - UNKNOWN: {_safe(actual.get("UNKNOWN"), 0)}
74
+
75
+ ### Category Quality
76
+ - Benign Total: {_safe(metrics.get("benign_total"), 0)}
77
+ - Benign Correct Allow: {_safe(metrics.get("benign_correct_allow"), 0)}
78
+ - Malicious Total: {_safe(metrics.get("malicious_total"), 0)}
79
+ - Malicious Correct Block: {_safe(metrics.get("malicious_correct_block"), 0)}
80
+ - Ambiguous Total: {_safe(metrics.get("ambiguous_total"), 0)}
81
+ - Ambiguous Correct Freeze: {_safe(metrics.get("ambiguous_correct_freeze"), 0)}
82
+ """
83
+
84
+
85
+ def _render_case_outcomes(report: Dict[str, Any]) -> str:
86
+ outcomes = report.get("outcomes", [])
87
+ lines: List[str] = []
88
+ lines.append("## 4. Case-by-Case Outcomes")
89
+
90
+ if not outcomes:
91
+ lines.append("- No outcomes recorded.")
92
+ return "\n".join(lines)
93
+
94
+ for item in outcomes:
95
+ lines.append(f"### {item.get('case_id', 'unknown_case')}")
96
+ lines.append(f"- Category: {_safe(item.get('category'))}")
97
+ lines.append(f"- Expected: {_safe(item.get('expected'))}")
98
+ lines.append(f"- Actual: {_safe(item.get('actual'))}")
99
+ lines.append(f"- Match: {_safe(item.get('match'))}")
100
+ lines.append(f"- False Positive: {_safe(item.get('false_positive'))}")
101
+ lines.append(f"- False Negative: {_safe(item.get('false_negative'))}")
102
+ lines.append(f"- Summary: {_safe(item.get('result_summary'))}")
103
+ lines.append("")
104
+
105
+ return "\n".join(lines).rstrip() + "\n"
106
+
107
+
108
+ def _render_preliminary_verdict(report: Dict[str, Any]) -> str:
109
+ metrics = report.get("metrics", {})
110
+ fp = float(metrics.get("false_positive_rate_pct", 0.0) or 0.0)
111
+ fn = float(metrics.get("false_negative_rate_pct", 0.0) or 0.0)
112
+ accuracy = float(metrics.get("accuracy_pct", 0.0) or 0.0)
113
+
114
+ if accuracy >= 85.0 and fp <= 15.0 and fn <= 15.0:
115
+ verdict = "Validation posture is promising for continued bank-grade hardening."
116
+ elif accuracy >= 70.0 and fp <= 25.0 and fn <= 25.0:
117
+ verdict = "Validation posture is directionally acceptable, but more tuning is required before customer-facing claims."
118
+ else:
119
+ verdict = "Validation posture indicates meaningful tuning is still required before bank-facing production claims."
120
+
121
+ return f"""## 5. Preliminary Technical Verdict
122
+ {verdict}
123
+
124
+ ## 6. Notes
125
+ - This validation report reflects the current Sovereign bank runtime path.
126
+ - False positive performance is especially important for banking trust and operator adoption.
127
+ - False negative performance is especially important for risk containment and control credibility.
128
+ - This report is a technical validation artifact, not yet a final regulatory or procurement submission.
129
+ """
130
+
131
+
132
+ def build_false_positive_markdown(report: Dict[str, Any]) -> str:
133
+ parts = [
134
+ _render_summary(report),
135
+ _render_operational_breakdown(report),
136
+ _render_case_outcomes(report),
137
+ _render_preliminary_verdict(report),
138
+ ]
139
+ return "\n\n".join(parts).strip() + "\n"
140
+
141
+
142
+ def save_false_positive_report(
143
+ report: Dict[str, Any],
144
+ output_dir: str = FALSE_POSITIVE_OUTPUT_DIR,
145
+ base_name: Optional[str] = None,
146
+ ) -> Dict[str, str]:
147
+ _ensure_dir(output_dir)
148
+
149
+ ts = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
150
+ base = base_name or f"sovereign_validation_report_{ts}"
151
+
152
+ json_path = os.path.join(output_dir, f"{base}.json")
153
+ md_path = os.path.join(output_dir, f"{base}.md")
154
+
155
+ with open(json_path, "w", encoding="utf-8") as f:
156
+ json.dump(report, f, ensure_ascii=False, indent=2)
157
+
158
+ markdown = build_false_positive_markdown(report)
159
+ with open(md_path, "w", encoding="utf-8") as f:
160
+ f.write(markdown)
161
+
162
+ return {
163
+ "json_report": json_path,
164
+ "markdown_report": md_path,
165
+ }
166
+
167
+
168
+ def generate_false_positive_report(
169
+ output_dir: str = FALSE_POSITIVE_OUTPUT_DIR,
170
+ base_name: Optional[str] = None,
171
+ ) -> Dict[str, Any]:
172
+ report = run_false_positive_suite()
173
+ files = save_false_positive_report(
174
+ report=report,
175
+ output_dir=output_dir,
176
+ base_name=base_name,
177
+ )
178
+
179
+ return {
180
+ "ok": True,
181
+ "generated_at": _utc_now(),
182
+ "report": report,
183
+ "files": files,
184
+ }
185
+
186
+
187
+ if __name__ == "__main__":
188
+ out = generate_false_positive_report()
189
+ print(json.dumps(out, indent=2, ensure_ascii=False))
190
+