Skip to content

Commit ae750b3

Browse files
committed
fix(dashboard): add missing 'Refresh Local Scan' button in Phase 3 sidebar
The Transparency Feed warned "Run 'Refresh Local Scan' in sidebar" but the button was never implemented. Adds sidebar button that computes SHA-256 evidence hash, runs CycloneDX BOM scan, and loads code context from the latest trace file. Bump to v0.5.4.
1 parent ee6dcfd commit ae750b3

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "venturalitica"
3-
version = "0.5.3"
3+
version = "0.5.4"
44
description = "Frictionless Governance for AI. Enforce policies in your ML training with one line of code."
55
requires-python = ">=3.11"
66
readme = "README.md"

src/venturalitica/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "0.5.3"
1+
__version__ = "0.5.4"
22

33
from .api import (
44
enforce,

src/venturalitica/dashboard/main.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import hashlib
2+
import json
13
import os # Forced reload triggered by agent
24
import sys
35
import types
@@ -92,6 +94,56 @@ def _resolve_logo():
9294
return None, 50
9395

9496

97+
def _run_local_scan(target_dir: str):
98+
"""Scan the project directory to populate evidence for Phase 3."""
99+
from pathlib import Path
100+
101+
# 1. Evidence hash — SHA-256 of all .py files
102+
h = hashlib.sha256()
103+
py_files = sorted(Path(target_dir).rglob("*.py"))
104+
for pf in py_files:
105+
if ".venv" in pf.parts or "__pycache__" in pf.parts:
106+
continue
107+
try:
108+
h.update(pf.read_bytes())
109+
except OSError:
110+
pass
111+
st.session_state["evidence_hash"] = h.hexdigest()
112+
113+
# 2. BOM scan
114+
try:
115+
from venturalitica.scanner import BOMScanner
116+
117+
scanner = BOMScanner(target_dir)
118+
bom_json = scanner.scan()
119+
bom_data = json.loads(bom_json)
120+
st.session_state["bom"] = bom_data
121+
st.session_state["bom_security"] = {"vulnerable": False, "issues": []}
122+
except Exception:
123+
st.session_state["bom"] = {}
124+
st.session_state["bom_security"] = {}
125+
126+
# 3. Code context from latest trace (if available)
127+
runs_dir = Path(target_dir) / ".venturalitica" / "runs"
128+
if runs_dir.exists():
129+
sessions = sorted(
130+
[d for d in runs_dir.iterdir() if d.is_dir() and d.name != "latest"],
131+
reverse=True,
132+
)
133+
for session_dir in sessions:
134+
for trace_file in session_dir.glob("trace_*.json"):
135+
try:
136+
trace = json.loads(trace_file.read_text())
137+
if trace.get("code_context"):
138+
st.session_state["code_context"] = trace["code_context"]
139+
st.session_state["runtime_meta"] = trace
140+
break
141+
except Exception:
142+
pass
143+
if st.session_state.get("code_context"):
144+
break
145+
146+
95147
def render_dashboard():
96148
# --- HEADER ---
97149
logo_path, logo_width = _resolve_logo()
@@ -291,6 +343,14 @@ def format_phase(key):
291343
# PHASE 3 & 4: SESSION CONTEXT REQUIRED
292344
# =========================================================================
293345
else:
346+
# --- Refresh Local Scan button ---
347+
st.sidebar.markdown("### 🔬 Local Scan")
348+
if st.sidebar.button("🔄 Refresh Local Scan", use_container_width=True):
349+
with st.sidebar:
350+
with st.spinner("Scanning project..."):
351+
_run_local_scan(target_dir)
352+
st.rerun()
353+
294354
# Session Selector
295355
st.sidebar.markdown("### 🕒 Session Context")
296356
available_sessions = ["Global / History"] + list_available_sessions()

0 commit comments

Comments
 (0)