---
title: "Field"
description: "The Field namespace — the engine's Luau API reference for Field."
section: "API Reference"
slug: "api-field"
canonical: "https://origozero.ai/docs/api-field"
updated: "2026-09-05T23:13:46.452520020+00:00"
tags: ["api", "reference"]
---

# Field

The `Field` namespace — 42 functions.

## globals/Field/alias {#globals-field-alias}

```lua
Field.alias(target: string | { string }, description: string?) -> FieldDesc<any>
```

Alias for one or more existing fields. An alias is an
ACCEPTED key that is not stored itself — it routes the
written value to the real field(s) it points at, so a component
answers to a caller's natural key without hand-rolling translation
code, and both the runtime and the LSP recognise the key.

The key works everywhere the fields it targets do: as a
`component.add` init key, and as a read and a write on the live
component. Reading it returns what the target(s) hold right now.

Two forms:
- `Field.alias("radius")` — rename. The value is written verbatim
to the single target field (running that field's normal
coercion, so an alias onto an assetRef field resolves the ref),
and reads back as that field's value.
- `Field.alias({ "colorR", "colorG", "colorB" })` — fan-out. The
value is destructured across the targets: an array `{a, b, c}`
positionally, or a named `{r=, g=, b=}` / `{x=, y=, z=}` table
by the target's position (r/x, g/y, b/z, a/w). It reads back as
an array in target order, so `c.color = c.color` round-trips.

An alias never replicates and is never persisted — the fields it
targets own their own Sync/NoSync, so no mode argument is taken.

**Parameters**

- `target` `string | { string }` — A single target field name, or an array of target field names.
- `description` `string` _(optional)_ — Documents the alias for the LSP; nil to leave it undocumented.

**Returns** `FieldDesc<any>` — FieldDesc descriptor with `kind = "alias"`.

```lua
type  = Field.alias("kind")
color = Field.alias({ "colorR", "colorG", "colorB" })
```

## globals/Field/assetRef {#globals-field-assetref}

```lua
Field.assetRef(category: C & string, default: AssetRef<C> | I | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<C, I>>
```

Typed asset reference field. `C` is the asset category — a
singleton string type inferred from the `category` argument
(`"material"`, `"mesh"`, `"@user/customCategory"`, etc.). One
constructor handles every category, including user-registered ones.

Default accepts a resolved `AssetRef<C>` handle, an identity string
(full `@library::path` form OR a bare leaf name resolved
category-locally via `asset.resolve(identity, category)`), or `nil`.

At registration the engine resolves any string default through the
same category-aware resolver `public_newindex` uses for runtime
writes, so the first read of `public.<field>` already returns a
resolved envelope — not a raw string.

**Parameters**

- `category` `C & string` — Asset category as a string literal (`"material"`, `"mesh"`, etc.). Inferred into `C`.
- `default` `AssetRef<C> | I | nil` _(optional)_ — AssetRef envelope, identity string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<C, I>> descriptor.

```lua
material = Field.assetRef("material", "@my-library::materials.gold", Sync)
source = Field.assetRef("bundle", nil, Sync)
```

## globals/Field/bitmask {#globals-field-bitmask}

```lua
Field.bitmask(bits: number, default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
```

Bit-mask number field. `bits` declares the width the consumer can
address; a default or a write that is not a whole number in
`0 .. 2^bits - 1` is rejected, naming the width. Use it wherever a numeric
field is read as a set of bits rather than as a quantity — what the field
reads back is then a mask, so a read-back is evidence the value took.

**Parameters**

- `bits` `number` — How many bits wide the mask is, 1..53.
- `default` `number` _(optional)_ — Numeric default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<number> descriptor carrying a `bitmask` constraint.

```lua
lightChannels = Field.bitmask(32, 0, Sync)
```

## globals/Field/bool {#globals-field-bool}

```lua
Field.bool(default: boolean?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<boolean>
```

Boolean field. `nil` leaves the field unset.

**Parameters**

