Runtime and ownership contract
All PAPER calls except getVersion, getModVersion, and isReady are
game-thread-only. Result-returning functions use WrongThread; older bool/count
queries fail closed. Do not call the provider from workers, render/physics
callbacks, arbitrary destructors or static teardown.
Callback lifetime
PAPER event callbacks run on its owner thread. The event record is borrowed only during that call; the consumer retains ownership of its callback code and userdata. Copy values, not event pointers. FrameComplete is the control/lease boundary for runtime, reload and motion observations. Final native-pose observation uses PresentationComplete, dispatched after ROCK's Presented phase publishes the final pose. It requires both FrameCallbacks and NativePosePipeline capabilities. This additional observation does not advance leases.
Owner lifetime
Consumer registration creates an owner token tied to a provider generation.
Unregistration removes callbacks, leases and authority owned by that token.
A normal RuntimeReset clears authority, capture leases and cached observations but preserves consumer registrations and event callbacks. Discard stale generation-dependent data and deliberately rearm activity. Full provider shutdown/reinitialization clears registrations; reconnect when that registration is actually gone rather than registering duplicate owners on every runtime reset.
Leases
Animation authority accepts zero for persistent-until-clear ownership, or a bounded frame lease up to 1200. Prefer renewable short leases for temporary coordination.
Development capture never accepts a persistent request. Its lease must be 1–1200 frames and the user's configuration remains the permission ceiling.
Cleanup
On the game thread: clear development capture and authority, unregister event callbacks, unregister the owner, then discard every retained sequence and provider-derived cache.