""" delivery.decisions.render — render a DecisionQueue to Markdown / HTML. Triage-focused: the table foregrounds urgency / status / owner so an operations owner can scan the queue and decide what to pick up next. """ from __future__ import annotations from ..evidence.render import _esc, _fmt_pct, _fmt_score from .queue import STATUS_ORDER, DecisionQueue, DecisionQueueItem def _status_summary_line(queue: DecisionQueue) -> str: parts = [f"{queue.status_counts.get(s, 0)} {s}" for s in STATUS_ORDER] return ", ".join(parts) # --- markdown ------------------------------------------------------------- def _filter_phrase(queue: DecisionQueue) -> str: if queue.status_filter is None: return "all statuses" return f"status = {queue.status_filter}" def render_markdown(queue: DecisionQueue) -> str: lines = [ f"# Decision Queue — `{queue.tenant_id}`", "", f"- **Filter:** {_filter_phrase(queue)}", f"- **Counts:** {_status_summary_line(queue)}", f"- **Returned:** {len(queue.items)}", "", ] if not queue.items: lines += [ "No decisions match the current filter.", "", ] return "\n".join(lines).rstrip() + "\n" lines += [ "| Urgency | Status | Entity | Recommendation | Owner | Confidence | Run | Updated |", "|---:|---|---|---|---|---:|---|---|", ] for it in queue.items: lines.append( f"| {_fmt_score(it.urgency)} " f"| {it.status} " f"| `{it.entity_id}` ({it.entity_type}) " f"| {it.recommendation} " f"| {it.owner or '—'} " f"| {_fmt_pct(it.confidence)} " f"| `{it.run_id}` " f"| {it.updated_at or '—'} |" ) lines.append("") return "\n".join(lines).rstrip() + "\n" # --- html ----------------------------------------------------------------- _HTML_HEAD = ( "" "Decision Queue" "" ) _HTML_FOOT = "" def _status_badge(status: str) -> str: cls = status if status in STATUS_ORDER else "open" return f'{_esc(status)}' def _counts_html(queue: DecisionQueue) -> str: spans = [ f"{queue.status_counts.get(s, 0)} {_esc(s)}" for s in STATUS_ORDER ] return '

' + "".join(spans) + "

" def _row_html(it: DecisionQueueItem) -> str: return ( "" f"{_esc(_fmt_score(it.urgency))}" f"{_status_badge(it.status)}" f"{_esc(it.entity_id)} " f'({_esc(it.entity_type)})' f"{_esc(it.recommendation)}" f"{_esc(it.owner or '—')}" f"{_esc(_fmt_pct(it.confidence))}" f"{_esc(it.run_id)}" f"{_esc(it.updated_at or '—')}" "" ) def render_html(queue: DecisionQueue) -> str: parts = [ _HTML_HEAD, f"

Decision Queue — {_esc(queue.tenant_id)}

", '

' f"Filter: {_esc(_filter_phrase(queue))} · " f"returned {len(queue.items)}" "

", _counts_html(queue), ] if not queue.items: parts.append("

No decisions match the current filter.

") else: parts.append( "" "" "" "" "" ) for it in queue.items: parts.append(_row_html(it)) parts.append("
UrgencyStatusEntityRecommendationOwnerConfidenceRunUpdated
") parts.append(_HTML_FOOT) return "".join(parts)