// GET /cms/admin/workflow/runs/:id — one run's overall + per-step status, read // straight from the platform via workflow::run_status (F-038). Replaces the // former app-side `wfruns` KV tracking — the SDK is app-scoped, so a run from // another app resolves to () (404) here. import "auth" as auth; let g = auth::guard(ctx, ["admin", "author"]); if !g.ok { return g.response; } let run_id = ctx.request.params.id; let st = workflow::run_status(run_id); if st == () { return #{ statusCode: 404, body: #{ error: "no such run" } }; } let engine = st.status; // pending|running|succeeded|failed let terminal = engine == "succeeded" || engine == "failed"; // Normalize per-step status for the UI. A DAG step absent from the run — its // `when` gate was false — shows as skipped once the run is terminal, else // pending; the engine's "ready" (queued) also maps to pending. let steps = #{}; for name in ["validate", "enrich", "seo", "publish", "finalize"] { let s = st.steps[name]; if s == () { s = if terminal { "skipped" } else { "pending" }; } else if s == "ready" { s = "pending"; } steps[name] = #{ status: s }; } // CMS-level overall: "blocked" when the gate stopped publish, else mirror the // engine's terminal state (skip != fail, so the engine itself reports // "succeeded" even when publish was gated out — F-039). let overall_status = if !terminal { "running" } else if steps.publish.status == "succeeded" { "completed" } else { "blocked" }; #{ statusCode: 200, body: #{ run_id: run_id, overall: #{ status: overall_status }, steps: steps } }