Versioned State
The Foresight Development Kit is built on a versioned object system where every state change is tracked and persistent.
Versioned Objects
Every object in a project is versioned. Instead of overwriting data, every change creates a new, immutable version of that object.
When you modify data, you are working in a local workspace. This allows you to experiment, undo, and refine your work before synchronizing your changes with the project’s authoritative state.
Local Undo/Redo vs. Committed Versions
The Foresight Development Kit distinguishes between local session history and the project’s global version history:
- Local Undo/Redo: As you work within a tool or session, every Statement you execute is tracked in a local undo stack. This allows for immediate, granular reversals of your recent actions.
- Committed Versions (Cloud Only): For projects stored in the cloud, when you “check in” or commit your changes, those local modifications are flattened into a new authoritative version in the project’s global history. Because the project is versioned at the object level rather than the project level, this enables extremely granular updates and seamless collaboration. This does not apply to local files, which are simply saved rather than committed.
Both systems are built on the same underlying architecture and use the same backwards-compatibility and migration tooling. This means a plugin developer only needs to define how an object is versioned once, and it automatically supports both local undo/redo and collaborative editing.
Workflow
A typical user journey through a versioned project follows a predictable sequence:
- Exploration: Data is streamed on-demand, allowing users to view the project state. They can use the Timeline widget to scrub through history and see how the project has changed over time.
- The Checkout: To start editing, a user checks out a subset of objects. This signals that the data is being modified in a local workspace.
- The Check-in (Cloud Only): Once finished with a cloud project, the user checks their changes back in. A new authoritative project version is created on the server, making the changes persistent and visible to others. Local projects do not require a check-in.
Object-Granular Versioning
The Foresight Development Kit uses a “Last Check-in Wins” strategy at the Object level for cloud projects. This means that if two users edit the same object, the last one to check in will define the current state of that object.
Because the SDK is built on versioned objects, no data is ever lost. If User B overwrites User A’s changes to a specific node, User A’s work still exists in the project’s global history. At any time, a user can navigate back to a previous project version to recover data or compare differences.
Defining Custom Objects
Developers can define their own versioned objects within plugins by implementing the FseObject and PersistentObject traits.
- Automatic Support: Once defined, your custom objects automatically gain support for local undo/redo and global versioning.
- Schema Migrations: The SDK provides tooling to implement legacy support, allowing you to migrate older versions of your custom objects to the latest schema as the project evolves. This ensures that data remains accessible across different versions of a plugin and the SDK.
Best Practices for Developers
To make the most of this engine, we recommend a few design patterns for your plugins:
- Prioritize Granularity: Instead of creating one large object, break data into many smaller, independent objects (e.g., individual buildings, survey points, or terrain patches). This reduces conflicts because users are less likely to edit the same object simultaneously.
- Composition over Inheritance: When extending the object model, prefer composing simple objects with clear responsibilities. This ensures each object owns a non-overlapping slice of the rendered ECS state.
- Encourage Frequent Check-ins (Cloud Only): For collaborative cloud projects, large, multi-day checkouts increase the likelihood of merge friction. Design your tools to encourage small, incremental updates.
- Leverage Statements: Use Statements for all state mutations. This ensures that changes are applied atomically and consistently.