- `default` `boolean` _(optional)_ — Boolean default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<boolean> descriptor.

```lua
enabled = Field.bool(true, Sync)
```

## globals/Field/color {#globals-field-color}

```lua
Field.color(default: color?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<color>
```

Color field. Default is a `color` — either
`{r = .., g = .., b = .., a = ..?}` or `{r, g, b, a?}`.

**Parameters**

- `default` `color` _(optional)_ — color default for `public.<field>`.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<color> descriptor.

```lua
tint = Field.color({ 1, 1, 1, 1 }, Sync)
```

## globals/Field/componentRef {#globals-field-componentref}

```lua
Field.componentRef(componentType: T & string, default: ComponentRef<T> | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<ComponentRef<T>>
```

Typed component reference field. `T` is the component-type
name — a singleton string type inferred from the `componentType`
argument (`"Camera"`, `"Transform"`, `"@user/Inventory"`). The
engine validates the referent exists and is of the declared type
at every write.

**Parameters**

- `componentType` `T & string` — Component type name as a string literal. Inferred into `T`.
- `default` `ComponentRef<T> | nil` _(optional)_ — ComponentRef envelope or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<ComponentRef<T>> descriptor.

```lua
aimCam = Field.componentRef("Camera", nil, NoSync)
```

## globals/Field/dataRef {#globals-field-dataref}

```lua
Field.dataRef(contract: C & string, default: AssetRef<"data"> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<"data">>
```

Contract-constrained typed-data reference field. Accepts only
`.data` assets whose dataType contract chain includes `contract`.
Rides the assetRef machinery (category "data") — dependency graph,
sync, and rehydration behave exactly like Field.assetRef — with the
contract gate enforced through the generic field-constraint hook on
every write and on the registration-time default.

**Parameters**

- `contract` `C & string` — The required dataType contract identity. Inferred into `C`.
- `default` `AssetRef<"data"> | string | nil` _(optional)_ — AssetRef envelope, identity string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<"data">> descriptor.

```lua
weapon = Field.dataRef("weapon", nil, Sync)
```

## globals/Field/entityRef {#globals-field-entityref}

```lua
Field.entityRef(default: EntityRef | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<EntityRef>
```

Entity reference field. Accepts a live entity proxy (`EntityRef`),
a raw entity-id string, or `nil` (no target). Writes are normalised to
the plain id string for storage/replication; reads return a live
`EntityRef` proxy (or `nil`), so `public.<field>:method()` and
`public.<field>.id` work directly without re-resolving.

**Parameters**

- `default` `EntityRef | string | nil` _(optional)_ — Live entity proxy, entity-id string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<EntityRef> descriptor.

```lua
target = Field.entityRef(nil, Sync)
```

## globals/Field/enum {#globals-field-enum}

```lua
Field.enum(values: { string }, default: string?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<string>
```

Closed-set string field. `values` declares every member; a default or a
write outside the set is rejected with the whole set named. The editor
renders the members as a choice and the LSP completes them.

**Parameters**

- `values` `{ string }` — The members, as an array of non-empty, distinct strings.
- `default` `string` _(optional)_ — The default member, or nil to leave the field unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<string> descriptor carrying an `enum` constraint.

```lua
fit = Field.enum({ "exact", "hull" }, "hull", Sync)
```

## globals/Field/instantiableRef {#globals-field-instantiableref}

```lua
Field.instantiableRef(default: AssetRef<any> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<any>>
```

Scene-instantiable asset reference field — accepts ANY asset whose
type can be instantiated into a scene, gated by CAPABILITY rather than a
hardcoded type list. Rides the assetRef machinery with no category filter
(any asset type resolves), and the generic field-constraint hook rejects,
on every write and on the registration-time default, any asset whose type
defines no `instantiate` method (`ref:canInstantiate()` is false). A
new scene-instantiable asset type is accepted here the moment it defines
the hook — no edit to this field or its consumers. The uniform
`ref:instantiate(target?, opts?)` is how a consumer then instantiates the
assigned asset (`Asset.component`, a viewport drop, a tool argument).

