The local FastAPI operations dashboard — a workflow runner with per-feature scope, persisted run history, workflow chaining, and live SSE log streaming

Failure modes

Symptom Cause Fix Severity
RuntimeWarning: coroutine 'RunnerService.start' was never awaited start() called without await It's async — await it / asyncio.run high
Workflows won't run from the UI Config.allow_run is False (e.g. --read-only) Start without --read-only high
RunnerBusyError on start A run is already active (one at a time) Wait for / inspect runner.current medium
TypeError calling config.runs_dir() runs_dir is a property Drop the () medium
Cost panel shows an error fetch_summary returned a CostFetchError (no admin key, network) Inspect the error kind/message; cost is an adjacent surface low

Risk areas

Diagnosis order

  1. Confirm the app builds: create_app(build_config(Path("."))).
  2. Confirm runs are allowed: config.allow_run (and no --read-only).
  3. For a run that won't start: check runner.current / RunnerBusyError.
  4. For async warnings: await start() / iterate subscribe().
  5. For a data panel: that data is owned by its feature (telemetry / help-system / cost).