gitmodelmujtaba commited on
Commit
35d2813
Β·
verified Β·
1 Parent(s): b36cf96

Deploy ReguAI: Neuro-Symbolic AI GRC & Automated Conformity Assessment Engine

Browse files
Files changed (2) hide show
  1. app.py +204 -91
  2. data/active_learning_triplets.jsonl +1 -0
app.py CHANGED
@@ -37,70 +37,48 @@ DEFAULT_FACTSHEET = catalog.render_factsheet_html(DEFAULT_CASE_TITLE)
37
  DEFAULT_QUICK_BAR = catalog.render_quick_bar(DEFAULT_CASE_TITLE)
38
 
39
 
 
 
 
 
 
 
 
 
40
  def on_domain_change(selected_domain_name: str):
41
  cases = catalog.get_cases_for_domain(selected_domain_name)
 
 
 
 
 
 
42
  if not cases:
43
- return gr.update(choices=[], value=None), "", "", "<div style='padding:15px;'>No cases found.</div>"
44
  titles = [c["title"] for c in cases]
45
  first_title = titles[0]
46
  text = catalog.get_case_document_text(first_title)
47
  factsheet = catalog.render_factsheet_html(first_title)
48
  quick_bar = catalog.render_quick_bar(first_title)
49
- return gr.update(choices=titles, value=first_title), text, quick_bar, factsheet
50
 
51
 
52
  def on_case_change(selected_case_title: str):
 
 
 
 
 
 
53
  if not selected_case_title:
54
- return "", "", "<div style='padding:15px;'>Select a case study.</div>"
55
  text = catalog.get_case_document_text(selected_case_title)
56
  factsheet = catalog.render_factsheet_html(selected_case_title)
57
  quick_bar = catalog.render_quick_bar(selected_case_title)
58
- return text, quick_bar, factsheet
59
-
60
 