**Parameters**

- `default` `AssetRef<any> | string | nil` _(optional)_ — AssetRef envelope, identity string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<any>> descriptor.

```lua
source = Field.instantiableRef(nil, Sync)
```

## globals/Field/list {#globals-field-list}

```lua
Field.list(element: FieldDesc<any>, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<ListValue>
```

List field — an array of one repeated element type. The element
is the Field constructor descriptor every item conforms to, often a
Field.struct for a list of records. The list value is an array of
the element's value type. Like Field.struct, the engine descends
the element schema to resolve nested asset refs into envelopes, so
a stack of structs each holding an asset ref has every ref appear
in the asset dependency graph, validates each item, and the LSP
type-checks the array. The default value is an empty list. The
element declares its own Sync or NoSync for typing; the list's own
mode governs replication of the whole array as a unit.

**Parameters**

- `element` `FieldDesc<any>` — The Field constructor descriptor each item conforms to.
- `mode` `SyncMode` — Sync or NoSync — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** `FieldDesc<ListValue>` — FieldDesc whose value is an array of the element's values.

## globals/Field/number {#globals-field-number}

```lua
Field.number(default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
```

Number field. `nil` leaves the field unset, so a component can treat an
absent value as "derive this from somewhere else" without a second field
recording whether the first one was authored.

**Parameters**

- `default` `number` _(optional)_ — Numeric default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<number> descriptor consumed by component registration.

```lua
positionX = Field.number(0, Sync)
```

## globals/Field/quat {#globals-field-quat}

```lua
Field.quat(default: quat?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<quat>
```

Quaternion field. Default is a `quat` — either
`{x = .., y = .., z = .., w = ..}` or `{x, y, z, w}`.

**Parameters**

- `default` `quat` _(optional)_ — quat default for `public.<field>`.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<quat> descriptor.

```lua
rotation = Field.quat({ 0, 0, 0, 1 }, Sync)
```

## globals/Field/range {#globals-field-range}

```lua
Field.range(min: number?, max: number?, default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
```

Bounded number field. `min` and `max` declare the interval the value
means something in; a default or a write outside it is rejected with the
interval named. Either bound may be nil, leaving that side open. The value
the field reads back is one the system consuming it can use, and a number
that lands outside is reported where it was written.

**Parameters**

- `min` `number` _(optional)_ — Lowest accepted value, or nil to leave the low side open.
- `max` `number` _(optional)_ — Highest accepted value, or nil to leave the high side open.
- `default` `number` _(optional)_ — Numeric default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<number> descriptor carrying a `range` constraint.

```lua
volume = Field.range(0, 1, 1, Sync)
```

## globals/Field/resource {#globals-field-resource}

```lua
Field.resource(category: C & string, default: AssetRef<C> | Handle<C> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<C> | Handle<C>>
```

Category-gated RESOURCE field — accepts EITHER a persistent
`AssetRef<C>` OR a live GPU `Handle<C>`, gated by category. This is the
renderer-facing field type (e.g. `Model.model`, `Model.material`, material
texture slots): content can author a persistent asset OR pass a runtime
handle (`renderer.<resource>.create(...)`); the component bridges either to
the GPU resource. The category gate still holds — an `AssetRef<audio>` or a
wrong-category handle (a `TextureHandle` on a `"mesh"` slot) is a type error
AND a runtime rejection. Use `Field.assetRef` instead when the field MUST be
a persistent asset (handles rejected).
With `Sync`, persistent-asset values replicate to peers; a live GPU
handle value is local by construction and stays local — peers keep the
last replicated asset value.

**Parameters**

- `category` `C & string` — Resource category string literal (`"mesh"`, `"texture"`, `"material"`, ...). Inferred into `C`.
- `default` `AssetRef<C> | Handle<C> | string | nil` _(optional)_ — `AssetRef<C>` / `Handle<C>` / identity string / nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<C> | Handle<C>> descriptor.

