Gessa Docs
Recipes

Recipe

World build document authoring compile apply loop

Any intent with more than one part: a floor plus walls, a batch of pickups, a lit and framed scene. Do not open with a string of one entity per call writes. Express the whole structural intent as ONE document and land it in ONE decisive call. This is the primary authoring write path; the per mutation create/update tools are the precision and repair tier described at the end.
engine v1.0.234since world-build-operation-catalog.v1, world-build-semantic-compiler.v1, action-catalog.v1.0.232Copy for LLM

Use this for

any multi part authoring intent; creating many entities at once as one atomic undoable transaction; the catalog then compile then apply loop; the decisive one document write path

Not for

a single targeted edit to one existing entity or field (use the precision tools); creating the game or the world itself (see blank-game-quickstart)

Pairs with: Blank game quickstart cold start recipe empty project, Game loop assembly entities scripts HUD win shippable loop, Playtest verification loop proving gameplay executed evidence, Collectibles pickups scoring and win condition

Authoring with the world build document compile and apply loop

When to use

On a blank game whose user asked for a playable genre, do NOT rebuild a player, camera, or controller here first: start from a certified starter template (see blank-game-quickstart, template plus delta), then use this document to author only the delta on top of it.

The three tools

  • world_build_get_operation_catalog returns the high level operation catalog (intent level operation ids, not raw component payloads). Read it once so you author with catalog operations instead of endpoint shaped payloads.
  • world_build_compile_semantic_operations is the DRY RUN twin: it validates the document and returns diagnostics and the lowered operations without writing.
  • world_build_apply_semantic_operations is the WRITE twin: it compiles through the SAME validator, then lands the result as one atomic, idempotent, undoable transaction. A replay of the same document is a no op.

The loop

  1. Ensure a target world exists (a blank game ships a start world). Name it with context.world_id OR context.world_key (either coordinate resolves); a single-world game needs neither - apply binds the only world. Apply does NOT create the game or world.
  2. Read the operation catalog once with world_build_get_operation_catalog.
  3. Write the whole intent as one operations array. Each operation is { "operationId": <catalog id>, "payload": { ... } }.
  4. If you are confident, call world_build_apply_semantic_operations directly. If you are uncertain, call world_build_compile_semantic_operations first, read the diagnostics, fix the document, then apply.
  5. Read the result: createdEntityCount, createdKeys, revision, and the compiler diagnostics. Then verify by playing (see playtest-verification-loop).

What apply lands (the seam)

