# `AshUi.Patch.Runtime`
[🔗](https://github.com/hyperbob-labs/ash_ui/blob/main/lib/ash_ui/patch/runtime.ex#L1)

Change derivation over a compiled `AshUi.Patch.Table`.

The patching protocol is the live host's own: the compiled skeleton supplies
statics, evaluator closures supply dynamics, and the ONLY thing this
module contributes is the changed-address set — which dynamics may
return a value instead of nil under change tracking. The live host's diff
engine and client own every DOM decision; there is no parallel op
vocabulary, no slot-value store, no tree.

`diff/2` compares attributes AND loaded relationships, calculations,
and aggregates — relationship-as-read reactivity means a reloaded
relationship with unchanged attributes must still invalidate the slots
that read it. A field that is `%Ash.NotLoaded{}` on both sides is
unchanged; loaded on one side only is changed (the truth moved or is
unknown — invalidate).

# `changed_addresses`

```elixir
@spec changed_addresses(module() | AshUi.Patch.Table.t(), struct() | nil, struct()) ::
  :all | MapSet.t()
```

The changed slot addresses between two records, straight from the
propagation index — the gate the live host needs to build a
differential render. `:all` when the before-image is missing or the
resources differ.

# `diff`

```elixir
@spec diff(struct(), struct()) :: %{fields: [atom()]}
```

Changed field names between two records of the same resource.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