```lua
model = Field.resource("mesh", nil, Sync)
```

## globals/Field/string {#globals-field-string}

```lua
Field.string(default: string?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<string>
```

String field. `nil` leaves the field unset.

**Parameters**

- `default` `string` _(optional)_ — String default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<string> descriptor.

```lua
label = Field.string("hello", Sync)
```

## globals/Field/struct {#globals-field-struct}

```lua
Field.struct(schema: FieldSchema, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<StructValue>
```

Struct field — a table whose keys are themselves typed fields.
The schema maps each subfield name to its Field constructor
descriptor; the struct value is a table holding one value per
subfield. Use this instead of Field.table when the table carries
asset references or other typed data: the engine descends the
schema to resolve nested asset refs into envelopes at registration
and at write time, so they appear in the asset dependency graph,
validates writes per subfield, and the LSP type-checks the shape.
Each subfield declares its own Sync or NoSync for typing; the
struct's own mode governs replication of the whole value as a unit.

**Parameters**

- `schema` `FieldSchema` — Map of subfield name to a Field constructor descriptor.
- `mode` `SyncMode` — Sync or NoSync — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** `FieldDesc<StructValue>` — FieldDesc whose value is a table of the subfields' values.

## globals/Field/table {#globals-field-table}

```lua
Field.table(default: T, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<T>
```

Generic table field. `T` is the table's shape — usually
inferred from the default value, or supplied explicitly via
an explicit ascription `Field.table({} :: MyShape, mode)` when the default doesn't cover every
key the runtime will write. The engine accepts any Luau table as
a value at write time; per-shape enforcement is opt-in static
typing only.

**Parameters**

- `default` `T` — Table value to use as the default for `public.<field>`.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<T> descriptor.

```lua
idMap = Field.table({} :: { [string]: string }, NoSync)
```

## globals/Field/taggedRef {#globals-field-taggedref}

```lua
Field.taggedRef(tag: string, default: AssetRef<any> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<any>>
```

Tag-constrained asset reference field — accepts any asset carrying
`tag` in its `.metadata.tags`, whatever its type. This is how a slot
states the KIND of asset it takes (a camera behavior, a player visual)
without naming the assets themselves: a new asset becomes assignable the
moment it is tagged, with no edit here or in the consumer. Rides the
assetRef machinery with no category filter — dependency graph, sync and
rehydration behave exactly like Field.assetRef — and the generic
field-constraint hook rejects an untagged asset on every write and on the
registration-time default. `asset.list({ fields = { tags = tag } })`
enumerates what fits the slot.

**Parameters**

- `tag` `string` — The tag an assigned asset must carry.
- `default` `AssetRef<any> | string | nil` _(optional)_ — AssetRef envelope, identity string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<any>> descriptor.

```lua
behavior = Field.taggedRef("cameraBehavior", nil, Sync)
```

## globals/Field/vec2 {#globals-field-vec2}

```lua
Field.vec2(default: vec2?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<vec2>
```

**Parameters**

- `default` `vec2` _(optional)_
- `mode` `SyncMode`
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_

**Returns** `FieldDesc<vec2>`

## globals/Field/vec3 {#globals-field-vec3}

```lua
Field.vec3(default: vec3?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<vec3>
```

Vec3 field. Default is a `vec3` — either `{x = .., y = .., z = ..}`
or the 3-element array form `{x, y, z}`.

**Parameters**

- `default` `vec3` _(optional)_ — vec3 default for `public.<field>`.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<vec3> descriptor.

```lua
offset = Field.vec3({ 0, 0, 0 }, Sync)
```

## typed/builtin//modules/field/Field/alias {#typed-builtin-modules-field-field-alias}

```lua
Field.alias(target: string | { string }, description: string?) -> FieldDesc<any>
```

Alias for one or more existing fields. An alias is an
ACCEPTED key that is not stored itself — it routes the
written value to the real field(s) it points at, so a component
answers to a caller's natural key without hand-rolling translation
code, and both the runtime and the LSP recognise the key.

