# WAI Extension: Avatars (Digital Humans) > Status: Draft. Phase 4 of the cargo roadmap. Motion as instructions: > ship a signed stream of joint transforms — a skeleton, not a video of a > body — and the sink skins a mesh by the deterministic pose. An avatar > is a skeletal world, so conformance is **pose-equivalence**, a special > case of replay-equivalence. Reference impl: the `world` feature of > `wai-rs` (sim `wai.world.sim.skeletal0`); corpus: `avatar-conformance/`; > live sink: wai.transaction.science/avatar. Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174. ## 1. Scope and model A `wai.avatar.pose` object is a **skeletal world**: the same `WWLD` container, op log, canonical ordering, causality, sealing, state hash, and receipt chain as interactive-worlds (see `interactive-worlds.md`), with the simulation step reduced to the **identity** (as with state-feeds). The bones are nodes; an animation / expression op stream sets joint transforms; nothing is integrated. A telepresence stream is a live world of one avatar — the op log that drives a multiplayer world drives a body. In scope: the bone model, the registered skeletal sim (`wai.world.sim.skeletal0`) and its mutation kinds, the statement that conformance is worlds' replay-equivalence over the pose, and the binding to a `wai.mesh.glb` for skinning. Out of scope: everything interactive-worlds already defines (normative here unchanged); the skinning algorithm and forward-kinematics composition (sink presentation — a pure function of the hashed pose + the hierarchy); a transport; blend-shape / morph-target semantics beyond joint transforms (a later registration may add them). Relationship to the core spec: a registration under interactive-worlds, not a new container. `media` takes the value `"avatar"`; the authoritative capability is `wai.avatar.pose`, carried in a `WWLD` whose contract names `sim = wai.world.sim.skeletal0`. The avatar's mesh is a content-addressed `wai.mesh.glb` asset (its armature + skin weights), bound to the rig like any other presentation asset. ## 2. The bone A node is a **bone**: a parent reference plus a local TRS transform. Canonical field order (and therefore hash order) is exactly: | field | type | meaning | |---|---|---| | `parent` | `[u8; 16]` | parent bone's node id, or all-zero for a root | | `translation` | `[Fx; 3]` | local translation (Q32.32) | | `rotation` | `[Fx; 4]` | local rotation quaternion `(x, y, z, w)` | | `scale` | `[Fx; 3]` | local scale | The canonical node serialization is `parent(16) | translation | rotation | scale` = 16 + 10×`i64` = 96 bytes. The default bone is the identity (zero translation, identity quaternion, unit scale). The floor stays **trig-free**: a rotation is carried as a quaternion, and the quaternion → rotation-matrix the sink uses for skinning is `+ − ×` only. Axis-angle authoring (which needs sin/cos) happens once, off-line, in whatever produces the op bytes — the canonical artifact is the `Fx` quaternion, and every sink replays it exactly. ## 3. The skeletal sim — `wai.world.sim.skeletal0` Registers these mutation kinds; the `step` is the identity. All are LWW (a transform set rides the canonical total order — last canonical writer wins; there is no commutative transform set, so no SUM kind). | kind | payload | effect | |---|---|---| | `0x0001` CREATE | `parent[16] \| translation[3] \| rotation[4] \| scale[3]` | insert a bone; target MUST equal `mint_node_id(actor, lamport)` | | `0x0002` DELETE | *(empty)* | remove the bone | | `0x0010` SET_ROTATION | `rotation[4]` | set a joint's local rotation (the animation driver) | | `0x0011` SET_TRANSLATION | `translation[3]` | set a bone's local translation | | `0x0012` SET_SCALE | `scale[3]` | set a bone's local scale | An op targeting an absent bone is a **deterministic no-op** (interactive-worlds §6.4). `parent` need not name a present bone — a missing parent is treated as a root at FK time; the *hash* depends only on the stored values, so existence is irrelevant to conformance. ## 4. Conformance — pose-equivalence > Given the same avatar container and the same signed op set, a > conforming sink MUST compute the identical BLAKE3 **state hash** at > every checkpoint — the per-bone local transforms, in node-id order — on > every machine, no tolerance parameter. This is interactive-worlds' criterion verbatim, applied to the bone state. The forward-kinematics composition into world space and the skinning of the mesh produce identical results on any two sinks that agree on the pose (a pure function of the hashed locals + the hierarchy), so they are legitimately left to presentation and excluded from the hash — exactly as `wai.mesh.glb` geometry is. ## 5. Receipt (JWP profile) The interactive-worlds session receipt (`jwp-receipts.md`) applies unchanged: world identity over contract + tick-0 graph; the group's objects are the op batches, Merkle-bound; one Ed25519 seal (verified as SPEC §7 *Signatures* requires) over world hash + root + checkpoints + exact signed `work` + carried `joules_micro` (with its acquisition class as an optional signed label, [energy-measurement](energy-measurement.md) §2.8); `parent_receipt_hash` chains a performance's seals into a timeline. ## Appendix An avatar is the highest-bandwidth capture reduced to its instructions: a body in motion is a rig plus a stream of joint angles, and the standard carries the rig and the angles, not the pixels. Pose-equivalence makes the *motion* auditable — two parties to a call hold the same signed skeleton — while the *appearance* stays the sink's, skinned from a shared mesh. Sight (worlds), sound (mixdown), touch (sample), live state (feed), and now a moving body (pose) are one floor, one verification.