diff --git a/crates/miyabi-cli/src/main.rs b/crates/miyabi-cli/src/main.rs index bb849dc..132ecf5 100644 --- a/crates/miyabi-cli/src/main.rs +++ b/crates/miyabi-cli/src/main.rs @@ -2128,6 +2128,10 @@ const POLARIS_DASHBOARD_HTML: &str = r##"

Loading...

+
+

Completion Stats

+
Loading stats...
+

Tasks

@@ -2254,6 +2258,27 @@ const POLARIS_DASHBOARD_HTML: &str = r##" } } + function renderStats(snapshot) { + const tasks = Array.isArray(snapshot.tasks) ? snapshot.tasks : []; + if (tasks.length === 0) { + document.getElementById("stats").innerHTML = 'No tasks'; + return; + } + const done = tasks.filter(t => t.current_state === "done" || t.current_state === "merged").length; + const active = tasks.filter(t => t.current_state === "implementing" || t.current_state === "reviewing").length; + const pending = tasks.filter(t => t.current_state === "pending" || t.current_state === "draft" || t.current_state === "blocked").length; + const total = tasks.length; + const pct = total > 0 ? Math.round(done / total * 100) : 0; + + const bar = '
' + + '
'; + + document.getElementById("stats").innerHTML = + '
' + pct + '%
' + + '
completed
' + bar + + '
' + done + ' done / ' + active + ' active / ' + pending + ' pending / ' + total + ' total
'; + } + async function refresh() { try { const [statusRes, locksRes, dagRes] = await Promise.all([ @@ -2272,6 +2297,7 @@ const POLARIS_DASHBOARD_HTML: &str = r##" dagRes.json() ]); + renderStats(status); renderTasks(status); renderLocks(locks); renderDag(dag); @@ -2281,6 +2307,7 @@ const POLARIS_DASHBOARD_HTML: &str = r##" " | auto-refresh every 3s"; } catch (error) { document.getElementById("meta").textContent = "Refresh failed: " + error.message; + document.getElementById("stats").innerHTML = 'Failed to load'; setEmpty("tasks", "Failed to load tasks"); setEmpty("dag", "Failed to load DAG"); setEmpty("locks", "Failed to load locks");