Apply lands, in ONE atomic idempotent commit: lowered project.entity.create (entities into the target world, honoring EXPLICIT per-item key and tags - required exact keys are spec, write them on the items), project.component.create and project.component.update, and - as receipted post-commit stages under the same idempotency umbrella - script.semantic_patch.apply (creates the script shell if missing, fills version and fingerprint from its own read, patches, then attaches the ScriptComponent to every entity named in the cluster's entityKeys), typed_state.store.create (resolve-or-replay), and ui.hud.bind/HUD recipes. EVERY lane is wired: the whole playable game - bodies, behavior loop, per-entity script attachments, typed-state store, HUD - lands in ONE document. gameplay.collectible_cluster.create is the loop carrier: give it tag, entityKeys, scriptKey, score, victory and it composes the touch-pickup trigger loop, attaches the script to every listed collectible, completes a static trigger collider on every collectible body this same document creates (an item that declares its own collider wins; do NOT add RigidBody to a static sensor), and auto-creates the referenced store. prefab.create defines a named reusable entity subtree (components + scripts per entity) that scripts spawn with spawnEntityFromTemplate prefabKey; the default gameplay loop's projectile prefab is compiler-ensured, and an explicitly named prefab is yours to declare (same document or precision tool). Package and proof operations are compile-visible but never applied here (proofs run via world_playtest_scenario).

Worked example: the arena shell in one document

A blank game already has a start world; read its id from project_get_graph_snapshot. Then apply the shell (floor, four walls, a ring of coin bodies, camera, sky) as ONE transaction with real operation ids:

Text
world_build_apply_semantic_operations({
  game_id: <gameId>,
  context: { world_id: <worldId> },
  operations: [
    { operationId: "entity.role_batch.create", payload: { items: [
      { name: "Arena Floor", primitive: "box", position: {x:0,y:0,z:0},   scale: {x:20,y:1,z:20}, role: "boundary", materialTint: "#3f3f46" },
      { name: "Wall North",  primitive: "box", position: {x:0,y:1,z:-10}, scale: {x:20,y:2,z:1},  role: "boundary" },
      { name: "Wall South",  primitive: "box", position: {x:0,y:1,z:10},  scale: {x:20,y:2,z:1},  role: "boundary" }
      /* Wall East, Wall West ... */
    ] } },
    { operationId: "entity.primitive_batch.create", payload: { items: [
      { key: "arena_coin_1", name: "Coin 1", tags: ["coin"], primitive: "sphere", position: {x:6,y:1.2,z:0},    scale: {x:0.6,y:0.6,z:0.6}, materialTint: "#facc15" },
      { key: "arena_coin_2", name: "Coin 2", tags: ["coin"], primitive: "sphere", position: {x:4.24,y:1.2,z:4.24}, scale: {x:0.6,y:0.6,z:0.6}, materialTint: "#facc15" }
      /* arena_coin_3..8 around a radius 6 ring ... */
    ] } },
    { operationId: "gameplay.collectible_cluster.create", payload: {
      tag: "coin", clusterKey: "arena_coins", scriptKey: "script.arena.coin_pickup",
      entityKeys: ["arena_coin_1", "arena_coin_2" /* ..._8 */], removeOnPickup: true,
      score: { field: "score", increment: 1 },
      victory: { message: "All coins collected!" } } },
    { operationId: "ui.hud_recipe.apply",             payload: { panelKey: "arena_hud_score", name: "Score HUD" } },
    { operationId: "camera.hero_frame.set",           payload: { position: {x:0,y:14,z:16} } },
    { operationId: "environment.sky_atmosphere.apply", payload: {} }
  ]
})

The cluster operation composes the whole gameplay loop: an onTriggerEnter handler that despawns the touched collectible and increments the score, an onTick handler that re-scans the tag, writes the won flag, and declares the win condition, a HUD wire when the document carries a panel, the ScriptComponent attached to every entity in entityKeys, a static TRIGGER COLLIDER completed onto every collectible body created in the same document (no RigidBody - a static sensor plus the KCC player is the proven trigger pair), and the referenced typed-state store auto-created. Explicit item keys make required exact keys land exactly.

One call, one commit, one undo unit. entity.primitive_batch.create and entity.role_batch.create each fan a payload.items array (max 32 per batch) out to one entity per item; the compiler owns the TransformComponent, RenderableComponent, and material defaults. Apply returns the created keys.

Compile diagnostics repair loop

When a document is rejected, world_build_apply_semantic_operations returns { ok: false, stage, code, message, diagnostics } and writes NOTHING. Common stages: compile (a payload the validator refused), budget (the document lowers to more than the apply cap; split it), owner (a post-commit stage failed or is owner_unavailable - the graph part COMMITTED and the result names what landed; finish the unavailable lane with its precision tool), apply (a transaction conflict). Read diagnostics, edit the one offending operation, and re apply. Prefer world_build_compile_semantic_operations to inspect diagnostics without a write when you are iterating.

The precision tier (per mutation is the repair tool, not the default)

The document carries the WHOLE game: bodies with exact keys and tags, the behavior loop with per-entity attachments (the cluster operation), the typed-state store, and the HUD. Do not follow a document with a string of project_add_component / project_create_ui_panel / project_create_data_store calls to "finish" it - the document already landed those lanes. Reach for a single project_create_entity, project_add_component, or a field update only to REPAIR or precisely target ONE entity after verification. The document is the write path; the per mutation call is the scalpel.

Verify

  • project_get_graph_snapshot to confirm the created entities and the new revision landed.
  • world_playtest_scenario to PLAY the result (see playtest-verification-loop): an after state that is identical to the before state is not proof of gameplay.
Was this helpful?Report an issueContact support

On this page