Documentation
    Preparing search index...

    Interface AuthorityNode

    Transform authority (§42).

    §42's rule is short and absolute: exactly one system owns a node's transform at a time, and "the engine must prevent multiple systems from silently overwriting the same transform". This module holds the vocabulary for that ownership (TransformAuthority) and the enforcement primitive every writing system shares (warnAuthorityConflict); the field itself lives on Node (§42 writes node.transformAuthority = "physics"), see Node.transformAuthority.

    §42 says conflicts "should produce development warnings" and that a warning "fires whenever a system writes a transform it does not own". A warning alone would still leave the transform overwritten — the very thing §42's first sentence forbids — so the engine pairs the two halves: the owner keeps the transform and the non-owner's write is refused. A refused write is loud (a console.warn) and lossless in the other direction: nothing about the owner's state is touched, so authority conflicts can never corrupt a simulation, only stall the system that mis-declared itself.

    The check belongs to the writer, not to Transform: transforms are written through plain math methods on hot paths (transform.position.set(...), plan D3), and gating every one of those on an ownership test would put a branch inside the innermost loop in the engine and still be trivially bypassable. Each system instead tests once per node per step, immediately before it would write — the shape warnAuthorityConflict is built for.

    A conflicting system conflicts every fixed step — 60 identical lines per second per node is noise that hides the first one. Warnings are therefore emitted once per node per writing authority and suppressed afterwards, tracked in a module-level WeakMap keyed by node so the bookkeeping dies with the node and holds nothing alive. Two different authorities fighting over one node produce two warnings, which is the point: each names a distinct mis-configured system.

    writer is a TransformAuthority rather than a free-form system name (decision, WP-2.3) because §42 identifies writers by the authority they claim — MotionSystem writes as "kinematic", a solver as "physics" — which keeps the value typo-checked and makes the suppression key the same vocabulary as the field being violated. Two systems that both claim "kinematic" over one node therefore share a suppression slot; they are, by §42's model, the same writer.

    The message is unconditional console.warn — not DEV / devWarnOnce. @fourjs/scene is a §33 simulation package: dev-build-mode.test.ts forbids any build-flag import here (the same reason a DEV-gated new Node() warn was reverted). The WeakMap is the once-per-pair suppress; production prints the first conflict and then stays quiet.

    Application writes on a system-owned node are a different contract (2026-10-05): they land, and a DEV build warns once. That hook lives on Transform.markDirty and is skipped inside runOwnedTransformWrite, which every writing system wraps its owned pose with. The DEV test is inlined (typeof __FOUR_DEV__) so this module still does not import DEV.

    interface AuthorityNode {
        id: string;
        name: string;
        transformAuthority: TransformAuthority;
    }
    Index
    id: string

    Node.id — stable identity for the warning and its suppression.

    name: string

    Node.name — empty when unnamed; used only to label the warning.

    transformAuthority: TransformAuthority

    Node.transformAuthority — the §42 owner being violated.