"""Page 1: Pipeline Operations — "Is the machine running?"
Renders: queue depth, throughput, error rate, stage flow, breakers,
funnel, rejection reasons, fix cycle, time-series charts.
All data comes from existing endpoints: /api/metrics, /api/snapshots,
/api/stage-times, /api/alerts, /api/fix-rates.
"""
import json
from datetime import datetime, timezone
from shared_ui import render_page
def render_ops_page(metrics: dict, snapshots: list, changes: list,
vital_signs: dict, now: datetime) -> str:
"""Render the Pipeline Operations page."""
# --- Prepare chart data ---
timestamps = [s["ts"] for s in snapshots]
throughput_data = [s.get("throughput_1h", 0) for s in snapshots]
approval_data = [(s.get("approval_rate") or 0) * 100 for s in snapshots]
open_prs_data = [s.get("open_prs", 0) for s in snapshots]
merged_data = [s.get("merged_total", 0) for s in snapshots]
rej_wiki = [s.get("rejection_broken_wiki_links", 0) for s in snapshots]
rej_schema = [s.get("rejection_frontmatter_schema", 0) for s in snapshots]
rej_dup = [s.get("rejection_near_duplicate", 0) for s in snapshots]
rej_conf = [s.get("rejection_confidence", 0) for s in snapshots]
rej_other = [s.get("rejection_other", 0) for s in snapshots]
# origin_agent/origin_human removed — replaced by /api/growth chart
annotations_js = json.dumps([
{
"type": "line", "xMin": c["ts"], "xMax": c["ts"],
"borderColor": "#d29922" if c["type"] == "prompt" else "#58a6ff",
"borderWidth": 1, "borderDash": [4, 4],
"label": {"display": True, "content": f"{c['type']}: {c.get('to', '?')}",
"position": "start", "backgroundColor": "#161b22",
"color": "#8b949e", "font": {"size": 10}},
}
for c in changes
])
# --- Status helpers ---
sm = metrics["status_map"]
ar = metrics["approval_rate"]
ar_color = "green" if ar > 0.5 else ("yellow" if ar > 0.2 else "red")
fr_color = "green" if metrics["fix_rate"] > 0.3 else ("yellow" if metrics["fix_rate"] > 0.1 else "red")
vs_review = vital_signs["review_throughput"]
vs_status_color = {"healthy": "green", "warning": "yellow", "critical": "red"}.get(vs_review["status"], "yellow")
# --- Rejection reasons table ---
reason_rows = "".join(
f'
{r["tag"]} | {r["unique_prs"]} | '
f'{r["count"]} |
'
for r in metrics["rejection_reasons"]
)
# --- Breaker rows ---
breaker_rows = ""
for name, info in metrics["breakers"].items():
state = info["state"]
color = "green" if state == "closed" else ("red" if state == "open" else "yellow")
age = f'{info.get("age_s", "?")}s ago' if "age_s" in info else "-"
breaker_rows += f'| {name} | {state} | {info["failures"]} | {age} |
'
# --- Funnel ---
funnel = vital_signs["funnel"]
# --- Queue staleness ---
qs = vital_signs.get("queue_staleness", {})
stale_count = qs.get("stale_count", 0)
stale_status = qs.get("status", "healthy")
stale_color = {"healthy": "green", "warning": "yellow", "critical": "red"}.get(stale_status, "")
body = f"""
Throughput
{metrics["throughput_1h"]}/hr
merged last hour
Approval Rate (24h)
{ar:.1%}
{metrics["approved_24h"]}/{metrics["evaluated_24h"]} evaluated
Review Backlog
{vs_review["backlog"]}
{vs_review["open_prs"]} open + {vs_review["reviewing_prs"]} reviewing + {vs_review["approved_waiting"]} approved
Merged Total
{sm.get("merged", 0)}
{sm.get("closed", 0)} closed
Fix Success
{metrics["fix_rate"]:.1%}
{metrics["fix_succeeded"]}/{metrics["fix_attempted"]} fixed
Time to Merge
{f"{metrics['median_ttm_minutes']:.0f}" if metrics["median_ttm_minutes"] else "—"}min
median (24h)
Pipeline Funnel
{funnel["sources_total"]}
Sources
→
{funnel["sources_queued"]}
In Queue
→
{funnel["sources_extracted"]}
Extracted
→
{funnel["prs_total"]}
PRs Created
→
{funnel["prs_merged"]}
Merged
→
{funnel["conversion_rate"]:.1%}
Conversion
Queue staleness: {stale_count} stale
{f'(oldest: {qs.get("oldest_age_days", "?")}d)' if stale_count > 0 else ""}
Throughput & Approval Rate
Rejection Reasons Over Time
PR Backlog
Cumulative Growth
Top Rejection Reasons (24h)
| Issue | PRs | Events |
{reason_rows if reason_rows else "| No rejections in 24h |
"}
Circuit Breakers
| Stage | State | Failures | Last Success |
{breaker_rows if breaker_rows else "| No breaker data |
"}
"""
scripts = f""""""
return render_page(
title="Pipeline Operations",
subtitle="Is the machine running?",
active_path="/ops",
body_html=body,
scripts=scripts,
timestamp=now.strftime("%Y-%m-%d %H:%M UTC"),
)