---
title: "Script Semantic Patch"
description: "Sources: `packages/script-semantic-patch/src/index.ts`."
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/spec/generated/script-semantic-patch/
---
<!-- GENERATED FILE: do not edit by hand. -->
<!-- Regenerate with `npm run gen-docs`. -->

Sources: `packages/script-semantic-patch/src/index.ts`.

# Script Semantic Patch

This generated snapshot is derived from `packages/script-semantic-patch`. Semantic patches are creator-facing edit operations; the backend compiler projects them into canonical Script IR and the normal Project Graph script update path persists the result.

Compiler version: `script-semantic-patch.v1`.
Compiler hash: `sha256:65836246e1f866e143e19eb54fdbf665d3f265465d5131da09e5a3ba56fa121d`.
Operation catalog version: `script-semantic-patch-ops.v1`.
Operation catalog hash: `sha256:2658160596d67879eb955963e315d6991009b714c80597bfeb8b74dd8ae07d7f`.
Operation count: `44`.

## Operations

| Operation | Title | Description | Mutates | Contexts | Effect tags | Undo |
| --- | --- | --- | --- | --- | --- | --- |
| `addHandler` | Add Handler | Create an event handler and its event root node. | `handlers`<br>`events` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | direct |
| `removeHandler` | Remove Handler | Remove an event handler by id or event. | `handlers`<br>`events` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | receipt-data |
| `addVariable` | Add Variable | Create a first-class Script IR variable. | `variables` | `visual_editor`<br>`raw_graph_import`<br>`test` | `writeState` | receipt-data |
| `renameVariable` | Rename Variable | Rename a variable while preserving its stable id. | `variables` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | direct |
| `setVariableDefault` | Set Variable Default | Set a variable default value. | `variables` | `visual_editor`<br>`raw_graph_import`<br>`test` | `writeState` | direct |
| `addNode` | Add Node | Insert a graph node in a handler or function scope. | `nodes` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | direct |
| `removeNode` | Remove Node | Remove a node and its incident edges. | `nodes`<br>`execEdges`<br>`dataEdges` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | receipt-data |
| `removeVariable` | Remove Variable | Remove a first-class Script IR variable by id or name. | `variables` | `visual_editor`<br>`raw_graph_import`<br>`test` | `writeState` | receipt-data |
| `removeFunction` | Remove Function | Remove a same-script function graph resource by id or name. | `functions` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | receipt-data |
| `disconnect` | Disconnect | Remove an execution or data edge by id. | `execEdges`<br>`dataEdges` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | receipt-data |
| `clearInlineValue` | Clear Inline Value | Clear an inline literal value on a graph node input. | `nodes.inlineValues` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | receipt-data |
| `connectExec` | Connect Exec | Add an execution edge between two nodes. | `execEdges` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | direct |
| `connectData` | Connect Data | Add a data edge between two nodes. | `dataEdges` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | direct |
| `setInlineValue` | Set Inline Value | Set an inline literal value on a graph node input. | `nodes.inlineValues` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | direct |
| `addHostOperation` | Add Host Operation | Insert a host.call node from the canonical node catalog. | `nodes` | `visual_editor`<br>`raw_graph_import`<br>`test` | `requiresAuthority` | direct |
| `addCustomEvent` | Add Custom Event | Declare a custom event contract. | `customEvents` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | receipt-data |
| `dispatchCustomEvent` | Dispatch Custom Event | Insert an event.dispatch node backed by a custom event declaration. | `nodes` | `visual_editor`<br>`raw_graph_import`<br>`test` | `emitEvent` | direct |
| `addFunction` | Add Function | Create a same-script function graph resource. | `functions` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | receipt-data |
| `callFunction` | Call Function | Insert a function.call node by function id or name. | `nodes` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | direct |
| `moveNode` | Move Node | Move a graph node without changing semantics. | `nodes.position` | `visual_editor`<br>`ai`<br>`mcp`<br>`sdk` | `pure` | direct |
| `addComment` | Add Comment | Add a visual comment box to the script canvas. | `comments` | `visual_editor`<br>`raw_graph_import`<br>`ai`<br>`mcp`<br>`sdk`<br>`test` | `pure` | receipt-data |
| `groupNodes` | Group Nodes | Create a visual color group for nodes. | `groups` | `visual_editor`<br>`raw_graph_import`<br>`ai`<br>`mcp`<br>`sdk`<br>`test` | `pure` | receipt-data |
| `replaceVisualScriptIr` | Replace Visual Script IR | Commit a checked visual-editor graph projection through Semantic Patch with version and fingerprint guards. | `handlers`<br>`variables`<br>`functions`<br>`customEvents`<br>`nodes`<br>`comments`<br>`groups` | `visual_editor`<br>`raw_graph_import`<br>`test` | `pure` | receipt-data |
| `replaceScriptFromGessaScript` | Replace Script From GessaScript | Compile whole-body GessaScript source text through the canonical compiler and validator, replacing the script with the resulting IR. The one checked subtractive/mutating write op admitted for AI/MCP. | `handlers`<br>`variables`<br>`functions`<br>`customEvents`<br>`nodes`<br>`comments`<br>`groups` | `ai`<br>`mcp`<br>`sdk`<br>`visual_editor`<br>`template`<br>`test` | `pure` | receipt-data |
| `applyTemplate` | Apply Template | Expand an approved backend template into semantic operations. | `handlers`<br>`variables`<br>`nodes`<br>`customEvents` | `template`<br>`raw_graph_import`<br>`test` | `requiresAuthority` | receipt-data |
| `createCustomEventHandler` | Create Custom Event Handler | Declare a custom event and create a guarded onCustomEvent handler for its semantic key. | `customEvents`<br>`handlers`<br>`nodes` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `emitEvent` | receipt-data |
| `addActionHandler` | Add Action Handler | Create an action-resolved handler without requiring graph ids. | `handlers`<br>`events` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `pure` | receipt-data |
| `addTriggerHandler` | Add Trigger Handler | Create a trigger-enter handler without requiring graph ids. | `handlers`<br>`events` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `pure` | receipt-data |
| `addTimerHandler` | Add Timer Handler | Create a timer-fired handler without requiring graph ids. | `handlers`<br>`events` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `pure` | receipt-data |
| `addTickHandler` | Add Tick Handler | Create a tick handler without requiring graph ids. | `handlers`<br>`events` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `pure` | receipt-data |
| `readTypedStateValue` | Read Typed State Value | Read a typed warehouse state field into a local Script IR binding. | `nodes`<br>`warehouse` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `readState`<br>`durable` | receipt-data |
| `writeTypedStateValue` | Write Typed State Value | Write one typed warehouse state field through Warehouse.update. | `nodes`<br>`warehouse` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `writeState`<br>`durable`<br>`requiresAuthority` | receipt-data |
| `incrementNumericState` | Increment Numeric State | Read a numeric warehouse field and write it back with a deterministic increment. | `nodes`<br>`warehouse` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `readState`<br>`writeState`<br>`durable`<br>`requiresAuthority` | receipt-data |
| `setBooleanState` | Set Boolean State | Write a boolean warehouse state field through Warehouse.update. | `nodes`<br>`warehouse` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `writeState`<br>`durable`<br>`requiresAuthority` | receipt-data |
| `findEntitiesByTag` | Find Entities By Tag | Create a World.find call assigned to a named result. | `nodes`<br>`world` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `readWorld` | receipt-data |
| `forEachEntityInResult` | For Each Entity In Result | Iterate a named entity result with bounded typed entity binding. | `nodes`<br>`world` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `readWorld`<br>`writeWorld` | receipt-data |
| `despawnEntity` | Despawn Entity | Despawn the current entity or a named entity binding. | `nodes`<br>`world` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `despawnEntity`<br>`writeWorld`<br>`requiresAuthority` | receipt-data |
| `compareRemainingCount` | Compare Remaining Count | Bind a boolean comparison against a named entity result count. | `nodes`<br>`world` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `readWorld` | receipt-data |
| `declareWinCondition` | Declare Win Condition | Transition match phase when the remaining entity count reaches the declared threshold. | `nodes`<br>`match`<br>`world` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `readWorld`<br>`writeState`<br>`emitEvent`<br>`requiresAuthority` | receipt-data |
| `emitCustomEvent` | Emit Custom Event | Emit a custom event by semantic event key. | `nodes`<br>`customEvents` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `emitEvent` | receipt-data |
| `spawnEntityFromTemplate` | Spawn Entity From Template Or Prefab | Spawn an entity or instantiate a prefab from semantic template/prefab keys. | `nodes`<br>`world` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `spawnEntity`<br>`writeWorld`<br>`requiresAuthority` | receipt-data |
| `attachComponentWithValidatedDefaults` | Attach Component With Validated Defaults | Attach an ECS component using canonical component defaults plus explicit overrides. | `nodes`<br>`components` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `writeState`<br>`writeWorld`<br>`requiresAuthority` | receipt-data |
| `wireHudStateBinding` | Wire HUD State Binding | Read a state field and push it through UI.setWidgetValue for HUD projection. | `nodes`<br>`ui`<br>`warehouse` | `ai`<br>`mcp`<br>`sdk`<br>`template` | `readState`<br>`durable`<br>`uiEffect` | receipt-data |
| `addShooterCollectorLoop` | Add Shooter/Collector Loop | Expand the common shooter/collector gameplay loop from semantic intent only. | `handlers`<br>`customEvents`<br>`nodes`<br>`warehouse`<br>`world`<br>`match` | `visual_editor`<br>`template` | `readWorld`<br>`writeWorld`<br>`readState`<br>`writeState`<br>`emitEvent`<br>`spawnEntity`<br>`despawnEntity`<br>`durable`<br>`requiresAuthority` | receipt-data |