61
- def load_preset(domain_idx: int, case_idx: int = 0):
62
- domains = catalog.list_domains()
63
- if domain_idx >= len(domains):
64
- domain_idx = 0
65
- dom = domains[domain_idx]
66
- dom_name = dom["domain_name"]
67
- cases = dom.get("case_studies", [])
68
- if not cases:
69
- return gr.update(), gr.update(), "", "", ""
70
- case = cases[min(case_idx, len(cases) - 1)]
71
- case_title = case["title"]
72
- case_titles = [c["title"] for c in cases]
73
- text = catalog.get_case_document_text(case_title)
74
- factsheet = catalog.render_factsheet_html(case_title)
75
- quick_bar = catalog.render_quick_bar(case_title)
76
- return (
77
- gr.update(value=dom_name),
78
- gr.update(choices=case_titles, value=case_title),
79
- text,
80
- quick_bar,
81
- factsheet,
82
- )
83
-
84
-
85
- def run_assessment(doc_text: str, auditor_id: str, annual_turnover: float = 50000000.0, is_sme: bool = False):
86
- if not doc_text or not doc_text.strip():
87
- return (
88
- "⚠️ Please enter model card text or select a pre-loaded sample.",
89
- [],
90
- [],
91
- "<div style='padding:20px;text-align:center;'>No graph generated.</div>",
92
- "N/A",
93
- "N/A",
94
- "{}",
95
- "",
96
- "<div>No certificate generated.</div>",
97
- [],
98
- [],
99
- "<div style='padding:15px;'>No fine liability evaluated.</div>",
100
- "{}",
101
- "{}",
102
- )
103
 
 
104
  report = engine.evaluate_system(
105
  doc_text,
106
  auditor_id=auditor_id or "auditor_01",
@@ -249,32 +227,121 @@ def run_assessment(doc_text: str, auditor_id: str, annual_turnover: float = 5000
249
  bom_json = json.dumps(engine.report_generator.generate_cyclonedx_bom(report), indent=2)
250
  sarif_json = SarifExporter.export_sarif_json(report, indent=2)
251
 
252
- return (
253
- exec_html,
254
- violations_data,
255
- claims_data,
256
- graph_iframe_html,
257
- cert_token,
258
- hash_summary,
259
- json_ld_cert,
260
- md_report,
261
- cert_iframe_html,
262
- borderline_data,
263
- frameworks_data,
264
- fine_html,
265
- bom_json,
266
- sarif_json,
267
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
- def load_preset_and_assess(domain_idx: int, case_idx: int, auditor_id: str, turnover: float, is_sme: bool):
271
- dom_update, case_update, text, quick_bar, factsheet = load_preset(domain_idx, case_idx)
272
- assessment_res = run_assessment(text, auditor_id, turnover, is_sme)
273
- return (dom_update, case_update, text, quick_bar, factsheet, *assessment_res)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
 
276
  # Pre-compute live initial evaluation for default case study so dashboard opens fully populated
277
- DEFAULT_ASSESSMENT = run_assessment(DEFAULT_SPEC_TEXT, "lead_compliance_auditor_01", 50000000.0, False)
 
278
 
279
 
280
  def record_triage(claim_id: str, new_status: str, new_category: str, notes: str, auditor_id: str):
@@ -790,6 +857,21 @@ button[variant="primary"]:hover {
790
  color: #60a5fa !important;
791
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important;
792
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
793
  """
794
 
795
  with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
@@ -880,21 +962,23 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
880
  with gr.Row():
881
  assess_btn = gr.Button("⚑ Run Deterministic Conformity Assessment", variant="primary", size="lg")
882
 
883
- gr.HTML(
884
- """
885
- <div style="font-size: 13px; color: #64748b; margin-top: 12px; text-align: center; padding: 10px; background: rgba(0,0,0,0.02); border-radius: 8px;">
886
- πŸ’‘ Select a sector and case study above, adjust specifications or turnover if needed, and click <strong>Run Deterministic Conformity Assessment</strong>. Switch to tabs <strong>2️⃣ Review Grounding</strong>, <strong>3️⃣ Run SHACL Proofs</strong>, and <strong>4️⃣ Export Annex IV Package</strong> to inspect the results.
887
- </div>
888
- """
889
  )
890
 
 
 
 
 
 
891
  # =============================================================
892
  # TAB 2: 2️⃣ Review Grounding
893
  # =============================================================
894
  with gr.TabItem("2️⃣ Review Grounding", id="tab_review_grounding"):
895
  with gr.Tabs():
896
  with gr.TabItem("πŸ•ΈοΈ Knowledge Graph & Ontology"):
897
- graph_output = gr.HTML(value=DEFAULT_ASSESSMENT[3], label="Force-Directed Knowledge Graph")
898
  with gr.TabItem("πŸ“š EUR-Lex Legal Factsheet"):
899
  factsheet_box = gr.HTML(
900
  value=DEFAULT_FACTSHEET,
@@ -904,7 +988,7 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
904
  claims_table = gr.Dataframe(
905
  headers=["Claim ID", "Category", "Status", "Confidence", "Target Article", "Evidence Span"],
906
  datatype=["str", "str", "str", "str", "str", "str"],
907
- value=DEFAULT_ASSESSMENT[2],
908
  label="Extracted Regulatory Claims",
909
  )
910
  with gr.TabItem("πŸ‘€ Active Learning Triage Queue"):
@@ -912,7 +996,7 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
912
  borderline_table = gr.Dataframe(
913
  headers=["Claim ID", "Category", "Status", "Confidence", "Evidence Quote"],
914
  datatype=["str", "str", "str", "str", "str"],
915
- value=DEFAULT_ASSESSMENT[9],
916
  )
917
  with gr.Row():
918
  triage_claim_id = gr.Textbox(label="Claim ID", placeholder="e.g. clm_001", scale=3)
@@ -927,47 +1011,61 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
927
  frameworks_table = gr.Dataframe(
928
  headers=["Target Framework", "Control ID", "Control Name", "Status", "Linked AI Act Article", "Audit Guidance"],
929
  datatype=["str", "str", "str", "str", "str", "str"],
930
- value=DEFAULT_ASSESSMENT[10],
931
  label="Harmonized Multi-Framework Controls",
932
  )
933
 
 
 
 
 
934
  # =============================================================
935
  # TAB 3: 3️⃣ Run SHACL Proofs
936
  # =============================================================
937
  with gr.TabItem("3️⃣ Run SHACL Proofs", id="tab_run_shacl_proofs"):
938
  with gr.Row():
939
  assess_btn_tab3 = gr.Button("⚑ Re-Run Deterministic Conformity Proofs", variant="primary", size="md")
940
- exec_output = gr.HTML(value=DEFAULT_ASSESSMENT[0], label="Executive Summary")
941
- fine_liability_output = gr.HTML(value=DEFAULT_ASSESSMENT[11], label="Article 99 Fine Liability")
942
  violations_table = gr.Dataframe(
943
  headers=["Legal Article", "Normative Requirement", "Severity", "SHACL Path", "Remediation Guidance"],
944
  datatype=["str", "str", "str", "str", "str"],
945
- value=DEFAULT_ASSESSMENT[1],
946
  label="Mathematical Proof: Non-Conformities Found",
947
  )
948
 
 
 
 
 
949
  # =============================================================
950
  # TAB 4: 4️⃣ Export Annex IV Package
951
  # =============================================================
952
  with gr.TabItem("4️⃣ Export Annex IV Package", id="tab_export_annex_iv"):
953
  with gr.Tabs():
954
  with gr.TabItem("πŸ“œ Attestation Certificate (HTML)"):
955
- cert_html_output = gr.HTML(value=DEFAULT_ASSESSMENT[8])
956
  with gr.TabItem("πŸ“¦ CycloneDX 1.6 AI-BOM"):
957
- bom_display = gr.Code(value=DEFAULT_ASSESSMENT[12], language="json", label="CycloneDX 1.6 Machine-Readable AI-BOM")
958
  with gr.TabItem("πŸ›‘οΈ OASIS SARIF 2.1.0 Report"):
959
- sarif_display = gr.Code(value=DEFAULT_ASSESSMENT[13], language="json", label="OASIS SARIF 2.1.0 Static Analysis Report")
960
  with gr.TabItem("πŸ“„ Annex IV Report (Markdown)"):
961
- report_markdown = gr.Markdown(value=DEFAULT_ASSESSMENT[7])
962
  with gr.TabItem("🌐 Machine-Readable JSON-LD"):
963
- jsonld_display = gr.Code(value=DEFAULT_ASSESSMENT[6], language="json", label="W3C JSON-LD Digital Certificate")
964
  with gr.TabItem("πŸ” W3C PROV-O Ledger"):
965
- token_display = gr.Textbox(value=DEFAULT_ASSESSMENT[4], label="Official Digital Conformity Token", interactive=False)
966
- ledger_display = gr.Markdown(value=DEFAULT_ASSESSMENT[5])
 
 
 
 
967
 
968
- # Assessment outputs list (14 components)
969
  assessment_inputs = [spec_input, auditor_input, turnover_input, is_sme_input]
970
  assessment_outputs = [
 
 
971
  exec_output,
972
  violations_table,
973
  claims_table,
@@ -988,12 +1086,12 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
988
  domain_dropdown.change(
989
  fn=on_domain_change,
990
  inputs=[domain_dropdown],
991
- outputs=[case_dropdown, spec_input, quick_bar_box, factsheet_box],
992
  )
993
  case_dropdown.change(
994
  fn=on_case_change,
995
  inputs=[case_dropdown],
996
- outputs=[spec_input, quick_bar_box, factsheet_box],
997
  )
998
 
999
  # Wire assessment buttons (Tab 1 primary and Tab 3 re-run)
@@ -1008,6 +1106,20 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
1008
  outputs=assessment_outputs,
1009
  )
1010
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1011
  triage_btn.click(
1012
  fn=record_triage,
1013
  inputs=[triage_claim_id, triage_status, triage_cat, triage_notes, auditor_input],
@@ -1017,3 +1129,4 @@ with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
1017
  if __name__ == "__main__":
1018
  demo.launch(server_name="0.0.0.0", server_port=7860, share=False, theme=gr.themes.Soft(), css=CUSTOM_CSS)
1019
 
 
 
37
  DEFAULT_QUICK_BAR = catalog.render_quick_bar(DEFAULT_CASE_TITLE)
38
 
39
 
40
+ READY_BANNER_HTML = """
41
+ <div style="margin-top: 12px; padding: 12px 16px; border-radius: 8px; background: #f8fafc; border: 1px dashed #cbd5e1; font-size: 13px; color: #64748b; display: flex; align-items: center; gap: 8px;">
42
+ <span>ℹ️</span>
43
+ <span>Ready to evaluate. Click <strong>⚑ Run Deterministic Conformity Assessment</strong> below to execute SHACL verification and auto-navigate to Proofs.</span>
44
+ </div>
45
+ """
46
+
47
+
48
  def on_domain_change(selected_domain_name: str):
49
  cases = catalog.get_cases_for_domain(selected_domain_name)
50
+ banner = """
51
+ <div style="margin-top: 12px; padding: 12px 16px; border-radius: 8px; background: #f8fafc; border: 1px dashed #cbd5e1; font-size: 13px; color: #64748b; display: flex; align-items: center; gap: 8px;">
52
+ <span>ℹ️</span>
53
+ <span>New regulatory sector selected. Click <strong>⚑ Run Deterministic Conformity Assessment</strong> below to evaluate.</span>
54
+ </div>
55
+ """
56
  if not cases:
57
+ return gr.update(choices=[], value=None), "", "", "<div style='padding:15px;'>No cases found.</div>", banner
58
  titles = [c["title"] for c in cases]
59
  first_title = titles[0]
60
  text = catalog.get_case_document_text(first_title)
61
  factsheet = catalog.render_factsheet_html(first_title)
62
  quick_bar = catalog.render_quick_bar(first_title)
63
+ return gr.update(choices=titles, value=first_title), text, quick_bar, factsheet, banner
64
 
65
 
66
  def on_case_change(selected_case_title: str):
67
+ banner = """
68
+ <div style="margin-top: 12px; padding: 12px 16px; border-radius: 8px; background: #f8fafc; border: 1px dashed #cbd5e1; font-size: 13px; color: #64748b; display: flex; align-items: center; gap: 8px;">
69
+ <span>ℹ️</span>
70
+ <span>Case study loaded. Click <strong>⚑ Run Deterministic Conformity Assessment</strong> below to execute deterministic SHACL verification.</span>
71
+ </div>
72
+ """
73
  if not selected_case_title:
74
+ return "", "", "<div style='padding:15px;'>Select a case study.</div>", banner
75
  text = catalog.get_case_document_text(selected_case_title)
76
  factsheet = catalog.render_factsheet_html(selected_case_title)
77
  quick_bar = catalog.render_quick_bar(selected_case_title)
78
+ return text, quick_bar, factsheet, banner
 
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
+ def compute_assessment_data(doc_text: str, auditor_id: str, annual_turnover: float = 50000000.0, is_sme: bool = False):
82
  report = engine.evaluate_system(
83
  doc_text,
84
  auditor_id=auditor_id or "auditor_01",
 
227
  bom_json = json.dumps(engine.report_generator.generate_cyclonedx_bom(report), indent=2)
228
  sarif_json = SarifExporter.export_sarif_json(report, indent=2)
229
 
230
+ return {
231
+ "report": report,
232
+ "overall_conforms": report.overall_conforms,
233
+ "score": report.conformity_score,
234
+ "system_name": report.system_metadata.name,
235
+ "violations_count": len(report.violations),
236
+ "passed_count": report.passed_requirements_count,
237
+ "total_count": report.total_requirements_evaluated,
238
+ "exec_html": exec_html,
239
+ "violations_data": violations_data,
240
+ "claims_data": claims_data,
241
+ "graph_iframe_html": graph_iframe_html,
242
+ "cert_token": cert_token,
243
+ "hash_summary": hash_summary,
244
+ "json_ld_cert": json_ld_cert,
245
+ "md_report": md_report,
246
+ "cert_iframe_html": cert_iframe_html,
247
+ "borderline_data": borderline_data,
248
+ "frameworks_data": frameworks_data,
249
+ "fine_html": fine_html,
250
+ "bom_json": bom_json,
251
+ "sarif_json": sarif_json,
252
+ }
253
+
254
+
255
+ def run_assessment(doc_text: str, auditor_id: str, annual_turnover: float = 50000000.0, is_sme: bool = False):
256
+ if not doc_text or not doc_text.strip():
257
+ gr.Warning("Please select or enter a system technical specification.")
258
+ empty_banner = """
259
+ <div style="margin-top: 14px; padding: 14px 18px; border-radius: 8px; background: #fef2f2; border: 1.5px solid #fca5a5; color: #991b1b;">
260
+ ⚠️ Please enter or select a system technical specification before running assessment.
261
+ </div>
262
+ """
263
+ return (
264
+ gr.update(),
265
+ empty_banner,
266
+ "⚠️ Please enter model card text or select a pre-loaded sample.",
267
+ [],
268
+ [],
269
+ "<div style='padding:20px;text-align:center;'>No graph generated.</div>",
270
+ "N/A",
271
+ "N/A",
272
+ "{}",
273
+ "",
274
+ "<div>No certificate generated.</div>",
275
+ [],
276
+ [],
277
+ "<div style='padding:15px;'>No fine liability evaluated.</div>",
278
+ "{}",
279
+ "{}",
280
+ )
281
 
282
+ data = compute_assessment_data(doc_text, auditor_id, annual_turnover, is_sme)
283
+
284
+ status_tag = "PASSED (100%)" if data["overall_conforms"] else f"FAILED ({data['violations_count']} VIOLATIONS)"
285
+ gr.Info(f"Conformity Assessment: {data['system_name']} β€” {status_tag}. Navigating to Step 3: Run SHACL Proofs.")
286
+
287
+ if data["overall_conforms"]:
288
+ banner_html = f"""
289
+ <div style="margin-top: 14px; padding: 14px 18px; border-radius: 8px; background: #f0fdf4; border: 1.5px solid #86efac; display: flex; align-items: center; justify-content: space-between; box-shadow: 0 2px 4px rgba(0,0,0,0.04); flex-wrap: wrap; gap: 10px;">
290
+ <div style="display: flex; align-items: center; gap: 12px;">
291
+ <span style="font-size: 24px;">βœ…</span>
292
+ <div>
293
+ <div style="font-weight: 700; color: #166534; font-size: 15px;">Conformity Assessment Passed (100.0% Index)</div>
294
+ <div style="font-size: 13px; color: #15803d; margin-top: 2px;">
295
+ System: <strong>{data['system_name']}</strong> β€” All {data['passed_count']} normative requirements satisfied with zero SHACL violations.
296
+ </div>
297
+ </div>
298
+ </div>
299
+ <div style="font-size: 13px; font-weight: 600; color: #166534; background: #dcfce7; padding: 6px 12px; border-radius: 6px;">
300
+ βž” Auto-navigated to Step 3: Run SHACL Proofs
301
+ </div>
302
+ </div>
303
+ """
304
+ else:
305
+ banner_html = f"""
306
+ <div style="margin-top: 14px; padding: 14px 18px; border-radius: 8px; background: #fef2f2; border: 1.5px solid #fca5a5; display: flex; align-items: center; justify-content: space-between; box-shadow: 0 2px 4px rgba(0,0,0,0.04); flex-wrap: wrap; gap: 10px;">
307
+ <div style="display: flex; align-items: center; gap: 12px;">
308
+ <span style="font-size: 24px;">❌</span>
309
+ <div>
310
+ <div style="font-weight: 700; color: #991b1b; font-size: 15px;">Non-Conformities Detected ({data['violations_count']} SHACL Violations Found)</div>
311
+ <div style="font-size: 13px; color: #b91c1c; margin-top: 2px;">
312
+ System: <strong>{data['system_name']}</strong> β€” Conformity score: {data['score']:.1f}%. Immediate statutory remediation required.
313
+ </div>
314
+ </div>
315
+ </div>
316
+ <div style="font-size: 13px; font-weight: 600; color: #991b1b; background: #fee2e2; padding: 6px 12px; border-radius: 6px;">
317
+ βž” Auto-navigated to Step 3: Run SHACL Proofs
318
+ </div>
319
+ </div>
320
+ """
321
 
322
+ return (
323
+ gr.update(selected="tab_run_shacl_proofs"),
324
+ banner_html,
325
+ data["exec_html"],
326
+ data["violations_data"],
327
+ data["claims_data"],
328
+ data["graph_iframe_html"],
329
+ data["cert_token"],
330
+ data["hash_summary"],
331
+ data["json_ld_cert"],
332
+ data["md_report"],
333
+ data["cert_iframe_html"],
334
+ data["borderline_data"],
335
+ data["frameworks_data"],
336
+ data["fine_html"],
337
+ data["bom_json"],
338
+ data["sarif_json"],
339
+ )
340
 
341
 
342
  # Pre-compute live initial evaluation for default case study so dashboard opens fully populated
343
+ DEFAULT_ASSESSMENT = compute_assessment_data(DEFAULT_SPEC_TEXT, "lead_compliance_auditor_01", 50000000.0, False)
344
+
345
 
346
 
347
  def record_triage(claim_id: str, new_status: str, new_category: str, notes: str, auditor_id: str):
 
857
  color: #60a5fa !important;
858
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important;
859
  }
860
+
861
+ /* Workflow Step Navigation Buttons */
862
+ .tab-nav-footer {
863
+ margin-top: 24px !important;
864
+ padding-top: 16px !important;
865
+ border-top: 1px solid #e2e8f0 !important;
866
+ }
867
+
868
+ .dark .tab-nav-footer {
869
+ border-top-color: #334155 !important;
870
+ }
871
+
872
+ .tab1-nav-row {
873
+ margin-top: 12px !important;
874
+ }
875
  """
876
 
877
  with gr.Blocks(title="ReguAI: Neuro-Symbolic AI GRC Engine") as demo:
 
962
  with gr.Row():
963
  assess_btn = gr.Button("⚑ Run Deterministic Conformity Assessment", variant="primary", size="lg")
964
 
965
+ status_banner_box = gr.HTML(
966
+ value=READY_BANNER_HTML,
967
+ label="Assessment Execution Status",
 
 
 
968
  )
969
 
970
+ with gr.Row(elem_classes=["tab1-nav-row"]):
971
+ jump_to_tab2_btn = gr.Button("πŸ” Step 2: Review Grounding & Graph βž”", variant="secondary", size="sm")
972
+ jump_to_tab3_btn = gr.Button("πŸ“ Step 3: View SHACL Proofs & Scorecard βž”", variant="secondary", size="sm")
973
+ jump_to_tab4_btn = gr.Button("πŸ“¦ Step 4: Export Annex IV Package βž”", variant="secondary", size="sm")
974
+
975
  # =============================================================
976
  # TAB 2: 2️⃣ Review Grounding
977
  # =============================================================
978
  with gr.TabItem("2️⃣ Review Grounding", id="tab_review_grounding"):
979
  with gr.Tabs():
980
  with gr.TabItem("πŸ•ΈοΈ Knowledge Graph & Ontology"):
981
+ graph_output = gr.HTML(value=DEFAULT_ASSESSMENT["graph_iframe_html"], label="Force-Directed Knowledge Graph")
982
  with gr.TabItem("πŸ“š EUR-Lex Legal Factsheet"):
983
  factsheet_box = gr.HTML(
984
  value=DEFAULT_FACTSHEET,
 
988
  claims_table = gr.Dataframe(
989
  headers=["Claim ID", "Category", "Status", "Confidence", "Target Article", "Evidence Span"],
990
  datatype=["str", "str", "str", "str", "str", "str"],
991
+ value=DEFAULT_ASSESSMENT["claims_data"],
992
  label="Extracted Regulatory Claims",
993
  )
994
  with gr.TabItem("πŸ‘€ Active Learning Triage Queue"):
 
996
  borderline_table = gr.Dataframe(
997
  headers=["Claim ID", "Category", "Status", "Confidence", "Evidence Quote"],
998
  datatype=["str", "str", "str", "str", "str"],
999
+ value=DEFAULT_ASSESSMENT["borderline_data"],
1000
  )
1001
  with gr.Row():
1002
  triage_claim_id = gr.Textbox(label="Claim ID", placeholder="e.g. clm_001", scale=3)
 
1011
  frameworks_table = gr.Dataframe(
1012
  headers=["Target Framework", "Control ID", "Control Name", "Status", "Linked AI Act Article", "Audit Guidance"],
1013
  datatype=["str", "str", "str", "str", "str", "str"],
1014
+ value=DEFAULT_ASSESSMENT["frameworks_data"],
1015
  label="Harmonized Multi-Framework Controls",
1016
  )
1017
 
1018
+ with gr.Row(elem_classes=["tab-nav-footer"]):
1019
+ nav_tab2_to_tab1 = gr.Button("⬅️ Back to Step 1: Select Scenario", variant="secondary")
1020
+ nav_tab2_to_tab3 = gr.Button("Continue to Step 3: Run SHACL Proofs βž”", variant="primary")
1021
+
1022
  # =============================================================
1023
  # TAB 3: 3️⃣ Run SHACL Proofs
1024
  # =============================================================
1025
  with gr.TabItem("3️⃣ Run SHACL Proofs", id="tab_run_shacl_proofs"):
1026
  with gr.Row():
1027
  assess_btn_tab3 = gr.Button("⚑ Re-Run Deterministic Conformity Proofs", variant="primary", size="md")
1028
+ exec_output = gr.HTML(value=DEFAULT_ASSESSMENT["exec_html"], label="Executive Summary")
1029
+ fine_liability_output = gr.HTML(value=DEFAULT_ASSESSMENT["fine_html"], label="Article 99 Fine Liability")
1030
  violations_table = gr.Dataframe(
1031
  headers=["Legal Article", "Normative Requirement", "Severity", "SHACL Path", "Remediation Guidance"],
1032
  datatype=["str", "str", "str", "str", "str"],
1033
+ value=DEFAULT_ASSESSMENT["violations_data"],
1034
  label="Mathematical Proof: Non-Conformities Found",
1035
  )
1036
 
1037
+ with gr.Row(elem_classes=["tab-nav-footer"]):
1038
+ nav_tab3_to_tab2 = gr.Button("⬅️ Back to Step 2: Review Grounding", variant="secondary")
1039
+ nav_tab3_to_tab4 = gr.Button("Continue to Step 4: Export Annex IV Package βž”", variant="primary")
1040
+
1041
  # =============================================================
1042
  # TAB 4: 4️⃣ Export Annex IV Package
1043
  # =============================================================
1044
  with gr.TabItem("4️⃣ Export Annex IV Package", id="tab_export_annex_iv"):
1045
  with gr.Tabs():
1046
  with gr.TabItem("πŸ“œ Attestation Certificate (HTML)"):
1047
+ cert_html_output = gr.HTML(value=DEFAULT_ASSESSMENT["cert_iframe_html"])
1048
  with gr.TabItem("πŸ“¦ CycloneDX 1.6 AI-BOM"):
1049
+ bom_display = gr.Code(value=DEFAULT_ASSESSMENT["bom_json"], language="json", label="CycloneDX 1.6 Machine-Readable AI-BOM")
1050
  with gr.TabItem("πŸ›‘οΈ OASIS SARIF 2.1.0 Report"):
1051
+ sarif_display = gr.Code(value=DEFAULT_ASSESSMENT["sarif_json"], language="json", label="OASIS SARIF 2.1.0 Static Analysis Report")
1052
  with gr.TabItem("πŸ“„ Annex IV Report (Markdown)"):
1053
+ report_markdown = gr.Markdown(value=DEFAULT_ASSESSMENT["md_report"])
1054
  with gr.TabItem("🌐 Machine-Readable JSON-LD"):
1055
+ jsonld_display = gr.Code(value=DEFAULT_ASSESSMENT["json_ld_cert"], language="json", label="W3C JSON-LD Digital Certificate")
1056
  with gr.TabItem("πŸ” W3C PROV-O Ledger"):
1057
+ token_display = gr.Textbox(value=DEFAULT_ASSESSMENT["cert_token"], label="Official Digital Conformity Token", interactive=False)
1058
+ ledger_display = gr.Markdown(value=DEFAULT_ASSESSMENT["hash_summary"])
1059
+
1060
+ with gr.Row(elem_classes=["tab-nav-footer"]):
1061
+ nav_tab4_to_tab3 = gr.Button("⬅️ Back to Step 3: Review Proofs", variant="secondary")
1062
+ nav_tab4_to_tab1 = gr.Button("πŸ”„ Start New Scenario (Step 1)", variant="secondary")
1063
 
1064
+ # Assessment outputs list (16 components: main_tabs + status_banner_box + 14 metrics/deliverables)
1065
  assessment_inputs = [spec_input, auditor_input, turnover_input, is_sme_input]
1066
  assessment_outputs = [
1067
+ main_tabs,
1068
+ status_banner_box,
1069
  exec_output,
1070
  violations_table,
1071
  claims_table,
 
1086
  domain_dropdown.change(
1087
  fn=on_domain_change,
1088
  inputs=[domain_dropdown],
1089
+ outputs=[case_dropdown, spec_input, quick_bar_box, factsheet_box, status_banner_box],
1090
  )
1091
  case_dropdown.change(
1092
  fn=on_case_change,
1093
  inputs=[case_dropdown],
1094
+ outputs=[spec_input, quick_bar_box, factsheet_box, status_banner_box],
1095
  )
1096
 
1097
  # Wire assessment buttons (Tab 1 primary and Tab 3 re-run)
 
1106
  outputs=assessment_outputs,
1107
  )
1108
 
1109
+ # Workflow step navigation clicks
1110
+ jump_to_tab2_btn.click(fn=lambda: gr.update(selected="tab_review_grounding"), outputs=[main_tabs])
1111
+ jump_to_tab3_btn.click(fn=lambda: gr.update(selected="tab_run_shacl_proofs"), outputs=[main_tabs])
1112
+ jump_to_tab4_btn.click(fn=lambda: gr.update(selected="tab_export_annex_iv"), outputs=[main_tabs])
1113
+
1114
+ nav_tab2_to_tab1.click(fn=lambda: gr.update(selected="tab_select_scenario"), outputs=[main_tabs])
1115
+ nav_tab2_to_tab3.click(fn=lambda: gr.update(selected="tab_run_shacl_proofs"), outputs=[main_tabs])
1116
+
1117
+ nav_tab3_to_tab2.click(fn=lambda: gr.update(selected="tab_review_grounding"), outputs=[main_tabs])
1118
+ nav_tab3_to_tab4.click(fn=lambda: gr.update(selected="tab_export_annex_iv"), outputs=[main_tabs])
1119
+
1120
+ nav_tab4_to_tab3.click(fn=lambda: gr.update(selected="tab_run_shacl_proofs"), outputs=[main_tabs])
1121
+ nav_tab4_to_tab1.click(fn=lambda: gr.update(selected="tab_select_scenario"), outputs=[main_tabs])
1122
+
1123
  triage_btn.click(
1124
  fn=record_triage,
1125
  inputs=[triage_claim_id, triage_status, triage_cat, triage_notes, auditor_input],
 
1129
  if __name__ == "__main__":
1130
  demo.launch(server_name="0.0.0.0", server_port=7860, share=False, theme=gr.themes.Soft(), css=CUSTOM_CSS)
1131
 
1132
+
data/active_learning_triplets.jsonl CHANGED
@@ -21,3 +21,4 @@
21
  {"timestamp": "2026-09-21T14:47:50.118531+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
22
  {"timestamp": "2026-09-21T14:48:40.951594+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
23
  {"timestamp": "2026-09-21T15:05:44.655438+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
 
 
21
  {"timestamp": "2026-09-21T14:47:50.118531+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
22
  {"timestamp": "2026-09-21T14:48:40.951594+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
23
  {"timestamp": "2026-09-21T15:05:44.655438+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}
24
+ {"timestamp": "2026-09-21T16:35:03.024528+00:00", "auditor_id": "compliance_lead_01", "claim_id": "clm_test_99", "anchor_text": "Verified operational override in production dashboard.", "positive_label": "HUMAN_OVERSIGHT", "negative_label": "IRRELEVANT_TEXT", "verified_assertion_status": "IMPLEMENTED", "auditor_notes": "Verified operational override in production dashboard."}