HomeDeveloper docsConnection kinds: execution and data, a complete graph
Examples by kind 5 min read

Connection kinds: execution and data, a complete graph

Trace a lever graph that reads a state through typed data edges and runs actions through ordered execution edges.

Goal

Activate a lever only when its starting state is off, then show an original message to the triggering participant. The false branch deactivates it. This single document demonstrates both accepted edge.kind values.

These JSON files describe the stored Blueprint v2 subdocument. They are development fixtures, not an installable module, a complete Builder project or a campaign archive. Recreate the nodes in the editor, or use the fixtures in isolated contributor tests. This guide does not assume a JSON import button in the Smart Object editor.

Download the complete example bundle or the validator. Every example uses original synthetic data. The host's internal Python evaluator is for source development; browser modules must use the public SDK.

Recreate the two connection kinds

  1. Create a Lever as in the lever example. Open On interaction.

  2. Add Get property: Current state → Compare state: Deactivated → Check state: Test. These are the data links. Get property and Compare state are pure value nodes.

  3. Connect On interaction → Check state. True → Change state: Activated → Show message, with text “The mechanism is active.” and audience Trigger. False → Change state: Deactivated. These are execution links.

  4. Simulate once from off, then once from on. The first reads values and runs state/message; the second runs only the state action.

edge.kindRequired keys in addition to kindConcrete edge
executionfrom, to, outputstart.next → branch
datafrom, to, output, inputcompare.result → branch.test
json
{
  "kind": "execution",
  "from": "start",
  "to": "branch",
  "output": "next"
}
json
{
  "kind": "data",
  "from": "compare",
  "to": "branch",
  "output": "result",
  "input": "test"
}

Complete JSON

Download execution-data.json

json
{
  "version": 2,
  "kind": "lever",
  "states": {
    "off": {
      "appearance": "inherit"
    },
    "on": {
      "appearance": "inherit"
    }
  },
  "graphs": {
    "interact": {
      "nodes": [
        {
          "id": "start",
          "type": "event",
          "x": 40,
          "y": 80,
          "event": "interact"
        },
        {
          "id": "read",
          "type": "property",
          "x": 300,
          "y": 300,
          "property": "state"
        },
        {
          "id": "compare",
          "type": "compare",
          "x": 560,
          "y": 300,
          "state": "off"
        },
        {
          "id": "branch",
          "type": "condition",
          "x": 560,
          "y": 80,
          "state": "off"
        },
        {
          "id": "on",
          "type": "state",
          "x": 820,
          "y": 40,
          "targetState": "on"
        },
        {
          "id": "message",
          "type": "showMessage",
          "x": 1080,
          "y": 40,
          "audience": {
            "scope": "trigger"
          },
          "text": "The mechanism is active."
        },
        {
          "id": "off",
          "type": "state",
          "x": 820,
          "y": 220,
          "targetState": "off"
        }
      ],
      "edges": [
        {
          "from": "start",
          "to": "branch",
          "output": "next",
          "kind": "execution"
        },
        {
          "from": "branch",
          "to": "on",
          "output": "true",
          "kind": "execution"
        },
        {
          "from": "on",
          "to": "message",
          "output": "next",
          "kind": "execution"
        },
        {
          "from": "branch",
          "to": "off",
          "output": "false",
          "kind": "execution"
        },
        {
          "from": "read",
          "to": "compare",
          "output": "value",
          "kind": "data",
          "input": "value"
        },
        {
          "from": "compare",
          "to": "branch",
          "output": "result",
          "kind": "data",
          "input": "test"
        }
      ]
    }
  }
}

Expected result

From off, the exact trace is start → branch → read → compare → on → message. A pure value is evaluated when the executing condition needs it, so the trace lists branch before the values it reads. The actions are state:on and showMessage. From on, the trace ends with off and the only action is state:off.

Run the fixture in a development installation

Extract the example bundle to data/blueprint-examples inside a disposable checkout of the documented host. From the checkout root, run:

sh
uv run --locked python data/blueprint-examples/check-examples.py --host .

The checker configures an in-memory database, blocks database queries and calls the real clean_blueprint and evaluate_graph functions. It validates all four object kinds, both connection kinds and all 44 node types, including requestRoll and setQuestStatus. It checks both roll visibilities, all six quest statuses and continuing execution without drawing dice or changing journals. This verifies document shape and predicted actions. Test behavior is still needed to check real targets, authorization and the complete server chain.

python
import json
from pathlib import Path
from gravewright.maps.blueprints import clean_blueprint, evaluate_graph

raw = json.loads(Path("data/blueprint-examples/execution-data.json").read_text(encoding="utf-8"))
blueprint = clean_blueprint(raw, asset_ids=set(), light_ids=set(), track_ids=set())
result = evaluate_graph(blueprint, "interact", "off")
print(result["trace"])
print(result["actions"])
assert result["trace"] == ["start", "branch", "read", "compare", "on", "message"]
assert [a["type"] for a in result["actions"]] == ["state", "showMessage"]

Ordering and rejected connections

  • Execution fan-out follows authored edge order depth-first. A sequence uses then1, then2, then3, then4 in that order. A shared descendant executes once per event.

  • Pure value nodes have no execution ports. An execution link to read, or from read.next, fails validation.

  • A data input has one source. Two sources for branch.test fail validation; one value output may feed compatible inputs.

  • State, boolean, number, text, element and resource references are typed. Compare state emits result:boolean; connect it to Test, not a state-valued input.

  • The saved Element reference output is still named door and has type element. This is compatible with non-door element references; do not rename the serialized port.

  • All connections, including disconnected draft branches, must be acyclic. Use named signals/timers through their supported runtime instead of a cable loop.

Test as GM and player

Run Simulate to inspect one local event. Then use Test behavior to rehearse through the server; its changes are rolled back. Generate or update the scene as GM, then test a synthetic scene with a GM and an authorized player. Verify that a streamer cannot write. After editing the project again, use Update scene before expecting different live behavior.

On the first player interaction, the message audience is trigger. A second player must not receive a private trigger message merely because they share the scene. Check Automation as GM: values, Boolean decision and action order must match the simulation. A paused scene must execute no blueprint actions.

Common failures

A visible node without an execution path does not run. A data cable does not start an action. A correct simulation does not prove that a live target exists or that a player can modify it. When comparing the state after an earlier action in this event, remember that the property reads the starting snapshot.

How to use AI to add a typed input

text
Extend execution-data.json for Gravewright 0.3.1 by adding a second Boolean requirement from getVariable(scope=element, name=ready, valueType=boolean, default=true). Combine it with the existing compare result through all inputs a/b. Inspect data_inputs/data_outputs and the real field validators. Keep pure nodes off execution cables, preserve one source per input and show the complete JSON plus off/on and ready true/false traces. Do not claim data edges execute actions.

All object kinds · All 44 node examples