---
title: "Writing GessaScript source to rewrite or remove behavior a patch cannot express (whole-body script text)"
description: "You want to author or REWRITE a whole script as text - including removing a handler or changing an existing value, which the add-only semantic ops cannot express. One `replaceScriptFromGessaScript` operation replaces the entire script body; the compiler owns IR, node ids, and layout, and returns structured `GS_*` diagnostics (stable codes + source paths) when the source does not parse or validate."
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/knowledge/playbooks/writing-gessascript-source/
---

# Writing GessaScript source to rewrite or remove behavior a patch cannot express (whole-body script text)

## When to use

You want to author or REWRITE a whole script as text - including removing a
handler or changing an existing value, which the add-only semantic ops cannot
express. One `replaceScriptFromGessaScript` operation replaces the entire
script body; the compiler owns IR, node ids, and layout, and returns structured
`GS_*` diagnostics (stable codes + source paths) when the source does not parse
or validate. For small additive tweaks, prefer the typed ops instead.

## The call

```json
{
  "id_or_key": "coin_pickup",
  "request": {
    "ifVersion": <current version>,
    "intent": "Rewrite coin pickup as whole-body source.",
    "operations": [
      { "op": "replaceScriptFromGessaScript", "source": "<the whole script text>" }
    ]
  }
}
```

via `project_apply_script_semantic_patch`. The op is in the `ai_safe` pack.

## The grammar (complete for v1)

Top-level, inside `script <scriptKey> { ... }`:

- `var <name>: <type> = <literal>;`
- `custom event <key>(<params>);`
- `event <eventName>(<params>) { <statements> }`
- `function <name>(<params>) -> <type> { <statements> }` (prefix `export` to expose)

Statements:

- `let <name> = <expression>;`
- `set <path> = <expression>;`
- `host <Namespace>.<name>(<args>);`
- `component <ComponentType>.patch({ ... });`
- `if <expression> { ... } else { ... }`
- `for <name> from <expr> to <expr> max <number> { ... }`
- `while <expression> max <number> { ... }`
- `return <expression>;`

Expressions:

- JSON literals, arrays, records, `vector3(x, y, z)`
- `get(path.to.value)` - read a variable/state path
- `event.key()`, `event.payload(path, type, default?)`
- `record.get(record, path, type, default?)`
- `array.length(v)`, `array.get(v, index, type, default?)`, `array.first(v, type, default?)`
- `call <functionName>(...)` (or bare `<functionName>(...)` as a statement)
- math/comparison/boolean HELPER CALLS, not operators: `add`, `sub`, `mul`,
  `div`, `mod`, `eq`, `ne`, `lt`, `lte`, `gt`, `gte`, `and`, `or`, `not`.
  Write `if gt(deltaSeconds, 0) { ... }`, never `if (deltaSeconds > 0)`.

It is NOT TypeScript: no imports, no arbitrary code, no infix arithmetic or
comparison operators, no `const`, no template strings. Unsupported syntax
returns `GS_*` diagnostics naming the construct and its span.

## Compile-verified example

```
script script.launch {
  var score: number = 0;
  custom event combat.hit(entityId: string);

  event onStart() {
    let greeting = "ready";
    host Debug.log(greeting);
    component TransformComponent.patch({ position: vector3(0, 1, 0) });
  }

  event onTick(deltaSeconds: number) {
    if gt(deltaSeconds, 0) {
      host Debug.log("tick");
    }
  }

  export function addScore(by: number) -> number {
    return add(by, 1);
  }
}
```

Handler events available: `onStart`, `onTick(deltaSeconds)`, `onTriggerEnter`,
`onTimerFired`, `onActionResolved`, `onCustomEvent` (custom events also arrive
via their declared key; read fields with `event.payload(...)`).

## Gotchas

- The source replaces the WHOLE script: include every handler you want to keep.
- Host namespaces are the Script SDK surface (`Debug`, `World`, `Warehouse`,
  `Match`, `Events`, `UI`, ...) - discover exact signatures via
  `engine_get_sdk_function_signature` / `engine-reference/script-sdk`.
- `set score = add(score, 1);` mutates a declared `var`; `let` bindings are
  local to the handler.
- Component patches go through `component <Type>.patch({...})` with canonical
  component fields (see `engine-reference/component-types`).
