Running and testing a project
The run-&-test tools embed TurboWarp's scratch-vm
(the fork with a JIT compiler) directly in the server process — no browser, no
WebGL. The loop is: edit (scratch4js) → vm_load → vm_green_flag → vm_run →
read vm_state → assert.
This returns structured state (score = 42, Cat at (120, -30), said "You win!")
rather than pixels, which is far easier for an agent to assert against and is
deterministic and CI-friendly. The headless VM has no renderer or audio engine:
costume metadata still loads (so switching costumes by name/number works), but a
few renderer-backed blocks (touching colour/sprite/edge, pen) and sound playback
are inert. When you need to see the real rendered stage, run the project in
TurboWarp Desktop and call screenshot — that uses the editor's real renderer
(see Live reload).
Events
Notable events — say/think, broadcast, greenflag, stop,
question/answer and runtime/compile errors, each { level, type, message, …fields } — are surfaced two ways:
- In
vm_run's result (events): the ordered timeline since the previousvm_run. This is the agent-facing channel — the model reads it straight from the tool result and can assert on sequence, not just final state. Always on. - As MCP log notifications (
notifications/message,logger: "scratch-vm"): the client/human-facing channel for a host's log view. Off until the client raises its level vialogging/setLevel—"info"for activity,"debug"to also include run boundaries and bubble-clears,"warning"+ for errors only. Most clients don't feed notifications back to the model, which is why thevm_runchannel exists.
Repeated identical say/think bubbles are de-duplicated, so a say inside a
loop doesn't flood either channel.