## Operation Packs

| Pack | Operations |
| --- | --- |
| `visual_editor` | `addHandler`<br>`removeHandler`<br>`addVariable`<br>`renameVariable`<br>`setVariableDefault`<br>`addNode`<br>`removeNode`<br>`removeVariable`<br>`removeFunction`<br>`disconnect`<br>`clearInlineValue`<br>`connectExec`<br>`connectData`<br>`setInlineValue`<br>`addHostOperation`<br>`addCustomEvent`<br>`dispatchCustomEvent`<br>`addFunction`<br>`callFunction`<br>`moveNode`<br>`addComment`<br>`groupNodes`<br>`replaceVisualScriptIr`<br>`replaceScriptFromGessaScript`<br>`createCustomEventHandler`<br>`addActionHandler`<br>`addTriggerHandler`<br>`addTimerHandler`<br>`addTickHandler`<br>`readTypedStateValue`<br>`writeTypedStateValue`<br>`incrementNumericState`<br>`setBooleanState`<br>`findEntitiesByTag`<br>`forEachEntityInResult`<br>`despawnEntity`<br>`compareRemainingCount`<br>`declareWinCondition`<br>`emitCustomEvent`<br>`spawnEntityFromTemplate`<br>`attachComponentWithValidatedDefaults`<br>`wireHudStateBinding`<br>`addShooterCollectorLoop` |
| `ai_safe` | `createCustomEventHandler`<br>`addActionHandler`<br>`addTriggerHandler`<br>`addTimerHandler`<br>`addTickHandler`<br>`readTypedStateValue`<br>`writeTypedStateValue`<br>`incrementNumericState`<br>`setBooleanState`<br>`findEntitiesByTag`<br>`forEachEntityInResult`<br>`despawnEntity`<br>`compareRemainingCount`<br>`declareWinCondition`<br>`emitCustomEvent`<br>`spawnEntityFromTemplate`<br>`attachComponentWithValidatedDefaults`<br>`wireHudStateBinding`<br>`replaceScriptFromGessaScript`<br>`moveNode`<br>`addComment`<br>`groupNodes` |
| `mcp_safe` | `createCustomEventHandler`<br>`addActionHandler`<br>`addTriggerHandler`<br>`addTimerHandler`<br>`addTickHandler`<br>`readTypedStateValue`<br>`writeTypedStateValue`<br>`incrementNumericState`<br>`setBooleanState`<br>`findEntitiesByTag`<br>`forEachEntityInResult`<br>`despawnEntity`<br>`compareRemainingCount`<br>`declareWinCondition`<br>`emitCustomEvent`<br>`spawnEntityFromTemplate`<br>`attachComponentWithValidatedDefaults`<br>`wireHudStateBinding`<br>`replaceScriptFromGessaScript`<br>`moveNode`<br>`addComment`<br>`groupNodes` |
| `sdk_basic` | `createCustomEventHandler`<br>`addActionHandler`<br>`addTriggerHandler`<br>`addTimerHandler`<br>`addTickHandler`<br>`readTypedStateValue`<br>`writeTypedStateValue`<br>`incrementNumericState`<br>`setBooleanState`<br>`findEntitiesByTag`<br>`forEachEntityInResult`<br>`despawnEntity`<br>`compareRemainingCount`<br>`declareWinCondition`<br>`emitCustomEvent`<br>`spawnEntityFromTemplate`<br>`attachComponentWithValidatedDefaults`<br>`wireHudStateBinding`<br>`replaceScriptFromGessaScript`<br>`moveNode`<br>`addComment`<br>`groupNodes` |
| `raw_graph_import` | `addHandler`<br>`removeHandler`<br>`addVariable`<br>`renameVariable`<br>`setVariableDefault`<br>`addNode`<br>`removeNode`<br>`removeVariable`<br>`removeFunction`<br>`disconnect`<br>`clearInlineValue`<br>`connectExec`<br>`connectData`<br>`setInlineValue`<br>`addHostOperation`<br>`addCustomEvent`<br>`dispatchCustomEvent`<br>`addFunction`<br>`callFunction`<br>`addComment`<br>`groupNodes`<br>`replaceVisualScriptIr`<br>`applyTemplate` |