The key works everywhere the fields it targets do: as a
`component.add` init key, and as a read and a write on the live
component. Reading it returns what the target(s) hold right now.

Two forms:
- `Field.alias("radius")` — rename. The value is written verbatim
to the single target field (running that field's normal
coercion, so an alias onto an assetRef field resolves the ref),
and reads back as that field's value.
- `Field.alias({ "colorR", "colorG", "colorB" })` — fan-out. The
value is destructured across the targets: an array `{a, b, c}`
positionally, or a named `{r=, g=, b=}` / `{x=, y=, z=}` table
by the target's position (r/x, g/y, b/z, a/w). It reads back as
an array in target order, so `c.color = c.color` round-trips.

An alias never replicates and is never persisted — the fields it
targets own their own Sync/NoSync, so no mode argument is taken.

**Parameters**

- `target` `string | { string }` — A single target field name, or an array of target field names.
- `description` `string` _(optional)_ — Documents the alias for the LSP; nil to leave it undocumented.

**Returns** `FieldDesc<any>` — FieldDesc descriptor with `kind = "alias"`.

```lua
type  = Field.alias("kind")
color = Field.alias({ "colorR", "colorG", "colorB" })
```

## typed/builtin//modules/field/Field/assetRef {#typed-builtin-modules-field-field-assetref}

```lua
Field.assetRef(category: C & string, default: AssetRef<C> | I | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<C, I>>
```

Typed asset reference field. `C` is the asset category — a
singleton string type inferred from the `category` argument
(`"material"`, `"mesh"`, `"@user/customCategory"`, etc.). One
constructor handles every category, including user-registered ones.

Default accepts a resolved `AssetRef<C>` handle, an identity string
(full `@library::path` form OR a bare leaf name resolved
category-locally via `asset.resolve(identity, category)`), or `nil`.

At registration the engine resolves any string default through the
same category-aware resolver `public_newindex` uses for runtime
writes, so the first read of `public.<field>` already returns a
resolved envelope — not a raw string.

**Parameters**

- `category` `C & string` — Asset category as a string literal (`"material"`, `"mesh"`, etc.). Inferred into `C`.
- `default` `AssetRef<C> | I | nil` _(optional)_ — AssetRef envelope, identity string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<C, I>> descriptor.

```lua
material = Field.assetRef("material", "@my-library::materials.gold", Sync)
source = Field.assetRef("bundle", nil, Sync)
```

## typed/builtin//modules/field/Field/bitmask {#typed-builtin-modules-field-field-bitmask}

```lua
Field.bitmask(bits: number, default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
```

Bit-mask number field. `bits` declares the width the consumer can
address; a default or a write that is not a whole number in
`0 .. 2^bits - 1` is rejected, naming the width. Use it wherever a numeric
field is read as a set of bits rather than as a quantity — what the field
reads back is then a mask, so a read-back is evidence the value took.

**Parameters**

- `bits` `number` — How many bits wide the mask is, 1..53.
- `default` `number` _(optional)_ — Numeric default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<number> descriptor carrying a `bitmask` constraint.

```lua
lightChannels = Field.bitmask(32, 0, Sync)
```

## typed/builtin//modules/field/Field/bool {#typed-builtin-modules-field-field-bool}

```lua
Field.bool(default: boolean?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<boolean>
```

Boolean field. `nil` leaves the field unset.

**Parameters**

- `default` `boolean` _(optional)_ — Boolean default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<boolean> descriptor.

```lua
enabled = Field.bool(true, Sync)
```

## typed/builtin//modules/field/Field/color {#typed-builtin-modules-field-field-color}

```lua
Field.color(default: color?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<color>
```

Color field. Default is a `color` — either
`{r = .., g = .., b = .., a = ..?}` or `{r, g, b, a?}`.

**Parameters**

- `default` `color` _(optional)_ — color default for `public.<field>`.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<color> descriptor.

```lua
tint = Field.color({ 1, 1, 1, 1 }, Sync)
```

