at least one hero exists, the hero's health is above 100) — and the
engine evaluates it against the live world. Probe advances the simulation and checks assertions in
one call; a manifest links a build’s features to the assertions that define “done,” so the build
grades itself. This page writes a contract for a world and grades it end to end; every command is real
and runnable against a local server, with output captured from one.
Write and evaluate an expectation
Spawn two units to assert over, then create two assertions. An assertion is aname, a condition,
and an optional severity (error / warning / info, default error). The condition is a
shorthand string with sibling parameters (filter, min, field, op, value, …).
entity_id:3, 4). Evaluate them all against the live world:
message explaining why it passed or failed. The result is also
cached on the assertion (read it back later with GET /assert/results, without re-running).
There are 10 condition kinds and 5 filter kinds:
Filters are
any, team:N, role:NAME, tag:NAME, and component:NAME; join several with +
for AND (team:1+role:hero).
Probe — advance and check in one call
probe runs the simulation forward ticks steps, then evaluates assertions — atomically, in one
request. It answers “if I run 30 ticks, do these still hold?” Pass assertions to check only named
ones.
probe runs on the real world and advances it — it is not a rollback. To check a hypothetical and
then discard it, probe a fork instead (POST /fork/{id}/probe).
Grade a build with a manifest
A manifest describes what the build is — aname, genre, description, and a list of features.
Each feature links to the assertion names that define “done” for it. Here, combat links to the two
assertions we already evaluated (cached as passing); economy links to one that doesn’t exist yet.
combat reads as verified even though it was declared inprogress — when every linked assertion
has a passing result, the manifest upgrades the effective status. economy stays planned: its
assertion was never created, so it reads not_evaluated and doesn’t count. completion_pct is verified
features ÷ total — here, 1 of 2 = 50%.
Behavior and gotchas
The things you only find out by running it:probemutates the real world; it does not roll back. “Atomic” means step-and-evaluate in one call, not a safe peek. Thebefore_snapshot/after_snapshotflags capture summaries but don’t restore state. To check-then-discard, probe a fork.- Assertions are entities, and
anycounts them. Creating an assertion spawns an entity, so anentity-countwithfilter:"any"includes your assertions in the total. Filter byrole,team, orcomponentto count only gameplay entities. entity:Nis not a valid assertion filter — it silently becomesany. A bad filter string doesn’t error; it falls back to “match everything.” Createentity-countwithfilter:"entity:1"and it returnsCount 6(every entity, assertions included), notCount 1. Use the five real filter kinds. (Per-entity targeting by id is a rule filter, not an assertion filter.)- Manifest
statusis lowercase, no underscore —inprogress, notin_progress. Postingin_progressreturns{"ok":false,"error":"Invalid manifest: unknown variant \in_progress`, expected one of `planned`, `inprogress`, `complete`, `verified`“}. (POST /manifest/feature*does* acceptin_progress; onlyPOST /manifest` is strict — name them deliberately.) - The manifest grades against cached results. A feature reads
verifiedonly after its assertions have been evaluated (via/assert/evaluateor/probe). Until then they’renot_evaluatedand the feature can’t pass.
Endpoints
Status
- Shipped — typed assertions (10 condition kinds, 5 filter kinds), evaluation, cached results, probe (including on forks), and a feature manifest with completion tracking. All headless.
- Caveat — probe advances the real world; it does not roll back. To check then discard, probe a fork instead.
Assertion & manifest endpoints
Assertion, probe, and manifest endpoints with request and response schemas.