---
title: "How-To: Publish and Play"
description: "Task recipe for publishing a world, entering Play, and handling reconnect and reload, trusting backend receipts, not the client."
engineVersion: v1.0.234
date: 2026-09-28
license: "(c) Gessa, proprietary. Cite with attribution to https://gessa.ai/docs/. Terms: https://gessa.ai/terms/."
canonical: https://gessa.ai/docs/how-to/publish-and-play/
---

# How-To: Publish and Play

Publish a world, enter **Play**, and handle the normal lifecycle: reconnecting after a dropped session and reloading after an edit. The thread running through every step is that the **frontend is a non-authoritative projection**, the runtime owns the session, and the client re-derives from authoritative state. You trust the backend receipt, never the client's local picture.

This page describes the canonical publish-and-Play flow for v1. The engine is **pre-launch**: its readiness rows are all unaccepted, and "publishable" or "playable" is a contract model here, not a guarantee that a given world runs end-to-end today. Status tracks the [v1 readiness ledger](../../../cycles/v1-engine-readiness-loop/FEATURE_LEDGER.json).

## Publishing is gated, not automatic

Publishing promotes a project graph to a **deployment** that a Play session can run against. It is not a copy step, it passes a gate first. The relevant surfaces:

- **Script publish gate.** `script_publish_gate` runs the script publish-gate checks for a game and surfaces blockers *before* a deployment is created. Run it first; a script blocker should stop the publish, not the Play session.
- **Create the deployment.** `runtime_create_deployment` publishes a project graph as a deployment (action surfaces include `deployment.redeploy` to redeploy a content version and `deployment.rollback` to revert). These are `mcp:admin` / `publish`-domain operations: they are deliberately not in the everyday `mcp:write` set.
- **Open a room.** `runtime_create_room` creates a Runtime room for a deployment; a Play session connects to that room.

{% warning severity="caution" title="Publishing does not by itself make a world playable" %}
Promoting state and passing the script gate is necessary, not sufficient. A scene that renders is not a game. Playability is a separate, runtime-proved property (camera, spawn, possession under a live session) and it is gated by the proof registry, not by a successful publish. See [Reference: Runtime Playability](../reference/runtime-playability.md).
{% /warning %}

## The publish-and-Play recipe

{% recipe id="publish-and-play" goal="Publish a world, enter Play, and survive reconnect and reload" audience="both" %}

1. **Run the publish gate.** Call `script_publish_gate` for the game. Resolve any reported blockers before continuing: the gate exists to catch them before deployment, not after.
2. **Publish a deployment.** Promote the project graph with `runtime_create_deployment` (action domain `publish`). This produces the authoritative, version-pinned content a Play session runs against.
3. **Enter Play.** Open a Runtime room (`runtime_create_room`) and connect. The runtime drives the session; the client renders a projection of authoritative state. It does not simulate independently.
4. **Reconnect on drop.** If the session drops, the client re-establishes the connection and re-syncs to the authoritative snapshot: it does **not** invent state to fill the gap. After reconnect, the client's view is whatever the snapshot says, not whatever it last believed.
5. **Reload after an edit.** After authoring a change (a component edit, a script patch), reload the Play session so it runs against the latest published state. A live edit is not silently mixed into a running session; you re-derive from the new published content.

{% /recipe %}

## The frontend is non-authoritative, trust the receipt

None of these steps let the client become a second source of truth. Publish, Play, reconnect, and reload all re-derive from backend authority:

- **Publish** promotes *authoritative* state; the client does not "own" the published version.
- **Play** is runtime-driven; the client renders a projection.
- **Reconnect** re-syncs to the authoritative snapshot rather than reconstructing from local memory.
- **Reload** re-projects from the latest published content.

{% ai-context audience="mcp" priority="must" %}
Treat publish and deployment results as receipts from the authority, not as confirmation of your local intent. Run `script_publish_gate` before `runtime_create_deployment`. After reconnect or reload, read current state from the runtime rather than assuming your last-sent change is live. Never narrate the client's local view as ground truth.
{% /ai-context %}

This is the same backend-authority discipline that governs editing, see [Explanation: Backend Authority](../explanation/backend-authority.md). The runtime, the publish gate, and the deployment lifecycle are owned by the server runtime modules (`server/src/modules/runtime`); there is no single generator for runtime playability, so its source of truth is those modules plus the readiness registries.

## What "playable" formally means

In v1, a world is **playable** only when runtime evidence holds under a live session, and that evidence is recorded as a proof, not asserted in prose. The minimum runtime proof is **camera, spawn, and possession** under a live session, runnable via the `runtime.proof.run` action.

{% proof class="runtime" registry="docs/cycles/v1-engine-readiness-loop/PROOF_REGISTRY.json" status="planned" %}
A playability claim requires runtime-driven camera, controlled-entity spawn, and possession (input bound to the controlled entity) demonstrated under a live session, backed by a registry receipt. A markdown description is not proof. Today every v1 readiness-ledger row is unaccepted, so this is a contract model, not a guarantee.
{% /proof %}

The readiness registries are the source of truth for what is proven: [`FEATURE_LEDGER.json`](../../../cycles/v1-engine-readiness-loop/FEATURE_LEDGER.json), `PROOF_REGISTRY.json`, and the others under [`docs/cycles/v1-engine-readiness-loop/`](../../../cycles/v1-engine-readiness-loop/).

## Related

- [Reference: Runtime Playability](../reference/runtime-playability.md): the playability criteria and the registries that gate them.
- [Explanation: Playability Proofs](../explanation/playability-proofs.md): why proof, not prose, decides "playable".
- [Explanation: Backend Authority](../explanation/backend-authority.md): why reconnect and reload re-derive from authority.
- [How-To: Use MCP Tools](use-mcp-tools.md): the deployment and room tools used above.

Status: this page documents the canonical publish-and-Play flow for v1. The engine is pre-launch; "publishable" and "playable" are contract models whose end-to-end runnable status tracks the [v1 readiness ledger](../../../cycles/v1-engine-readiness-loop/FEATURE_LEDGER.json).