## typed/builtin//modules/field/Field/componentRef {#typed-builtin-modules-field-field-componentref}

```lua
Field.componentRef(componentType: T & string, default: ComponentRef<T> | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<ComponentRef<T>>
```

Typed component reference field. `T` is the component-type
name — a singleton string type inferred from the `componentType`
argument (`"Camera"`, `"Transform"`, `"@user/Inventory"`). The
engine validates the referent exists and is of the declared type
at every write.

**Parameters**

- `componentType` `T & string` — Component type name as a string literal. Inferred into `T`.
- `default` `ComponentRef<T> | nil` _(optional)_ — ComponentRef envelope or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<ComponentRef<T>> descriptor.

```lua
aimCam = Field.componentRef("Camera", nil, NoSync)
```

## typed/builtin//modules/field/Field/dataRef {#typed-builtin-modules-field-field-dataref}

```lua
Field.dataRef(contract: C & string, default: AssetRef<"data"> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<"data">>
```

Contract-constrained typed-data reference field. Accepts only
`.data` assets whose dataType contract chain includes `contract`.
Rides the assetRef machinery (category "data") — dependency graph,
sync, and rehydration behave exactly like Field.assetRef — with the
contract gate enforced through the generic field-constraint hook on
every write and on the registration-time default.

**Parameters**

- `contract` `C & string` — The required dataType contract identity. Inferred into `C`.
- `default` `AssetRef<"data"> | string | nil` _(optional)_ — AssetRef envelope, identity string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<"data">> descriptor.

```lua
weapon = Field.dataRef("weapon", nil, Sync)
```

## typed/builtin//modules/field/Field/entityRef {#typed-builtin-modules-field-field-entityref}

```lua
Field.entityRef(default: EntityRef | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<EntityRef>
```

Entity reference field. Accepts a live entity proxy (`EntityRef`),
a raw entity-id string, or `nil` (no target). Writes are normalised to
the plain id string for storage/replication; reads return a live
`EntityRef` proxy (or `nil`), so `public.<field>:method()` and
`public.<field>.id` work directly without re-resolving.

**Parameters**

- `default` `EntityRef | string | nil` _(optional)_ — Live entity proxy, entity-id string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<EntityRef> descriptor.

```lua
target = Field.entityRef(nil, Sync)
```

## typed/builtin//modules/field/Field/enum {#typed-builtin-modules-field-field-enum}

```lua
Field.enum(values: { string }, default: string?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<string>
```

Closed-set string field. `values` declares every member; a default or a
write outside the set is rejected with the whole set named. The editor
renders the members as a choice and the LSP completes them.

**Parameters**

- `values` `{ string }` — The members, as an array of non-empty, distinct strings.
- `default` `string` _(optional)_ — The default member, or nil to leave the field unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<string> descriptor carrying an `enum` constraint.

```lua
fit = Field.enum({ "exact", "hull" }, "hull", Sync)
```

## typed/builtin//modules/field/Field/instantiableRef {#typed-builtin-modules-field-field-instantiableref}

```lua
Field.instantiableRef(default: AssetRef<any> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<any>>
```

Scene-instantiable asset reference field — accepts ANY asset whose
type can be instantiated into a scene, gated by CAPABILITY rather than a
hardcoded type list. Rides the assetRef machinery with no category filter
(any asset type resolves), and the generic field-constraint hook rejects,
on every write and on the registration-time default, any asset whose type
defines no `instantiate` method (`ref:canInstantiate()` is false). A
new scene-instantiable asset type is accepted here the moment it defines
the hook — no edit to this field or its consumers. The uniform
`ref:instantiate(target?, opts?)` is how a consumer then instantiates the
assigned asset (`Asset.component`, a viewport drop, a tool argument).

**Parameters**

- `default` `AssetRef<any> | string | nil` _(optional)_ — AssetRef envelope, identity string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<any>> descriptor.

```lua
source = Field.instantiableRef(nil, Sync)
```

## typed/builtin//modules/field/Field/list {#typed-builtin-modules-field-field-list}

