Sverka
Running

Run queries

> **Work in progress.** Run queries are implemented in the native engine. > APIs may change.

Work in progress. Run queries are implemented in the native engine. APIs may change.

A read-only query of a run's current state: which steps are pending, running, succeeded, failed, and the overall run status. The engine tracks this state internally; the query surfaces a point-in-time snapshot without consuming the RunEvent stream.

When to use queries

  • MCP server run.status tool — report run progress to an AI agent.
  • Dashboards — poll run state without subscribing to the event stream.

Querying a run

import { createEngine } from "@sverka/runtime";
import type {
  RuntimeDriver,
  ShellExecuteRequest,
  ShellResult,
} from "@sverka/runtime";
import { join } from "node:path";
import { tmpdir } from "node:os";

const testDir = join(tmpdir(), "sverka-test");

const driver: RuntimeDriver = {
  name: "shell",
  canExecute: () => true,
  executeShell: async (req: ShellExecuteRequest): Promise<ShellResult> => ({
    exitCode: 0,
    stdout: "",
    stderr: "",
    durationMs: 1,
    timedOut: false,
  }),
};
const engine = createEngine({ drivers: [driver] });

// `plan` is a RunPlan — obtain it by binding a DefinitionGraph:
//   const graph = synthesize(project);
//   const plan = bindRunPlan({ graph, entryId: "ci/on-push" });
// See the Workflow API docs for full details.
// (Snippet is illustrative — replace `plan` with a real RunPlan before running.)
const plan = {} as never; // placeholder — not a valid RunPlan

const iter = engine.run({
  plan,
  workspace: "./ws",
  artifactDir: join(testDir, "art"),
});
for await (const event of iter) {
  if (event.type === "run-started") {
    // Query is available immediately after run-started
    const state = engine.query();
    console.log(state);
    // {
    //   runId: "run-123",
    //   planId: "rp-abc",
    //   status: "running",
    //   startedAt: 1725379200000,
    //   steps: [
    //     { stepId: "ci/lint", state: "pending" },
    //     { stepId: "ci/build", state: "pending" },
    //   ]
    // }
  }
  if (event.type === "step-succeeded") {
    const state = engine.query();
    const step = state?.steps.find((s) => s.stepId === event.stepId);
    console.log(`${step?.stepId}: ${step?.state} (${step?.durationMs}ms)`);
  }
}

RunState model

interface RunState {
  runId: string;
  planId: string;
  status: "running" | "success" | "failure" | "cancelled" | "suspended";
  startedAt: number;
  steps: Array<{
    stepId: string;
    state:
      | "pending"
      | "ready"
      | "running"
      | "succeeded"
      | "failed"
      | "cancelled"
      | "skipped";
    durationMs?: number;
  }>;
}

"running" is the non-terminal status surfaced only by query — it is not part of RunStatus (which is terminal-only).

Limitations (v1)

  • Read-only. Queries snapshot the current state; they do not affect execution.
  • Signals (write side) are deferred. Engine.signal(name, payload) is not in v1. Suspend/resume + cancel cover the write side.
  • No CI equivalent yet. Compiled workflows lower steps to target-native constructs (jobs, includes, trigger jobs); suspend/resume is not lowered.

On this page