Skip to main content
Coming soon — experimental API 0.3. This page documents the development contract. See availability and scope.

Handle types

Handle<Tag> wraps a std::uint64_t token. The public aliases are DocumentHandle, WorkspaceHandle, PartHandle, AvatarHandle, and DialogHandle. Zero is invalid. Handles support equality, inequality, and an explicit boolean check. Treat a token as opaque. It is not a pointer, a ForgeCore registry ID, or an index into a snapshot vector. Do not perform arithmetic on it or resolve it through internal engine systems. Document, workspace, and part handles belong to the session that issued them and the current document incarnation. Opening or replacing a document invalidates its old identities. When a removed part disappears from a refreshed snapshot, its handle is retired. Refresh and reacquire handles after deletion or history changes; an object restored by undo can receive a new handle. Dialog handles identify UI registrations owned by a session. Use CloseDialog to release a registration. The host closes document dialogs when the costume resets, and session cleanup disposes its dialogs. Replacing the avatar retires its AvatarHandle even if the costume stays open. Measurement and tool identifiers are strings discovered from their catalogs; they are not C++ object handles. Do not save handles in project data or exchange them between sessions. Names are display text, not durable identities. There is no persistent object ID API in 0.3.

Revision checks

Revision is a std::uint64_t. A document snapshot includes its session’s current revision. The revision advances when the host observes a changed document snapshot. It is a coarse invalidation value, not a count of commands or a revision shared by every session. Every persistent mutation requires a nonzero expected_revision equal to the current document revision. Zero never means “ignore conflicts.” Use the revision from the snapshot on which you based the edit. Tool activation also requires this revision even though it creates no undo entry. Avatar values, viewport changes, and active-tool changes participate in observation invalidation.
  1. Read the document.
  2. Choose a handle from that snapshot and check its eligibility.
  3. Submit a command with that document handle and revision.
  4. Read a fresh snapshot after the command.
On RevisionConflict, refresh the document and reassess the edit. Do not blindly substitute a new revision and retry an operation whose assumptions may have changed. PartInfo.geometry_revision and MeshInfo.geometry_revision describe observed mesh geometry changes. They do not replace the document revision required by a command.

Result and error types

Each session method returns Result<T>, containing value and error. Its explicit boolean conversion succeeds only when error.code == ErrorCode::None. On failure, do not use value as a valid response. Error contains an ErrorCode code and a human-readable std::string message. Use the code for decisions. Messages can change and should not be parsed as identifiers. The host may report one of several applicable errors according to its validation order. Do not rely on error precedence.

Command completion and readback

RenamePart, StretchMesh, Undo, and Redo return Result<CommandResult>. A command can complete successfully while its subsequent readback fails. In that case the outer result remains successful, revision is zero, and refresh_error explains the readback failure. Do not repeat the command. Obtain a fresh snapshot when the host can read again.

Thread and state rules

Call all session methods on the thread that owns the session. Workers receive copied values, not a live session. Do not hold references to ForgeCore objects across a command or call into the API from an internal, unfinished command callback. The native host rejects reads or mutations during operations that prevent a consistent snapshot, such as loading, file processing, autosaving, printing, reset, or nested command execution. Use Busy as a signal to wait for the host to finish its current work.