import streamlit as st
from core import audit
from core.config import BIDDER_NAMES
from core.fallback import load_criteria
from core.schemas import Criterion
from ui.components import confidence_bar, verdict_pill
def _crit_map() -> dict[str, Criterion]:
data = st.session_state.get("criteria")
return {c["id"]: Criterion(**c) for c in data} if data else {c.id: c for c in load_criteria()}
def render() -> None:
st.markdown(
'
'
'Human Review Queue
'
''
'Verdicts that could not be automatically confirmed require officer sign-off.
',
unsafe_allow_html=True,
)
vdata: dict = st.session_state.get("verdicts", {})
if not vdata:
st.info("No evaluation results yet. Run the evaluation in the Bidder Evaluation tab first.")
return
cm = _crit_map()
pending = [
(bid, i, v)
for bid, verdicts in vdata.items()
for i, v in enumerate(verdicts)
if v.get("verdict") == "needs_review" and
v.get("review_status", "pending") == "pending"
]
if not pending:
st.success("✅ All flagged verdicts have been actioned. Nothing pending.")
return
st.markdown(
f''
f'
⚠️'
f'
'
f'
'
f'{len(pending)} item{"s" if len(pending) != 1 else ""} pending review
'
f'
'
f'High certainty = model is confident this needs human judgment, '
f'not that the bidder is ineligible.
'
f'
',
unsafe_allow_html=True,
)
for bid, idx, v in pending:
crit = cm.get(v["criterion_id"])
crit_title = crit.title if crit else v["criterion_id"]
company = BIDDER_NAMES.get(bid, bid)
with st.container(border=True):
st.markdown(
f''
f'
'
f'
'
f'{company}
'
f'
{v["criterion_id"]}: {crit_title}
'
f'
'
f'{verdict_pill(v["verdict"])}'
f'
',
unsafe_allow_html=True,
)
col_l, col_r = st.columns([3, 1])
with col_l:
if v.get("extracted_value"):
st.markdown(
f''
f'Extracted value: '
f'{v["extracted_value"]}
',
unsafe_allow_html=True,
)
if v.get("reason"):
st.markdown(
f''
f'Reason: {v["reason"]}
',
unsafe_allow_html=True,
)
if v.get("source") and v["source"].get("snippet"):
st.markdown(
f'“{v["source"]["snippet"]}”
',
unsafe_allow_html=True,
)
with col_r:
confidence_bar(v.get("combined_confidence", 0.0), "Certainty")
st.markdown("", unsafe_allow_html=True)
kp = f"rv_{bid}_{v['criterion_id']}"
bc1, bc2, bc3 = st.columns(3)
common = dict(bidder_id=bid, criterion_id=v["criterion_id"],
original_verdict=v["verdict"],
original_extracted_value=v.get("extracted_value", ""),
combined_confidence=v.get("combined_confidence", 0.0))
with bc1:
if st.button("✅ Approve", key=f"{kp}_approve",
use_container_width=True, type="primary"):
st.session_state["verdicts"][bid][idx]["review_status"] = "approved"
audit.log("human_review_action", actor="officer",
action_taken="approved", **common)
st.rerun()
with bc2:
edited = st.text_input("Corrected value", key=f"{kp}_edit_val",
placeholder="Optional override…",
label_visibility="collapsed")
if st.button("✏️ Edit & Approve", key=f"{kp}_edit", use_container_width=True):
st.session_state["verdicts"][bid][idx]["review_status"] = "edited"
if edited:
st.session_state["verdicts"][bid][idx]["extracted_value"] = edited
audit.log("human_review_action", actor="officer",
action_taken="edited", edited_value=edited, **common)
st.rerun()
with bc3:
if st.button("❌ Reject", key=f"{kp}_reject", use_container_width=True):
st.session_state["verdicts"][bid][idx]["review_status"] = "rejected"
audit.log("human_review_action", actor="officer",
action_taken="rejected", **common)
st.rerun()