## Eval Corpus

| Case | Title | Operations |
| --- | --- | --- |
| `coin-pickup` | Coin pickup behavior | `applyTemplate` |
| `door-trigger` | Door trigger behavior | `applyTemplate` |
| `timer` | Timer behavior | `applyTemplate` |
| `custom-event` | Custom event behavior | `applyTemplate` |
| `ai-edit` | AI edit behavior | `applyTemplate` |
| `shooter-collector-v2` | Shooter/collector V2 intent behavior | `addTickHandler`<br>`addActionHandler`<br>`createCustomEventHandler`<br>`findEntitiesByTag`<br>`readTypedStateValue`<br>`readTypedStateValue`<br>`forEachEntityInResult`<br>`compareRemainingCount`<br>`writeTypedStateValue`<br>`declareWinCondition`<br>`wireHudStateBinding`<br>`spawnEntityFromTemplate`<br>`emitCustomEvent`<br>`incrementNumericState`<br>`despawnEntity` |
| `handler-key-round-trip` | Handler created by handlerKey is referenceable by that key in the same batch | `addTriggerHandler`<br>`despawnEntity`<br>`incrementNumericState` |
| `custom-event-key-round-trip` | Custom event created by eventKey is emittable by that key in the same batch | `createCustomEventHandler`<br>`addTickHandler`<br>`emitCustomEvent` |