```lua
Field.list(element: FieldDesc<any>, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<ListValue>
```

List field — an array of one repeated element type. The element
is the Field constructor descriptor every item conforms to, often a
Field.struct for a list of records. The list value is an array of
the element's value type. Like Field.struct, the engine descends
the element schema to resolve nested asset refs into envelopes, so
a stack of structs each holding an asset ref has every ref appear
in the asset dependency graph, validates each item, and the LSP
type-checks the array. The default value is an empty list. The
element declares its own Sync or NoSync for typing; the list's own
mode governs replication of the whole array as a unit.

## typed/builtin//modules/field/Field/number {#typed-builtin-modules-field-field-number}

```lua
Field.number(default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
```

Number field. `nil` leaves the field unset, so a component can treat an
absent value as "derive this from somewhere else" without a second field
recording whether the first one was authored.

**Parameters**

- `default` `number` _(optional)_ — Numeric default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<number> descriptor consumed by component registration.

```lua
positionX = Field.number(0, Sync)
```

## typed/builtin//modules/field/Field/quat {#typed-builtin-modules-field-field-quat}

```lua
Field.quat(default: quat?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<quat>
```

Quaternion field. Default is a `quat` — either
`{x = .., y = .., z = .., w = ..}` or `{x, y, z, w}`.

**Parameters**

- `default` `quat` _(optional)_ — quat default for `public.<field>`.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<quat> descriptor.

```lua
rotation = Field.quat({ 0, 0, 0, 1 }, Sync)
```

## typed/builtin//modules/field/Field/range {#typed-builtin-modules-field-field-range}

```lua
Field.range(min: number?, max: number?, default: number?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<number>
```

Bounded number field. `min` and `max` declare the interval the value
means something in; a default or a write outside it is rejected with the
interval named. Either bound may be nil, leaving that side open. The value
the field reads back is one the system consuming it can use, and a number
that lands outside is reported where it was written.

**Parameters**

- `min` `number` _(optional)_ — Lowest accepted value, or nil to leave the low side open.
- `max` `number` _(optional)_ — Highest accepted value, or nil to leave the high side open.
- `default` `number` _(optional)_ — Numeric default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<number> descriptor carrying a `range` constraint.

```lua
volume = Field.range(0, 1, 1, Sync)
```

## typed/builtin//modules/field/Field/resource {#typed-builtin-modules-field-field-resource}

```lua
Field.resource(category: C & string, default: AssetRef<C> | Handle<C> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<C> | Handle<C>>
```

Category-gated RESOURCE field — accepts EITHER a persistent
`AssetRef<C>` OR a live GPU `Handle<C>`, gated by category. This is the
renderer-facing field type (e.g. `Model.model`, `Model.material`, material
texture slots): content can author a persistent asset OR pass a runtime
handle (`renderer.<resource>.create(...)`); the component bridges either to
the GPU resource. The category gate still holds — an `AssetRef<audio>` or a
wrong-category handle (a `TextureHandle` on a `"mesh"` slot) is a type error
AND a runtime rejection. Use `Field.assetRef` instead when the field MUST be
a persistent asset (handles rejected).
With `Sync`, persistent-asset values replicate to peers; a live GPU
handle value is local by construction and stays local — peers keep the
last replicated asset value.

**Parameters**

- `category` `C & string` — Resource category string literal (`"mesh"`, `"texture"`, `"material"`, ...). Inferred into `C`.
- `default` `AssetRef<C> | Handle<C> | string | nil` _(optional)_ — `AssetRef<C>` / `Handle<C>` / identity string / nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<C> | Handle<C>> descriptor.

```lua
model = Field.resource("mesh", nil, Sync)
```

## typed/builtin//modules/field/Field/string {#typed-builtin-modules-field-field-string}

```lua
Field.string(default: string?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<string>
```

String field. `nil` leaves the field unset.

**Parameters**

- `default` `string` _(optional)_ — String default for `public.<field>`, or nil to leave it unset.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<string> descriptor.

