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.statustool — 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.