## Coverage Matrix

```json
{
  "addHandler": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "events"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "direct"
  },
  "removeHandler": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "events"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "addVariable": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "variables"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "writeState"
    ],
    "inverse": "receipt-data"
  },
  "renameVariable": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "variables"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "direct"
  },
  "setVariableDefault": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "variables"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "writeState"
    ],
    "inverse": "direct"
  },
  "addNode": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "direct"
  },
  "removeNode": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "execEdges",
      "dataEdges"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "removeVariable": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "variables"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "writeState"
    ],
    "inverse": "receipt-data"
  },
  "removeFunction": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "functions"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "disconnect": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "execEdges",
      "dataEdges"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "clearInlineValue": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes.inlineValues"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "connectExec": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "execEdges"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "direct"
  },
  "connectData": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "dataEdges"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "direct"
  },
  "setInlineValue": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes.inlineValues"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "direct"
  },
  "addHostOperation": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "requiresAuthority"
    ],
    "inverse": "direct"
  },
  "addCustomEvent": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "customEvents"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "dispatchCustomEvent": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "emitEvent"
    ],
    "inverse": "direct"
  },
  "addFunction": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "functions"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "callFunction": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "direct"
  },
  "moveNode": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes.position"
    ],
    "contexts": [
      "visual_editor",
      "ai",
      "mcp",
      "sdk"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "direct"
  },
  "addComment": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "comments"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "ai",
      "mcp",
      "sdk",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "groupNodes": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "groups"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "ai",
      "mcp",
      "sdk",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "replaceVisualScriptIr": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "variables",
      "functions",
      "customEvents",
      "nodes",
      "comments",
      "groups"
    ],
    "contexts": [
      "visual_editor",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "replaceScriptFromGessaScript": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "variables",
      "functions",
      "customEvents",
      "nodes",
      "comments",
      "groups"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "visual_editor",
      "template",
      "test"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "applyTemplate": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "variables",
      "nodes",
      "customEvents"
    ],
    "contexts": [
      "template",
      "raw_graph_import",
      "test"
    ],
    "effectTags": [
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  },
  "createCustomEventHandler": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "customEvents",
      "handlers",
      "nodes"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "emitEvent"
    ],
    "inverse": "receipt-data"
  },
  "addActionHandler": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "events"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "addTriggerHandler": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "events"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "addTimerHandler": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "events"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "addTickHandler": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "events"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "pure"
    ],
    "inverse": "receipt-data"
  },
  "readTypedStateValue": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "warehouse"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "readState",
      "durable"
    ],
    "inverse": "receipt-data"
  },
  "writeTypedStateValue": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "warehouse"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "writeState",
      "durable",
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  },
  "incrementNumericState": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "warehouse"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "readState",
      "writeState",
      "durable",
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  },
  "setBooleanState": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "warehouse"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "writeState",
      "durable",
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  },
  "findEntitiesByTag": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "world"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "readWorld"
    ],
    "inverse": "receipt-data"
  },
  "forEachEntityInResult": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "world"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "readWorld",
      "writeWorld"
    ],
    "inverse": "receipt-data"
  },
  "despawnEntity": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "world"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "despawnEntity",
      "writeWorld",
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  },
  "compareRemainingCount": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "world"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "readWorld"
    ],
    "inverse": "receipt-data"
  },
  "declareWinCondition": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "match",
      "world"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "readWorld",
      "writeState",
      "emitEvent",
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  },
  "emitCustomEvent": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "customEvents"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "emitEvent"
    ],
    "inverse": "receipt-data"
  },
  "spawnEntityFromTemplate": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "world"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "spawnEntity",
      "writeWorld",
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  },
  "attachComponentWithValidatedDefaults": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "components"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "writeState",
      "writeWorld",
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  },
  "wireHudStateBinding": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "nodes",
      "ui",
      "warehouse"
    ],
    "contexts": [
      "ai",
      "mcp",
      "sdk",
      "template"
    ],
    "effectTags": [
      "readState",
      "durable",
      "uiEffect"
    ],
    "inverse": "receipt-data"
  },
  "addShooterCollectorLoop": {
    "catalog": true,
    "schema": true,
    "mutates": [
      "handlers",
      "customEvents",
      "nodes",
      "warehouse",
      "world",
      "match"
    ],
    "contexts": [
      "visual_editor",
      "template"
    ],
    "effectTags": [
      "readWorld",
      "writeWorld",
      "readState",
      "writeState",
      "emitEvent",
      "spawnEntity",
      "despawnEntity",
      "durable",
      "requiresAuthority"
    ],
    "inverse": "receipt-data"
  }
}
```

## Backend Action

- Action Catalog id: `project.script.patch.apply`.
- HTTP: `POST /api/games/:gameId/project/scripts/:idOrKey/patches/apply`.
- MCP: `project_apply_script_semantic_patch`.
- AI metadata: `apply_script_semantic_patch`.
- Persistence: existing `UpdateProjectScript` Project Graph event with semantic patch receipt in `editor.visualScript.semanticPatch`.
