Implementation type map and crate boundaries#
This guide is a reader-oriented map of the current implementation: where important types live, what they own, what crosses each crate boundary, and how authored objects become runtime state and finally GPU geometry. It is deliberately descriptive rather than normative. docs/architecture.md remains the sole architecture/roadmap authority.
The Rust public type is spelled Mobject. This document uses that spelling even when discussing the Manim/Python concept commonly called an “MObject”.
The two maps#
The first map follows one object from public authoring through semantic ownership, compilation, runtime evaluation, and renderer preparation. The D2 source is the useful maintenance artifact; the SVG is a reader preview.
The second map is the internal Cargo dependency graph. It is intentionally separate from the data-flow diagram: “crate A depends on crate B” and “data moves from layer A to layer B” are related but not identical statements.
D2 source: crate-dependencies.d2
One-minute mental model#
A useful way to read the code is:
Scene,Mobject,MobjectFamily, animation handles, signal handles, andLiveSessionare ergonomic authoring/orchestration handles innoon. They should not become a second scene model.SemanticStoreinnoon-coreis the authored Semantic Scene authority. AMobjectis only a store pointer plus a generationalSemanticNodeIdinto that store.noon-compilereads semantic state and derives an Execution Plan: execution identities/slots, compact values, tracks, reactive projections, painter order, and dependency-closed resources.ExecutionSessioninnoonowns the orchestration needed to keep that compiled projection coherent with oneSceneInstance; it does not own a second copy ofSemanticStore.SceneInstanceinnoon-runtimeowns the current effectiveFrameState. Authored/base state and effective/time-varying state are therefore different by construction.RendererPublicationgivesnoon-render-wgpuone coherent borrowed frame, its sparseFrameChanges, resource lookups, and publication context.- Analytic primitives become packed analytic instances.
VectorPathstays typed untilnoon-geometrytessellates it into mesh vertices/indices;noon-render-wgputhen packs and retains GPU buffers.
The most important rule for new code is: do not move an authority upward just because a lower layer has a convenient representation of the same object. ObjectId, frame indices, path cache indices, and GPU slots are all derived representations, not semantic identity.
Crate boundaries#
| Crate | Owns / is responsible for | Important types crossing its boundary | Direct internal dependencies |
|---|---|---|---|
noon-core |
Semantic identity/store, semantic object/family/signal/animation declarations, immutable resource arenas, renderer-independent compact value contracts | SemanticStore, SemanticNodeId, SemanticObjectState, SemanticObjectContent, StoredGeometry, GeometryResourceHandle, VectorPath, PathCommand, ObjectContentRef, GeometryRef, Transform2D, Style |
none |
noon-geometry |
Renderer-independent path algorithms: boolean operations, morphing, outlines, partial paths, smoothing, tessellation | consumes VectorPath; produces TessellatedPath, MeshVertex, path bounds/progress |
noon-core |
noon-compile |
Semantic-to-execution lowering, stable execution objects/slots, tracks, painter order, resource closure, incremental execution patches | SemanticExecutionIndex, SemanticExecutionProjection, SemanticExecutionObject, CompiledObject, CompiledScene, CompiledResources, ExecutionPatch |
noon-core, noon-geometry |
noon-runtime |
Deterministic effective evaluation, scheduler/reactive state, current frame, sparse invalidation, renderer publication | SceneInstance, FrameState, FrameObjectState, FrameChanges, RendererPublication, ExecutionSlotTable, RuntimeIdentity |
noon-core, noon-compile |
noon-render-wgpu |
Renderer preparation, packed instances, mesh residency/caching, painter-order draw preparation, WGPU resources/pipelines | consumes FrameState/RendererPublication; owns FramePreparer, PreparedFrame, packed analytic/path records |
noon-core, noon-geometry, noon-runtime, noon-text |
noon |
Public Rust authoring API and typed execution-session orchestration; shared high-level operations used by frontends | Scene, ScriptScene, SceneScript, Mobject, MobjectFamily, AnimationRequest, LiveSession, ExecutionSession, authoring options/errors |
noon-core, noon-geometry, noon-compile, noon-runtime; optional noon-text, noon-typst |
noon-text |
CPU text shaping and glyph raster services | shared text/font resource values from noon-core, shaped/rasterized glyph data for renderer consumers |
noon-core |
noon-typst |
Typst text/math layout provider | normalizes provider output into shared Noon resource/geometry types | noon-core |
noon-native |
Native window/event-loop/surface lifecycle and typed host execution | consumes public noon session/API and noon-render-wgpu |
noon, noon-core, noon-render-wgpu |
noon-web |
WASM/browser host integration and explicit cross-context transport where required | typed direct Rust/WASM path plus browser/worker transport adapters | noon, noon-core, noon-compile, noon-geometry, noon-runtime; target/feature-dependent noon-render-wgpu |
Notable external dependency placement is also intentional:
noon-coreis lightweight (serdeonly) so semantic contracts are reusable.noon-geometryisolateslyon_*andi_overlay.noon-render-wgpuisolateswgpu,bytemuck, and renderer-sideswashuse.noon-nativeisolateswinit, native WGPU backend selection, andpollster.noon-webisolateswasm-bindgen,web-sys,js-sys, transport codecs, and browser-target WGPU.noon-textisolates shaping/raster dependencies;noon-typstisolates the Typst toolchain.
Cargo dependency graph versus execution data flow#
The internal Cargo graph points from a consumer crate to crates it imports. The execution path reads in the opposite conceptual direction in several places: semantic values defined in noon-core are consumed by noon-compile, which is consumed by noon-runtime, which is consumed by the renderer. Keep those views separate when reasoning about ownership.
For example, noon-render-wgpu has a Cargo dependency on noon-runtime, but runtime state does not belong to the renderer. The renderer only receives a publication/observation of runtime state and builds disposable renderer-owned caches from it.
Mobject: what it actually is#
The public Rust handle is intentionally tiny. Its durable data is not stored in the handle:
#[derive(Clone, Debug)]
pub struct Mobject {
store: Rc<RefCell<SemanticStore>>,
id: SemanticNodeId,
}
Source: crates/noon/src/semantic_mobject.rs.
That definition has several consequences:
- Cloning the Rust handle clones the
Rcand the ID; it does not clone object geometry/state. - The ID is meaningful only with its originating store. Cross-store operations are rejected.
- Stale generational IDs fail validation instead of accidentally naming a later object that reused storage.
- Object queries read the current
SemanticObjectStatefrom the store. - Object edits stage canonical semantic mutations; the handle never becomes an independent mutable mirror.
Scene follows the same pattern. It owns the shared semantic arena, one family
root ID, an authoring cursor, and the optional execution component lowered from
that scene. The important ownership fields are:
| Field | Role |
|---|---|
store: Rc<RefCell<SemanticStore>> |
Shared authored semantic arena |
root: SemanticNodeId |
Scene's family root in that arena |
cursor: f64 |
Authoring cursor |
execution: Option<ExecutionSession> |
The scene's running execution component after bootstrap |
See crates/noon/src/scene.rs. Scene::circle, Scene::rectangle, Scene::line, Scene::path, text constructors, etc. create detached semantic nodes in that shared store; Scene::add changes membership of the existing node rather than copying it into a second scene container.
Construction path#
For geometry authoring, ManimGeometryOptions is inert typed input. It carries a GeometryRef, a high-precision SemanticTransform2_5D, SemanticStyle, and z_index, but it owns no semantic identity or runtime state.
The important construction sequence is:
Scene constructor / ManimGeometryOptions
↓
Mobject::from_manim_geometry(...)
↓
ManimGeometryOptions::into_state(store)
↓
import_geometry(store, GeometryRef)
↓
SemanticObjectState
↓
SemanticMutationTransaction::add_node(...)
↓
SemanticStore allocates SemanticNodeId
↓
Mobject { store, id }
Mobject::new gets the permanent identity from the committed transaction result. That is why code should not invent IDs in facade/frontend layers.
Mutation path#
Most persistent Mobject methods follow the same shape:
- validate the handle;
- read the current
SemanticObjectState; - modify a local copy/value;
commit_statecomputes the semantic differences;stage_state_changesemits canonical transaction operations such asreplace_content,set_property, orreplace_style;- the transaction applies atomically to
SemanticStore.
Raw handle edits are authored operations. Ordinary persistent edits use
Scene::set_color, Scene::set_fill, Scene::set_fill_opacity,
Scene::set_stroke_width, and Scene::shift
before and after Scene-owned execution bootstrap. These methods prepare the same
shared semantic transaction and pass it through Scene::apply_semantic_transaction;
running execution validates and publishes its derived changes atomically.
ScriptScene delegates these edits to that Scene without choosing a cold or live
feature API. Authored/base queries and coherent effective queries remain explicit.
Scene::add_family_members and Scene::remove_family_members prepare the existing
shared family membership transaction and use that same publication route. Family
creation, linear/grid arrangement, and anchored placement also remain Scene-owned
operations. Scene::effective_layout and the external LiveSession query share
one object-layout implementation, including descendant traversal and render-override
admission; effective_family_layout uses the existing family query. These queries
observe a coherent publication and do not store a second bounds representation.
Scene::live(&mut session) is for an explicitly borrowed external execution
component and callback/host integration. Raw mutable store access is an
integration escape hatch, not a live-edit API.
Semantic object representation#
A semantic object is not represented by one giant Mobject record. The key types are split by purpose.
Identity and node topology#
SemanticNodeId is the scene-global generational semantic identity. SemanticStore owns an arena of SemanticNodes. SemanticNodeKind distinguishes object, family, signal, and animation nodes, while the node also carries membership/parentage and other topology needed by the semantic scene.
This identity is the one callers should preserve across semantic operations. Lower layers may derive keys/indices from it, but they do not replace it as authored identity.
Object state#
SemanticObjectState is the authoritative authored object payload. Conceptually:
SemanticObjectState
├── content: SemanticObjectContent
├── transform: SemanticTransform2_5D # f64, authored/base
├── style: SemanticStyle # authored paint/stroke/opacity
├── presentation: SemanticPresentation # z-index/insertion ordering
├── role: SemanticObjectRole
└── signal_bindings: Vec<SemanticSignalBinding>
Bounds are intentionally derived rather than stored as another source of truth.
Content and geometry resources#
SemanticObjectContent is currently either:
Geometry(StoredGeometry)
Text(TextResourceHandle)
StoredGeometry deliberately treats cheap analytic values and heavy path payloads differently:
pub enum StoredGeometry {
Circle { radius: f32 },
Rectangle { size: Vec2 },
Line { start: Vec2, end: Vec2 },
Resource(GeometryResourceHandle),
}
A GeometryResourceHandle includes the owning arena namespace, a generational GeometryId, and a resource version. The arena stores immutable GeometryResource::VectorPath(Arc<VectorPath>) payloads. Replacing a resource can keep its stable ID while incrementing the version, which invalidates old snapshots/caches cleanly.
This is why a large path is not copied into every semantic object or track snapshot: the semantic layer copies a small versioned handle while the heavy immutable path stays arena-owned.
Identity ladder: do not confuse these IDs#
| Identity / index | Layer | Meaning | Stable semantic identity? |
|---|---|---|---|
SemanticNodeId |
Semantic Scene | generational ID for object/family/signal/animation node in one SemanticStore |
yes |
GeometryResourceHandle |
Semantic resources | arena + generational GeometryId + immutable resource version |
resource identity, not object identity |
ObjectId from SemanticExecutionIndex |
Compiler | derived compatibility key accepted by the current compiled/runtime object domain | no; do not expose as new authoring identity |
| compiled object slot / object index | Execution Plan | stable/tombstoned storage location used by compiled/runtime structures | no |
RuntimeIdentity |
Runtime | identifies one mutable SceneInstance incarnation/session runtime |
no; identifies runtime, not object |
FrameState row index |
Runtime observation | dense effective row for current compiled slot domain | no |
FramePreparer instance index / path cache index |
Renderer | packing/cache bookkeeping for a prepared frame | no |
| WGPU buffer offsets / draw batch indices | Renderer/device | disposable GPU submission/storage positions | no |
SemanticExecutionIndex is explicitly a compiler-owned bridge from SemanticNodeId to the existing ObjectId domain. New semantic APIs should not grow around ObjectId merely because it is convenient in compile/runtime code.
Precision and representation ladder#
Another common source of confusion is seeing similarly named values with different precision/semantics:
| Stage | Transform/style representation | Why |
|---|---|---|
| Semantic authored/base | SemanticTransform2_5D + SemanticStyle |
high-precision authored semantics, 2.5D-compatible shape |
| Compile/runtime execution | Transform2D + Style |
compact execution-facing values; lowering validates finite/range constraints |
| Renderer upload | PackedTransform + PackedStyle |
WGPU-friendly POD layout |
Lowering from semantic values is explicit. For example SemanticVec3::lower_xy_f32 and compile-side scalar lowering reject non-finite/out-of-range values instead of silently changing meaning.
End-to-end path: Mobject to actual GPU path#
This is the concrete trace for a vector path, including the representations that are easy to miss when reading only one crate.
1. Authoring starts with typed VectorPath#
VectorPath and PathCommand live in noon-core. A path owns an ordered command stream (MoveTo, LineTo, QuadraticTo, CubicTo, Close) plus optional morph-target data. Scene::path passes it through ordinary shared Rust authoring.
At this boundary ManimGeometryOptions/constructor helpers may use GeometryRef::VectorPath as input vocabulary. That does not mean GeometryRef is the persistent semantic storage model.
2. Authoring imports heavy geometry into the semantic resource arena#
semantic_mobject::import_geometry converts constructor GeometryRef into persistent StoredGeometry:
GeometryRef::Circle → StoredGeometry::Circle (inline)
GeometryRef::Rectangle → StoredGeometry::Rectangle (inline)
GeometryRef::Line → StoredGeometry::Line (inline)
GeometryRef::VectorPath → insert path in arena
→ StoredGeometry::Resource(handle)
GeometryRef::External → rejected by ordinary authoring
For a path, the heavy payload becomes GeometryResource::VectorPath(Arc<VectorPath>); the semantic object retains only the versioned handle.
3. The semantic node owns the authored object state#
The committed object node points to SemanticObjectState, whose content is SemanticObjectContent::Geometry(StoredGeometry::Resource(handle)). Mobject itself still owns only (store, SemanticNodeId).
4. noon-compile derives an execution projection#
SemanticExecutionIndex::lower_scene/lower_root traverses visible semantic leaves and produces SemanticExecutionObjects. This step:
- preserves the authoritative
semantic_id; - derives the current compatibility
ObjectId; - carries semantic content/resource handles forward long enough to validate/resolve them;
- lowers high-precision transforms/styles into compact
Transform2D/Style; - preserves presentation and authored signal-binding information needed by later lowering.
Importantly, lowering validates all visible objects before mutating the semantic-to-execution identity index, so a late failure cannot publish a partially updated mapping.
5. CompiledScene materializes renderer-independent execution content#
During compiled-scene materialization, lower_content resolves StoredGeometry using the originating store/resource closure:
StoredGeometry::Circle/Rectangle/Line
→ matching GeometryRef analytic value
StoredGeometry::Resource(handle)
→ GeometryResourceArena lookup(handle)
→ GeometryResource::VectorPath(Arc<VectorPath>)
→ GeometryRef::VectorPath(VectorPath)
The resulting CompiledObject contains an ObjectContentRef (Geometry(GeometryRef) or Text(handle)), compact transform/style, execution key, and dynamic/live metadata. CompiledScene owns the stable/tombstoned execution slot domain, tracks, painter order, and dependency-closed immutable resources.
This is the boundary where semantic resource identity is resolved into a renderer-independent execution value. The renderer still does not know about Mobject, SemanticNode, or SemanticStore.
6. Runtime owns the current effective row#
SceneInstance is created from the compiled plan and owns the current FrameState. Each FrameObjectState contains:
ObjectId
ObjectContentRef
Transform2D
Style
z_index / appearance
Parallel arrays hold presence, reveal, morph, family-animation state, and optional derived render geometry/transform overrides. FrameState::render_geometry(i) selects a temporary derived render geometry when an animation needs one; otherwise it returns the object's ordinary geometry.
That override is derived animation state. It does not replace the semantic object's persistent content.
7. Runtime publishes one coherent renderer observation#
SceneInstance::take_renderer_publication() bundles:
&FrameState;- accumulated sparse
FrameChanges; - publication/revision context;
- immutable text/font/geometry resource lookups;
- family-animation plans and painter order.
RendererPublication is borrowed and coherent. It is not a second retained render-world model.
8. Renderer splits analytic and vector-path preparation#
noon-render-wgpu::FramePreparer reads effective frame.render_geometry(object_index).
Analytic primitives avoid general tessellation:
Circle → CircleInstance
Rectangle → RectangleInstance
Line → LineInstance
A GeometryRef::VectorPath enters the path preparation/cache branch.
9. noon-geometry tessellates the typed path#
On a path cache miss, renderer preparation calls noon-geometry tessellation. The tessellator converts PathCommands into Lyon paths and produces:
TessellatedPath
├── vertices: Vec<MeshVertex>
│ ├── position
│ ├── target_position # morph endpoint when relevant
│ ├── surface: Fill | Stroke
│ ├── path_distance
│ └── path_progress
├── indices: Vec<u32>
├── bounds
├── stroke_length
├── morphing
└── cached reveal measure
Stroke join/cap/width and fill participation are inputs to tessellation. For screen-space strokes, renderer preparation may bake scale/rotation (not translation) into the tessellation path so stroke width semantics remain screen-space. Morphing can use the order-preserving tessellation variant required by compatibility behavior.
10. Renderer packs mesh residency and WGPU upload data#
noon-render-wgpu converts tessellated mesh data into its own retained GPU-facing representation:
PathVertex(position,target_position, packed surface/progress metadata);PathInstance(packed transform/style + reveal/morph parameters);- path index streams and batches;
- unique-path/mega-mesh residency/cache records;
- WGPU vertex/index/instance buffers and ordered draw metadata.
Renderer cache keys and buffer offsets are disposable optimization details. Changing a transform/color should not force path retessellation when the geometry/tessellation inputs did not change.
11. There is no canonical SVG-path lowering step#
The direct native/browser renderer path is:
PathCommand
→ VectorPath
→ semantic geometry resource handle
→ compiled GeometryRef::VectorPath
→ runtime effective geometry
→ TessellatedPath
→ PathVertex/index buffers
→ WGPU draw
It does not lower through an SVG d string. SVG/debug/export representations, where present, are explicit codecs or diagnostics rather than the engine's canonical execution boundary.
Execution/session types around the object path#
SceneScript and ScriptScene#
Scene::script adapts an ordinary compiled Rust future to sequential authoring.
SceneScript owns that source and its host callback table. ScriptScene is a weak,
scoped capability: each synchronous operation borrows the same Scene only while
the source is being polled. It contains no independent semantic state and cannot
retain a stopped source. Persistent edits delegate to Scene-owned operations.
Family construction accepts borrowed object collections or mixed MobjectTarget
collections. Scene attachment/detachment accepts either an object or a family;
family membership, linear/grid arrangement, anchored placement, and effective
layout queries delegate to the same shared operations. The capability does not
copy family topology or perform its own layout traversal. The existing nested,
aliased family-arrangement example runs as one sequential source on native and
direct Rust/WASM hosts.
play and wait yield the existing LiveProgram completion/publication boundary.
An owned AnimationRequest retains handles and requested edits, then captures
effective state when play admits it. It allocates no semantic target or animation
identity while being constructed. The shared composition transaction stages and
publishes those identities atomically at admission.
ExecutionSession#
ExecutionSession is the typed orchestration bridge between the authored store and one runtime. Its fields are deliberately derived/runtime structures: store identity, SemanticExecutionIndex, reachability, execution slots, spatial index, reactive projection, signal timeline, one SceneInstance, callback/completion state, etc.
It explicitly does not own or mirror SemanticStore. This matters for live mutation: semantic transactions remain the source of authored truth; execution publication updates the derived execution/runtime state only after preparation succeeds.
LiveSession#
Scene::live(&mut ExecutionSession) returns the borrowed execution facade for
external-session and callback/host integration. It supplies capabilities such as
explicit animation activation/completion, and retains operations required by
those integration callers. Ordinary supported construction, membership, persistent
edits and queries use Scene-owned routes; sequential sources use ScriptScene.
The facade should not accumulate a parallel scene model. If a new live feature seems to require copying semantic state into LiveSession, look for a semantic transaction + lowering/publication solution first.
SceneInstance#
SceneInstance is runtime authority, not semantic authority. It owns the compiled plan it is executing, the current FrameState, scheduling/group cursors, reactive runtime, sparse invalidation, publication context, and active derived animation state. Seeking/advancing changes this effective state without rewriting authored semantic declarations.
Other important type families#
The same boundary pattern applies beyond geometry.
| Domain | Semantic/authored types | Compile/runtime derived types | Notes |
|---|---|---|---|
| Families / membership | SemanticNodeId, family SemanticNodeKind, ordered members/parents in SemanticStore; public MobjectFamily handle |
reachability, painter order/ranks, execution slots | family topology belongs to semantic scene; runtime observes derived flattened order |
| Animation | semantic animation nodes/declarations, public declared animation handles/options | compiled tracks/channels/family plans, runtime scheduler/group state, frame reveal/morph/temporary render overrides | animation declarations are not frame state; frame state is not authored truth |
| Signals / reactive state | semantic signal nodes, SemanticSignalBinding, native/host source declarations |
SemanticReactiveProjection, runtime reactive program/state and dirty closure |
signal identity stays semantic; execution slots are derived |
| Text | TextResourceHandle, font/text resources and semantic content handles |
CompiledResources, frame text handles/bounds, noon-text shaping/raster output, renderer atlas entries |
text/font resource closure is captured during lowering; renderer atlas IDs are not semantic IDs |
| Presentation/order | SemanticPresentation (z_index, insertion order) |
compiled painter order/ranks; runtime order updates; renderer ordered batches/chunks | transform/style should not become an ordering authority |
| Camera | canonical semantic camera object | derived ObjectId/effective frame camera values |
camera value is read from effective runtime state, not retained as a separate host-owned scene |
Source index: where to start reading#
For a code-first walkthrough, these files give the shortest route through the system:
crates/noon/src/scene.rs— scene/store/root ownership and public factories.crates/noon/src/semantic_mobject.rs—Mobject, geometry import, persistent object mutations.crates/noon-core/src/semantic_store.rs— semantic arena/topology and transactions.crates/noon-core/src/semantic_store/semantic_model.rs—SemanticNode,SemanticObjectState, high-precision semantic values.crates/noon-core/src/semantic_store/object_content.rs— semantic content and loweredObjectContentRefvocabulary.crates/noon-core/src/resources/geometry.rs—StoredGeometry, versioned geometry handles, immutable path resource arena.crates/noon-compile/src/semantic_lowering/projection.rs— semantic identity/value projection into execution-facing objects.crates/noon-compile/src/semantic_lowering/compiled_scene.rs— resource resolution andCompiledObject/CompiledScenematerialization.crates/noon/src/execution_session.rs— typed semantic/execution orchestration.crates/noon-runtime/src/frame.rs— effective frame rows and render overrides.crates/noon-runtime/src/renderer_publication.rs— coherent frame/change/resource publication.crates/noon-geometry/src/tessellation.rs— typed path → mesh conversion.crates/noon-render-wgpu/src/lib.rs— frame preparation, analytic packing, path mesh caching/packing.- Workspace and per-crate
Cargo.tomlfiles — actual dependency edges; use them rather than inferring dependencies from call flow.
Where should a new type or behavior go?#
Use this as a practical placement check:
| If the change is primarily about… | Start in… | Avoid putting it in… |
|---|---|---|
| authored identity, topology, persistent content/style/transform, semantic invariants | noon-core semantic store/model |
renderer, host wrappers |
| public Rust ergonomics or a shared high-level authoring operation | noon |
Python/browser-only facade code |
| translating semantic declarations into execution slots/tracks/resources | noon-compile |
runtime or renderer caches |
| time evaluation, effective state, scheduling, reactive propagation, sparse dirty state | noon-runtime |
semantic store |
| path algorithms/tessellation independent of GPU API | noon-geometry |
WGPU renderer |
| GPU packing, mesh residency, batches, shaders, dirty uploads | noon-render-wgpu |
semantic/compile layers |
| native window/surface/event lifecycle | noon-native |
renderer core |
| browser/WASM/platform or genuine cross-worker transport | noon-web |
semantic authority |
| text shaping/raster provider work | noon-text |
core semantic store beyond shared resource contracts |
| Typst compilation/layout provider work | noon-typst |
renderer/runtime |
If a change seems to need state in two authority layers, first ask whether one copy can instead be a derived projection, handle, immutable resource reference, or bounded cache.
Common traps for readers and contributors#
Mobjectis not the object record. It is(store, SemanticNodeId).GeometryRefhas more than one role. It is convenient typed geometry input and the renderer-independent execution geometry value, but persistent semantic heavy-path storage isStoredGeometry::Resource(handle).ObjectIdis not the new semantic ID. It is currently a derived compiler/runtime compatibility key.- A runtime frame is not authored truth.
FrameStateis the effective result at a particular time/publication. - A renderer cache is not runtime truth.
PreparedFrame, mesh residency, instance indices, and GPU buffers are disposable renderer state. - Temporary render geometry is not persistent
become()state. Animation-time correspondence can produce derivedrender_geometries; persistent semantic topology/content changes still go through semantic publication. - Cargo dependency direction is not ownership direction. A crate can depend on another crate's types without taking ownership of that layer's authority.
- Serialization is not the normal in-process boundary. Native and single-context Rust/WASM paths should continue passing typed Rust values directly; codecs belong at explicit wire/storage boundaries.
- Do not bypass resource handles for heavy semantic paths. They exist to keep immutable payload ownership bounded and versioned.
Keeping this guide current#
This file should change when implementation types or crate handoffs move, not when a new roadmap decision is made. Architectural decisions belong in docs/architecture.md.
When updating the guide:
- re-check the current
Cargo.tomlgraph; - trace the concrete types rather than relying on older diagrams/comments;
- keep
SemanticNodeIdversus derived execution/renderer identities explicit; - update the D2 source beside the affected map;
- refresh the reader SVG preview;
- avoid turning this document into a second architecture roadmap.