```lua
label = Field.string("hello", Sync)
```

## typed/builtin//modules/field/Field/struct {#typed-builtin-modules-field-field-struct}

```lua
Field.struct(schema: FieldSchema, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<StructValue>
```

Struct field — a table whose keys are themselves typed fields.
The schema maps each subfield name to its Field constructor
descriptor; the struct value is a table holding one value per
subfield. Use this instead of Field.table when the table carries
asset references or other typed data: the engine descends the
schema to resolve nested asset refs into envelopes at registration
and at write time, so they appear in the asset dependency graph,
validates writes per subfield, and the LSP type-checks the shape.
Each subfield declares its own Sync or NoSync for typing; the
struct's own mode governs replication of the whole value as a unit.

**Parameters**

- `schema` `FieldSchema` — Map of subfield name to a Field constructor descriptor.
- `mode` `SyncMode` — Sync or NoSync — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** `FieldDesc<StructValue>` — FieldDesc whose value is a table of the subfields' values.

## typed/builtin//modules/field/Field/table {#typed-builtin-modules-field-field-table}

```lua
Field.table(default: T, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<T>
```

Generic table field. `T` is the table's shape — usually
inferred from the default value, or supplied explicitly via
an explicit ascription `Field.table({} :: MyShape, mode)` when the default doesn't cover every
key the runtime will write. The engine accepts any Luau table as
a value at write time; per-shape enforcement is opt-in static
typing only.

**Parameters**

- `default` `T` — Table value to use as the default for `public.<field>`.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<T> descriptor.

```lua
idMap = Field.table({} :: { [string]: string }, NoSync)
```

## typed/builtin//modules/field/Field/taggedRef {#typed-builtin-modules-field-field-taggedref}

```lua
Field.taggedRef(tag: string, default: AssetRef<any> | string | nil?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<AssetRef<any>>
```

Tag-constrained asset reference field — accepts any asset carrying
`tag` in its `.metadata.tags`, whatever its type. This is how a slot
states the KIND of asset it takes (a camera behavior, a player visual)
without naming the assets themselves: a new asset becomes assignable the
moment it is tagged, with no edit here or in the consumer. Rides the
assetRef machinery with no category filter — dependency graph, sync and
rehydration behave exactly like Field.assetRef — and the generic
field-constraint hook rejects an untagged asset on every write and on the
registration-time default. `asset.list({ fields = { tags = tag } })`
enumerates what fits the slot.

**Parameters**

- `tag` `string` — The tag an assigned asset must carry.
- `default` `AssetRef<any> | string | nil` _(optional)_ — AssetRef envelope, identity string, or nil.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<AssetRef<any>> descriptor.

```lua
behavior = Field.taggedRef("cameraBehavior", nil, Sync)
```

## typed/builtin//modules/field/Field/vec2 {#typed-builtin-modules-field-field-vec2}

```lua
Field.vec2(default: vec2?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<vec2>
```

**Parameters**

- `default` `vec2` _(optional)_
- `mode` `SyncMode`
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_

**Returns** `FieldDesc<vec2>`

## typed/builtin//modules/field/Field/vec3 {#typed-builtin-modules-field-field-vec3}

```lua
Field.vec3(default: vec3?, mode: SyncMode, marker: (SerializedMode | string | FieldOptions)?) -> FieldDesc<vec3>
```

Vec3 field. Default is a `vec3` — either `{x = .., y = .., z = ..}`
or the 3-element array form `{x, y, z}`.

**Parameters**

- `default` `vec3` _(optional)_ — vec3 default for `public.<field>`.
- `mode` `SyncMode` — `Sync` or `NoSync` — required.
- `marker` `(SerializedMode | string | FieldOptions)` _(optional)_ — `Serialized`, a description string, or a `{ serialized, description }` options table; omit for neither.

**Returns** FieldDesc<vec3> descriptor.

```lua
offset = Field.vec3({ 0, 0, 0 }, Sync)
```
