diff --git a/src/GameCult.Mesh/CultMesh.cs b/src/GameCult.Mesh/CultMesh.cs
index 9cc40ca2..b4e93588 100644
--- a/src/GameCult.Mesh/CultMesh.cs
+++ b/src/GameCult.Mesh/CultMesh.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
@@ -297,6 +298,796 @@ namespace GameCult.Mesh
return new CultMeshStreamCatalog();
}
+ ///
+ /// Creates a managed Verse context for generated domain sugar.
+ ///
+ public static CultMeshVerse Verse(
+ string verseId,
+ string runtimeId,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? claims = null)
+ {
+ return new CultMeshVerse(new CultMeshVerseContext(verseId, runtimeId, routeHint, claims));
+ }
+
+ ///
+ /// Creates a managed Verse context for generated domain sugar.
+ ///
+ public static Task ConnectVerseAsync(
+ string verseId,
+ string runtimeId,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? claims = null)
+ {
+ return Task.FromResult(Verse(verseId, runtimeId, routeHint, claims));
+ }
+
+ ///
+ /// Starts a fluent typed operation context for one runtime.
+ ///
+ public static CultMeshOperationContextBuilder OperationContextFor(string runtimeId)
+ {
+ return new CultMeshOperationContextBuilder(runtimeId);
+ }
+
+ ///
+ /// Starts a fluent typed query context for one runtime.
+ ///
+ public static CultMeshQueryContextBuilder QueryContextFor(string runtimeId)
+ {
+ return new CultMeshQueryContextBuilder(runtimeId);
+ }
+
+ ///
+ /// Binds a typed operation handle to a Verse context.
+ ///
+ public static CultMeshBoundOperationHandle BindOperation(
+ CultMeshVerseContext context,
+ CultMeshOperationHandle operation)
+ {
+ return new CultMeshBoundOperationHandle(context, operation);
+ }
+
+ ///
+ /// Binds a typed operation handle to a Verse.
+ ///
+ public static CultMeshBoundOperationHandle BindOperation(
+ CultMeshVerse verse,
+ CultMeshOperationHandle operation)
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return BindOperation(verse.Context, operation);
+ }
+
+ ///
+ /// Binds a typed query surface to a Verse context.
+ ///
+ public static CultMeshBoundQuerySurface BindQuery(
+ CultMeshVerseContext context,
+ CultMeshQuerySurface query)
+ {
+ return new CultMeshBoundQuerySurface(context, query);
+ }
+
+ ///
+ /// Binds a typed query surface to a Verse.
+ ///
+ public static CultMeshBoundQuerySurface BindQuery(
+ CultMeshVerse verse,
+ CultMeshQuerySurface query)
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return BindQuery(verse.Context, query);
+ }
+
+ ///
+ /// Binds a typed live feed to a Verse context.
+ ///
+ public static CultMeshBoundLiveFeed BindLiveFeed(
+ CultMeshVerseContext context,
+ CultMeshLiveFeed feed)
+ {
+ return new CultMeshBoundLiveFeed(context, feed);
+ }
+
+ ///
+ /// Binds a typed live feed to a Verse.
+ ///
+ public static CultMeshBoundLiveFeed BindLiveFeed(
+ CultMeshVerse verse,
+ CultMeshLiveFeed feed)
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return BindLiveFeed(verse.Context, feed);
+ }
+
+ ///
+ /// Binds a typed document live feed to a Verse context.
+ ///
+ public static CultMeshDocumentHandle BindDocument(
+ CultMeshVerseContext context,
+ CultMeshLiveFeed feed)
+ where TDocument : class
+ {
+ return new CultMeshDocumentHandle(BindLiveFeed(context, feed));
+ }
+
+ ///
+ /// Binds a typed document live feed to a Verse.
+ ///
+ public static CultMeshDocumentHandle BindDocument(
+ CultMeshVerse verse,
+ CultMeshLiveFeed feed)
+ where TDocument : class
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return BindDocument(verse.Context, feed);
+ }
+
+ ///
+ /// Binds a typed state pointer to a Verse context.
+ ///
+ public static CultMeshBoundStatePointer BindStatePointer(
+ CultMeshVerseContext context,
+ CultMeshStatePointer pointer)
+ {
+ return new CultMeshBoundStatePointer(context, pointer);
+ }
+
+ ///
+ /// Binds a typed state pointer to a Verse.
+ ///
+ public static CultMeshBoundStatePointer BindStatePointer(
+ CultMeshVerse verse,
+ CultMeshStatePointer pointer)
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return BindStatePointer(verse.Context, pointer);
+ }
+
+ ///
+ /// Binds a mutable typed state pointer to a Verse context.
+ ///
+ public static CultMeshBoundMutableStatePointer BindMutableStatePointer(
+ CultMeshVerseContext context,
+ CultMeshMutableStatePointer pointer)
+ {
+ return new CultMeshBoundMutableStatePointer(context, pointer);
+ }
+
+ ///
+ /// Binds a mutable typed state pointer to a Verse.
+ ///
+ public static CultMeshBoundMutableStatePointer BindMutableStatePointer(
+ CultMeshVerse verse,
+ CultMeshMutableStatePointer pointer)
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return BindMutableStatePointer(verse.Context, pointer);
+ }
+
+ ///
+ /// Creates a typed state pointer to Verse state.
+ ///
+ public static CultMeshStatePointer StatePointer(
+ string pointerId,
+ Func> resolve,
+ Func> watch,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? sources = null)
+ {
+ return new CultMeshStatePointer(
+ pointerId,
+ resolve,
+ watch,
+ routeHint,
+ sources);
+ }
+
+ ///
+ /// Creates a typed state pointer to Verse state that can resolve through a query context.
+ ///
+ public static CultMeshStatePointer StatePointer(
+ string pointerId,
+ Func> resolve,
+ Func> watch,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? sources = null)
+ {
+ return new CultMeshStatePointer(
+ pointerId,
+ resolve,
+ watch,
+ routeHint,
+ sources);
+ }
+
+ ///
+ /// Creates a mutable typed state pointer to Verse state.
+ ///
+ public static CultMeshMutableStatePointer MutableStatePointer(
+ string pointerId,
+ Func> resolve,
+ Func> watch,
+ Func replace,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? sources = null)
+ {
+ return new CultMeshMutableStatePointer(
+ pointerId,
+ resolve,
+ watch,
+ replace,
+ routeHint,
+ sources);
+ }
+
+ ///
+ /// Creates a mutable typed state pointer to Verse state that can operate through a query context.
+ ///
+ public static CultMeshMutableStatePointer MutableStatePointer(
+ string pointerId,
+ Func> resolve,
+ Func> watch,
+ Func replace,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? sources = null)
+ {
+ return new CultMeshMutableStatePointer(
+ pointerId,
+ resolve,
+ watch,
+ replace,
+ routeHint,
+ sources);
+ }
+
+ ///
+ /// Creates a typed projection source descriptor.
+ ///
+ public static CultMeshProjectionSource ProjectionSource(
+ string sourceId,
+ string? schemaId = null,
+ string? description = null)
+ {
+ return new CultMeshProjectionSource(sourceId, schemaId, description);
+ }
+
+ ///
+ /// Creates a named state-reference resolver for portable UI/tool surfaces.
+ ///
+ public static CultMeshStateRefResolver StateRefResolver(
+ string resolverId,
+ Func resolve,
+ IEnumerable? sources = null,
+ CultMeshRouteHint? routeHint = null)
+ {
+ if (resolve == null) throw new ArgumentNullException(nameof(resolve));
+ return new CultMeshStateRefResolver(
+ resolverId,
+ (stateRef, _context) => resolve(stateRef),
+ sources,
+ routeHint);
+ }
+
+ ///
+ /// Creates a named state-reference resolver for portable UI/tool surfaces.
+ ///
+ public static CultMeshStateRefResolver StateRefResolver(
+ string resolverId,
+ Func resolve,
+ IEnumerable? sources = null,
+ CultMeshRouteHint? routeHint = null)
+ {
+ return new CultMeshStateRefResolver(resolverId, resolve, sources, routeHint);
+ }
+
+ ///
+ /// Describes a state-reference resolver for catalogs and tools.
+ ///
+ public static CultMeshStateRefResolverDiagnostic DescribeStateRefResolver(
+ CultMeshStateRefResolver resolver)
+ {
+ if (resolver == null) throw new ArgumentNullException(nameof(resolver));
+ return new CultMeshStateRefResolverDiagnostic(
+ resolver.ResolverId,
+ resolver.RouteHint,
+ resolver.Sources);
+ }
+
+ ///
+ /// Creates a UI/tool binding descriptor from a component property to a typed state pointer.
+ ///
+ public static CultMeshStateBindingDescriptor StateBinding(
+ string targetProp,
+ CultMeshStatePointer pointer)
+ {
+ return CultMeshStateBindingDescriptor.FromPointer(targetProp, pointer);
+ }
+
+ ///
+ /// Creates a UI/tool binding descriptor from a component property to a mutable typed state pointer.
+ ///
+ public static CultMeshStateBindingDescriptor StateBinding(
+ string targetProp,
+ CultMeshMutableStatePointer pointer)
+ {
+ if (pointer == null) throw new ArgumentNullException(nameof(pointer));
+ return CultMeshStateBindingDescriptor.FromPointer(targetProp, pointer.AsStatePointer());
+ }
+
+ ///
+ /// Creates a UI/tool binding descriptor from a component property to a state pointer id.
+ ///
+ public static CultMeshStateBindingDescriptor StateBinding(
+ string targetProp,
+ string pointerId,
+ string? sourceId = null,
+ string? schemaId = null,
+ CultMeshRouteHint? routeHint = null)
+ {
+ return new CultMeshStateBindingDescriptor(targetProp, pointerId, sourceId, schemaId, routeHint);
+ }
+
+ ///
+ /// Creates transport-friendly fields from a state binding descriptor.
+ ///
+ public static CultMeshStateBindingRecord StateBindingRecord(CultMeshStateBindingDescriptor? binding)
+ {
+ return CultMeshStateBindingRecord.FromBinding(binding);
+ }
+
+ ///
+ /// Creates transport-friendly state binding fields directly.
+ ///
+ public static CultMeshStateBindingRecord StateBindingRecord(
+ string? targetProp,
+ string? pointerId,
+ string? sourceId = null,
+ string? schemaId = null,
+ string? routeKind = null,
+ string? routeDescription = null)
+ {
+ return new CultMeshStateBindingRecord(
+ targetProp,
+ pointerId,
+ sourceId,
+ schemaId,
+ routeKind,
+ routeDescription);
+ }
+
+ ///
+ /// Creates a UI/tool command binding descriptor from a typed operation handle.
+ ///
+ public static CultMeshOperationBindingDescriptor OperationBinding(
+ CultMeshOperationHandle operation,
+ string? label = null,
+ string? schemaId = null,
+ CultMeshRouteHint? routeHint = null)
+ {
+ return CultMeshOperationBindingDescriptor.FromOperation(operation, label, schemaId, routeHint);
+ }
+
+ ///
+ /// Creates a UI/tool command binding descriptor from a typed operation id.
+ ///
+ public static CultMeshOperationBindingDescriptor OperationBinding(
+ string operationId,
+ string? label = null,
+ string? schemaId = null,
+ CultMeshRouteHint? routeHint = null)
+ {
+ return new CultMeshOperationBindingDescriptor(operationId, label, schemaId, routeHint);
+ }
+
+ ///
+ /// Creates transport-friendly fields from an operation binding descriptor.
+ ///
+ public static CultMeshOperationBindingRecord OperationBindingRecord(
+ CultMeshOperationBindingDescriptor? binding)
+ {
+ return CultMeshOperationBindingRecord.FromBinding(binding);
+ }
+
+ ///
+ /// Creates transport-friendly operation binding fields directly.
+ ///
+ public static CultMeshOperationBindingRecord OperationBindingRecord(
+ string? operationId,
+ string? label = null,
+ string? schemaId = null,
+ string? routeKind = null,
+ string? routeDescription = null)
+ {
+ return new CultMeshOperationBindingRecord(
+ operationId,
+ label,
+ schemaId,
+ routeKind,
+ routeDescription);
+ }
+
+ ///
+ /// Creates a concrete invocation descriptor from an advertised operation binding.
+ ///
+ public static CultMeshOperationInvocationDescriptor OperationInvocation(
+ CultMeshOperationBindingDescriptor binding,
+ string? idempotencyKey = null)
+ {
+ return CultMeshOperationInvocationDescriptor.FromBinding(binding, idempotencyKey);
+ }
+
+ ///
+ /// Creates a concrete invocation descriptor from a typed operation handle.
+ ///
+ public static CultMeshOperationInvocationDescriptor OperationInvocation(
+ CultMeshOperationHandle operation,
+ string? schemaId = null,
+ CultMeshRouteHint? routeHint = null,
+ string? idempotencyKey = null)
+ {
+ return CultMeshOperationInvocationDescriptor.FromOperation(
+ operation,
+ schemaId,
+ routeHint,
+ idempotencyKey);
+ }
+
+ ///
+ /// Creates a concrete invocation descriptor from a typed operation id.
+ ///
+ public static CultMeshOperationInvocationDescriptor OperationInvocation(
+ string operationId,
+ string? schemaId = null,
+ CultMeshRouteHint? routeHint = null,
+ string? idempotencyKey = null)
+ {
+ return new CultMeshOperationInvocationDescriptor(operationId, schemaId, routeHint, idempotencyKey);
+ }
+
+ ///
+ /// Creates transport-friendly fields from a route hint.
+ ///
+ public static CultMeshRouteRecord RouteRecord(CultMeshRouteHint? routeHint)
+ {
+ return CultMeshRouteRecord.FromRoute(routeHint);
+ }
+
+ ///
+ /// Creates transport-friendly route fields directly.
+ ///
+ public static CultMeshRouteRecord RouteRecord(string? kind, string? description = null)
+ {
+ return new CultMeshRouteRecord(kind, description);
+ }
+
+ ///
+ /// Creates transport-friendly fields from a typed operation invocation.
+ ///
+ public static CultMeshOperationInvocationRecord OperationInvocationRecord(
+ CultMeshOperationInvocationDescriptor? invocation,
+ string? fallbackOperationId = null,
+ string? fallbackSchemaId = null,
+ CultMeshRouteHint? fallbackRouteHint = null,
+ string? fallbackIdempotencyKey = null)
+ {
+ return CultMeshOperationInvocationRecord.FromInvocation(
+ invocation,
+ fallbackOperationId,
+ fallbackSchemaId,
+ fallbackRouteHint,
+ fallbackIdempotencyKey);
+ }
+
+ ///
+ /// Creates transport-friendly operation invocation fields directly.
+ ///
+ public static CultMeshOperationInvocationRecord OperationInvocationRecord(
+ string? operationId,
+ string? schemaId = null,
+ string? routeKind = null,
+ string? routeDescription = null,
+ string? idempotencyKey = null)
+ {
+ return new CultMeshOperationInvocationRecord(
+ operationId,
+ schemaId,
+ routeKind,
+ routeDescription,
+ idempotencyKey);
+ }
+
+ ///
+ /// Creates an empty shared operation payload.
+ ///
+ public static CultMeshOperationPayload OperationPayload()
+ {
+ return CultMeshOperationPayload.Empty;
+ }
+
+ ///
+ /// Creates a shared operation payload from string-compatible fields.
+ ///
+ public static CultMeshOperationPayload OperationPayload(
+ IEnumerable>? fields)
+ {
+ return CultMeshOperationPayload.FromStrings(fields);
+ }
+
+ ///
+ /// Creates a shared operation payload from key/value pairs.
+ ///
+ public static CultMeshOperationPayload OperationPayload(params (string Key, string Value)[] fields)
+ {
+ var pairs = fields?.Select(field => new KeyValuePair(field.Key, field.Value));
+ return CultMeshOperationPayload.FromStrings(pairs);
+ }
+
+ ///
+ /// Creates a reusable projection recipe over typed source state.
+ ///
+ public static CultMeshProjectionRecipe ProjectionRecipe(
+ string projectionId,
+ IEnumerable sources,
+ Func> project,
+ CultMeshRouteHint? routeHint = null,
+ Func>? watch = null)
+ {
+ return new CultMeshProjectionRecipe(
+ projectionId,
+ sources,
+ project,
+ routeHint,
+ watch);
+ }
+
+ ///
+ /// Creates a typed live feed surface for coherent client snapshots.
+ ///
+ public static CultMeshLiveFeed LiveFeed(
+ string feedId,
+ Func> snapshot,
+ Func>? watch = null,
+ IEnumerable? sources = null,
+ CultMeshRouteHint? routeHint = null)
+ {
+ return new CultMeshLiveFeed(
+ feedId,
+ snapshot,
+ watch,
+ sources,
+ routeHint);
+ }
+
+ ///
+ /// Creates a typed document handle from snapshot/watch delegates and binds it to a Verse context.
+ ///
+ public static CultMeshDocumentHandle Document(
+ string documentId,
+ CultMeshVerseContext context,
+ Func> latest,
+ Func> watch,
+ IEnumerable? sources = null,
+ CultMeshRouteHint? routeHint = null)
+ where TDocument : class
+ {
+ if (latest == null) throw new ArgumentNullException(nameof(latest));
+ if (watch == null) throw new ArgumentNullException(nameof(watch));
+
+ var feed = LiveFeed(
+ documentId,
+ (_parameters, queryContext) => latest(queryContext),
+ (_parameters, queryContext) => watch(queryContext),
+ sources,
+ routeHint);
+ return BindDocument(context, feed);
+ }
+
+ ///
+ /// Creates a typed document handle from snapshot/watch delegates and binds it to a Verse.
+ ///
+ public static CultMeshDocumentHandle Document(
+ string documentId,
+ CultMeshVerse verse,
+ Func> latest,
+ Func> watch,
+ IEnumerable? sources = null,
+ CultMeshRouteHint? routeHint = null)
+ where TDocument : class
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return Document(documentId, verse.Context, latest, watch, sources, routeHint);
+ }
+
+ ///
+ /// Describes a typed live feed surface for tooling, UI, and diagnostics.
+ ///
+ public static CultMeshLiveFeedDiagnostic DescribeLiveFeed(
+ CultMeshLiveFeed feed)
+ {
+ if (feed == null) throw new ArgumentNullException(nameof(feed));
+ return new CultMeshLiveFeedDiagnostic(feed.FeedId, feed.RouteHint, feed.Sources);
+ }
+
+ ///
+ /// Describes a typed query surface for tooling, UI, and diagnostics.
+ ///
+ public static CultMeshQuerySurfaceDiagnostic DescribeQuerySurface(
+ CultMeshQuerySurface query)
+ {
+ if (query == null) throw new ArgumentNullException(nameof(query));
+ return new CultMeshQuerySurfaceDiagnostic(query.QueryId, query.RouteHint, query.Sources);
+ }
+
+ ///
+ /// Describes a typed operation handle for tooling, UI, and diagnostics.
+ ///
+ public static CultMeshOperationHandleDiagnostic DescribeOperationHandle(
+ CultMeshOperationHandle operation)
+ {
+ if (operation == null) throw new ArgumentNullException(nameof(operation));
+ return new CultMeshOperationHandleDiagnostic(operation.OperationId);
+ }
+
+ ///
+ /// Describes a typed state pointer for tooling, UI, and diagnostics.
+ ///
+ public static CultMeshStatePointerDiagnostic DescribeStatePointer(
+ CultMeshStatePointer pointer)
+ {
+ if (pointer == null) throw new ArgumentNullException(nameof(pointer));
+ return new CultMeshStatePointerDiagnostic(pointer.PointerId, pointer.RouteHint, pointer.Sources);
+ }
+
+ ///
+ /// Describes a mutable typed state pointer for tooling, UI, and diagnostics.
+ ///
+ public static CultMeshStatePointerDiagnostic DescribeStatePointer(
+ CultMeshMutableStatePointer pointer)
+ {
+ if (pointer == null) throw new ArgumentNullException(nameof(pointer));
+ return new CultMeshStatePointerDiagnostic(pointer.PointerId, pointer.RouteHint, pointer.Sources);
+ }
+
+ ///
+ /// Describes a native slice view for tooling, UI, and diagnostics.
+ ///
+ public static CultMeshNativeSliceViewDiagnostic DescribeNativeSliceView(
+ CultMeshNativeSliceViewDescriptor view)
+ {
+ return new CultMeshNativeSliceViewDiagnostic(view);
+ }
+
+ ///
+ /// Describes a typed projection recipe for tooling, UI, and diagnostics.
+ ///
+ public static CultMeshProjectionRecipeDiagnostic DescribeProjectionRecipe(
+ CultMeshProjectionRecipe recipe)
+ {
+ if (recipe == null) throw new ArgumentNullException(nameof(recipe));
+ return new CultMeshProjectionRecipeDiagnostic(recipe.ProjectionId, recipe.RouteHint, recipe.Sources);
+ }
+
+ ///
+ /// Describes a typed query surface as one entry in a surface catalog.
+ ///
+ public static CultMeshSurfaceDiagnostic DescribeSurface(
+ CultMeshQuerySurface query)
+ {
+ if (query == null) throw new ArgumentNullException(nameof(query));
+ return new CultMeshSurfaceDiagnostic(CultMeshSurfaceKind.Query, query.QueryId, query.RouteHint, query.Sources);
+ }
+
+ ///
+ /// Describes a typed operation handle as one entry in a surface catalog.
+ ///
+ public static CultMeshSurfaceDiagnostic DescribeSurface(
+ CultMeshOperationHandle operation)
+ {
+ if (operation == null) throw new ArgumentNullException(nameof(operation));
+ return new CultMeshSurfaceDiagnostic(CultMeshSurfaceKind.Operation, operation.OperationId);
+ }
+
+ ///
+ /// Describes a typed projection recipe as one entry in a surface catalog.
+ ///
+ public static CultMeshSurfaceDiagnostic DescribeSurface(
+ CultMeshProjectionRecipe recipe)
+ {
+ if (recipe == null) throw new ArgumentNullException(nameof(recipe));
+ return new CultMeshSurfaceDiagnostic(CultMeshSurfaceKind.ProjectionRecipe, recipe.ProjectionId, recipe.RouteHint, recipe.Sources);
+ }
+
+ ///
+ /// Describes a typed live feed as one entry in a surface catalog.
+ ///
+ public static CultMeshSurfaceDiagnostic DescribeSurface(
+ CultMeshLiveFeed feed)
+ {
+ if (feed == null) throw new ArgumentNullException(nameof(feed));
+ return new CultMeshSurfaceDiagnostic(CultMeshSurfaceKind.LiveFeed, feed.FeedId, feed.RouteHint, feed.Sources);
+ }
+
+ ///
+ /// Describes a typed state pointer as one entry in a surface catalog.
+ ///
+ public static CultMeshSurfaceDiagnostic DescribeSurface(
+ CultMeshStatePointer pointer)
+ {
+ if (pointer == null) throw new ArgumentNullException(nameof(pointer));
+ return new CultMeshSurfaceDiagnostic(
+ CultMeshSurfaceKind.StatePointer,
+ pointer.PointerId,
+ pointer.RouteHint,
+ pointer.Sources);
+ }
+
+ ///
+ /// Describes a mutable typed state pointer as one entry in a surface catalog.
+ ///
+ public static CultMeshSurfaceDiagnostic DescribeSurface(
+ CultMeshMutableStatePointer pointer)
+ {
+ if (pointer == null) throw new ArgumentNullException(nameof(pointer));
+ return new CultMeshSurfaceDiagnostic(
+ CultMeshSurfaceKind.StatePointer,
+ pointer.PointerId,
+ pointer.RouteHint,
+ pointer.Sources);
+ }
+
+ ///
+ /// Describes a native slice view as one entry in a surface catalog.
+ ///
+ public static CultMeshSurfaceDiagnostic DescribeSurface(
+ CultMeshNativeSliceViewDescriptor view)
+ {
+ if (view == null) throw new ArgumentNullException(nameof(view));
+ return new CultMeshSurfaceDiagnostic(CultMeshSurfaceKind.NativeSliceView, view.ViewId, view.Route);
+ }
+
+ ///
+ /// Creates a typed surface catalog diagnostic for tooling, UI, and generated bindings.
+ ///
+ public static CultMeshSurfaceCatalogDiagnostic DescribeSurfaceCatalog(
+ string catalogId,
+ IEnumerable surfaces)
+ {
+ return new CultMeshSurfaceCatalogDiagnostic(catalogId, surfaces);
+ }
+
+ ///
+ /// Creates a kind-indexed surface catalog diagnostic for generated bindings, UI, and tools.
+ ///
+ public static CultMeshSurfaceCatalogIndexDiagnostic DescribeSurfaceCatalogIndex(
+ CultMeshSurfaceCatalogDiagnostic catalog)
+ {
+ if (catalog == null) throw new ArgumentNullException(nameof(catalog));
+ return catalog.IndexByKind();
+ }
+
+ ///
+ /// Creates a timer-backed query watcher for runtimes that do not yet have native reactive transport.
+ ///
+ public static Func> PollingQueryWatcher(
+ Func> sample,
+ CultMeshPollingWatchOptions? options = null)
+ {
+ if (sample == null) throw new ArgumentNullException(nameof(sample));
+ var resolvedOptions = options ?? new CultMeshPollingWatchOptions();
+ return (parameters, context) => R3.Observable.Create(observer =>
+ {
+ var watcher = new CultMeshPollingWatcher(
+ sample,
+ parameters,
+ context,
+ resolvedOptions);
+ var subscription = watcher.Observable.Subscribe(observer);
+ return new CultMeshCompositeDisposable(subscription, watcher);
+ });
+ }
+
///
/// Parses a rudp://host:port endpoint into its host/port parts.
///
diff --git a/src/GameCult.Mesh/CultMeshPrimitives.cs b/src/GameCult.Mesh/CultMeshPrimitives.cs
new file mode 100644
index 00000000..49906d1c
--- /dev/null
+++ b/src/GameCult.Mesh/CultMeshPrimitives.cs
@@ -0,0 +1,2775 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using GameCult.Caching;
+using GameCult.Caching.MessagePack;
+using MessagePack;
+using R3;
+
+namespace GameCult.Mesh
+{
+ ///
+ /// Describes the route CultMesh used or should prefer for a typed operation, query, pointer, or native view.
+ ///
+ public enum CultMeshLocalityKind
+ {
+ /// Let CultMesh choose the fastest valid route.
+ Automatic,
+ /// The target is in the same process.
+ InProcess,
+ /// The target is available through a shared CultCache slab or native shared memory view.
+ SharedMemory,
+ /// The target is reachable through local inter-process transport.
+ Ipc,
+ /// The target is reachable through a network Verse route.
+ Network,
+ /// The target is hosted in or exposed to a WebAssembly runtime.
+ Wasm
+ }
+
+ ///
+ /// Names a CultMesh locality decision without exposing transport plumbing to application code.
+ ///
+ public sealed class CultMeshRouteHint
+ {
+ /// Creates a route hint.
+ public CultMeshRouteHint(CultMeshLocalityKind kind = CultMeshLocalityKind.Automatic, string? description = null)
+ {
+ Kind = kind;
+ Description = description;
+ }
+
+ /// Gets the requested or observed locality kind.
+ public CultMeshLocalityKind Kind { get; }
+
+ /// Gets optional human-facing route diagnostics.
+ public string? Description { get; }
+
+ /// Gets the default automatic route hint.
+ public static CultMeshRouteHint Automatic { get; } = new();
+ }
+
+ ///
+ /// Flat, transport-friendly fields for a CultMesh route hint.
+ ///
+ public sealed class CultMeshRouteRecord
+ {
+ /// Creates flat route fields.
+ public CultMeshRouteRecord(string? kind = null, string? description = null)
+ {
+ Kind = kind ?? "";
+ Description = description ?? "";
+ }
+
+ /// Gets the serialized route locality kind.
+ public string Kind { get; }
+
+ /// Gets the serialized route description.
+ public string Description { get; }
+
+ /// Creates flat route fields from a route hint.
+ public static CultMeshRouteRecord FromRoute(CultMeshRouteHint? routeHint)
+ {
+ var route = routeHint ?? CultMeshRouteHint.Automatic;
+ return new CultMeshRouteRecord(route.Kind.ToString(), route.Description);
+ }
+
+ /// Rehydrates flat route fields into a route hint.
+ public CultMeshRouteHint ToRoute(CultMeshRouteHint? fallback = null)
+ {
+ var fallbackRoute = fallback ?? CultMeshRouteHint.Automatic;
+ return new CultMeshRouteHint(
+ ParseKind(Kind, fallbackRoute.Kind),
+ string.IsNullOrWhiteSpace(Description) ? fallbackRoute.Description : Description);
+ }
+
+ private static CultMeshLocalityKind ParseKind(string? value, CultMeshLocalityKind fallback)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ return fallback;
+
+ if (Enum.TryParse(value, ignoreCase: true, out var parsed))
+ return parsed;
+
+ var normalized = value.Replace("-", "", StringComparison.Ordinal);
+ foreach (CultMeshLocalityKind candidate in Enum.GetValues(typeof(CultMeshLocalityKind)))
+ {
+ if (string.Equals(candidate.ToString(), normalized, StringComparison.OrdinalIgnoreCase))
+ return candidate;
+ }
+
+ return fallback;
+ }
+ }
+
+ ///
+ /// Shared Verse invocation context used by generated domain sugar.
+ ///
+ public sealed class CultMeshVerseContext
+ {
+ /// Creates a Verse context.
+ public CultMeshVerseContext(
+ string verseId,
+ string runtimeId,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? claims = null)
+ {
+ VerseId = RequireNonEmpty(verseId, nameof(verseId));
+ RuntimeId = RequireNonEmpty(runtimeId, nameof(runtimeId));
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ Claims = claims?.ToArray() ?? Array.Empty();
+ }
+
+ /// Gets the semantic Verse id.
+ public string VerseId { get; }
+
+ /// Gets the runtime using the Verse.
+ public string RuntimeId { get; }
+
+ /// Gets the preferred route for generated operations and queries.
+ public CultMeshRouteHint RouteHint { get; }
+
+ /// Gets authority claims carried by generated operations.
+ public IReadOnlyList Claims { get; }
+
+ /// Returns a copy with one additional authority claim.
+ public CultMeshVerseContext WithClaim(CultMeshAuthorityClaim claim)
+ {
+ if (claim == null) throw new ArgumentNullException(nameof(claim));
+ return new CultMeshVerseContext(VerseId, RuntimeId, RouteHint, Claims.Concat(new[] { claim }));
+ }
+
+ /// Returns a copy with the supplied route hint.
+ public CultMeshVerseContext WithRoute(CultMeshRouteHint routeHint)
+ {
+ if (routeHint == null) throw new ArgumentNullException(nameof(routeHint));
+ return new CultMeshVerseContext(VerseId, RuntimeId, routeHint, Claims);
+ }
+
+ /// Creates a typed operation context from the Verse context.
+ public CultMeshOperationContext OperationContext(string? idempotencyKey = null)
+ {
+ return new CultMeshOperationContext(RuntimeId, Claims, RouteHint, idempotencyKey);
+ }
+
+ /// Creates a typed query context from the Verse context.
+ public CultMeshQueryContext QueryContext()
+ {
+ return new CultMeshQueryContext(RuntimeId, RouteHint);
+ }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Managed Verse handle that generated domain packages can bind to.
+ ///
+ public sealed class CultMeshVerse
+ {
+ /// Creates a managed Verse handle.
+ public CultMeshVerse(CultMeshVerseContext context)
+ {
+ Context = context ?? throw new ArgumentNullException(nameof(context));
+ }
+
+ /// Gets the Verse context shared by generated domain sugar.
+ public CultMeshVerseContext Context { get; }
+
+ /// Gets the semantic Verse id.
+ public string VerseId => Context.VerseId;
+
+ /// Gets the runtime using the Verse.
+ public string RuntimeId => Context.RuntimeId;
+
+ /// Binds this Verse to a generated domain facade.
+ public TSchema Use(Func schemaFactory)
+ {
+ if (schemaFactory == null) throw new ArgumentNullException(nameof(schemaFactory));
+ return schemaFactory(Context);
+ }
+
+ /// Returns a Verse handle with one additional authority claim.
+ public CultMeshVerse WithClaim(CultMeshAuthorityClaim claim)
+ {
+ return new CultMeshVerse(Context.WithClaim(claim));
+ }
+
+ /// Returns a Verse handle with the supplied route hint.
+ public CultMeshVerse WithRoute(CultMeshRouteHint routeHint)
+ {
+ return new CultMeshVerse(Context.WithRoute(routeHint));
+ }
+
+ /// Creates a typed operation context from this Verse.
+ public CultMeshOperationContext OperationContext(string? idempotencyKey = null)
+ {
+ return Context.OperationContext(idempotencyKey);
+ }
+
+ /// Creates a typed query context from this Verse.
+ public CultMeshQueryContext QueryContext()
+ {
+ return Context.QueryContext();
+ }
+
+ /// Binds an operation handle to this Verse.
+ public CultMeshBoundOperationHandle BindOperation(
+ CultMeshOperationHandle operation)
+ {
+ return new CultMeshBoundOperationHandle(Context, operation);
+ }
+
+ /// Binds a query surface to this Verse.
+ public CultMeshBoundQuerySurface BindQuery(
+ CultMeshQuerySurface query)
+ {
+ return new CultMeshBoundQuerySurface(Context, query);
+ }
+
+ /// Binds a live feed to this Verse.
+ public CultMeshBoundLiveFeed BindLiveFeed(
+ CultMeshLiveFeed feed)
+ {
+ return new CultMeshBoundLiveFeed(Context, feed);
+ }
+
+ /// Binds a state pointer to this Verse.
+ public CultMeshBoundStatePointer BindStatePointer(
+ CultMeshStatePointer pointer)
+ {
+ return new CultMeshBoundStatePointer(Context, pointer);
+ }
+
+ /// Binds a mutable state pointer to this Verse.
+ public CultMeshBoundMutableStatePointer BindMutableStatePointer(
+ CultMeshMutableStatePointer pointer)
+ {
+ return new CultMeshBoundMutableStatePointer(Context, pointer);
+ }
+ }
+
+ ///
+ /// Describes a runtime authority claim attached to a typed operation.
+ ///
+ public sealed class CultMeshAuthorityClaim
+ {
+ /// Creates an authority claim.
+ public CultMeshAuthorityClaim(string role, string? shardId = null, string? leaseId = null)
+ {
+ Role = RequireNonEmpty(role, nameof(role));
+ ShardId = shardId;
+ LeaseId = leaseId;
+ }
+
+ /// Gets the role or claim kind being asserted.
+ public string Role { get; }
+
+ /// Gets the optional shard covered by the claim.
+ public string? ShardId { get; }
+
+ /// Gets the optional lease id backing the claim.
+ public string? LeaseId { get; }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Context supplied when invoking a typed CultMesh operation.
+ ///
+ public sealed class CultMeshOperationContext
+ {
+ /// Creates an operation context.
+ public CultMeshOperationContext(
+ string runtimeId,
+ IEnumerable? claims = null,
+ CultMeshRouteHint? routeHint = null,
+ string? idempotencyKey = null)
+ {
+ RuntimeId = RequireNonEmpty(runtimeId, nameof(runtimeId));
+ Claims = claims?.ToArray() ?? Array.Empty();
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ IdempotencyKey = idempotencyKey;
+ }
+
+ /// Gets the runtime invoking the operation.
+ public string RuntimeId { get; }
+
+ /// Gets authority claims attached to the operation.
+ public IReadOnlyList Claims { get; }
+
+ /// Gets the preferred route for the operation.
+ public CultMeshRouteHint RouteHint { get; }
+
+ /// Gets an optional operation idempotency key.
+ public string? IdempotencyKey { get; }
+
+ /// Creates an operation context for a runtime.
+ public static CultMeshOperationContext ForRuntime(string runtimeId)
+ {
+ return new CultMeshOperationContext(runtimeId);
+ }
+
+ /// Returns a copy with one additional authority claim.
+ public CultMeshOperationContext WithClaim(CultMeshAuthorityClaim claim)
+ {
+ if (claim == null) throw new ArgumentNullException(nameof(claim));
+ return new CultMeshOperationContext(RuntimeId, Claims.Concat(new[] { claim }), RouteHint, IdempotencyKey);
+ }
+
+ /// Returns a copy with the supplied route hint.
+ public CultMeshOperationContext WithRoute(CultMeshRouteHint routeHint)
+ {
+ if (routeHint == null) throw new ArgumentNullException(nameof(routeHint));
+ return new CultMeshOperationContext(RuntimeId, Claims, routeHint, IdempotencyKey);
+ }
+
+ /// Returns a copy with the supplied idempotency key.
+ public CultMeshOperationContext WithIdempotencyKey(string idempotencyKey)
+ {
+ return new CultMeshOperationContext(
+ RuntimeId,
+ Claims,
+ RouteHint,
+ RequireNonEmpty(idempotencyKey, nameof(idempotencyKey)));
+ }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Receipt returned by a typed CultMesh operation.
+ ///
+ public sealed class CultMeshOperationReceipt
+ {
+ /// Creates an operation receipt.
+ public CultMeshOperationReceipt(
+ string operationId,
+ bool accepted,
+ CultMeshRouteHint? route = null,
+ string? diagnostic = null)
+ {
+ OperationId = RequireNonEmpty(operationId, nameof(operationId));
+ Accepted = accepted;
+ Route = route ?? CultMeshRouteHint.Automatic;
+ Diagnostic = diagnostic;
+ }
+
+ /// Gets the semantic operation id.
+ public string OperationId { get; }
+
+ /// Gets whether the operation was accepted by the target authority boundary.
+ public bool Accepted { get; }
+
+ /// Gets the route used for the operation.
+ public CultMeshRouteHint Route { get; }
+
+ /// Gets optional operation diagnostics.
+ public string? Diagnostic { get; }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Method-shaped handle for a typed CultMesh operation.
+ ///
+ public sealed class CultMeshOperationHandle
+ {
+ private readonly Func> _invoke;
+
+ /// Creates an operation handle.
+ public CultMeshOperationHandle(
+ string operationId,
+ Func> invoke)
+ {
+ OperationId = RequireNonEmpty(operationId, nameof(operationId));
+ _invoke = invoke ?? throw new ArgumentNullException(nameof(invoke));
+ }
+
+ /// Gets the semantic operation id.
+ public string OperationId { get; }
+
+ /// Invokes the typed operation.
+ public Task InvokeAsync(TRequest request, CultMeshOperationContext context)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
+ return _invoke(request, context);
+ }
+
+ /// Invokes the typed operation for one runtime using default context.
+ public Task InvokeAsync(TRequest request, string runtimeId)
+ {
+ return InvokeAsync(request, CultMeshOperationContext.ForRuntime(runtimeId));
+ }
+
+ /// Binds this operation to a Verse context.
+ public CultMeshBoundOperationHandle Bind(CultMeshVerseContext context)
+ {
+ return new CultMeshBoundOperationHandle(context, this);
+ }
+
+ /// Binds this operation to a Verse.
+ public CultMeshBoundOperationHandle Bind(CultMeshVerse verse)
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return Bind(verse.Context);
+ }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Operation handle pre-bound to a Verse so generated domain sugar can invoke without context plumbing.
+ ///
+ public sealed class CultMeshBoundOperationHandle
+ {
+ /// Creates a Verse-bound operation handle.
+ public CultMeshBoundOperationHandle(
+ CultMeshVerseContext context,
+ CultMeshOperationHandle operation)
+ {
+ Context = context ?? throw new ArgumentNullException(nameof(context));
+ Operation = operation ?? throw new ArgumentNullException(nameof(operation));
+ }
+
+ /// Gets the bound Verse context.
+ public CultMeshVerseContext Context { get; }
+
+ /// Gets the underlying operation handle.
+ public CultMeshOperationHandle Operation { get; }
+
+ /// Gets the semantic operation id.
+ public string OperationId => Operation.OperationId;
+
+ /// Invokes the operation through the bound Verse.
+ public Task InvokeAsync(TRequest request, string? idempotencyKey = null)
+ {
+ return Operation.InvokeAsync(request, Context.OperationContext(idempotencyKey));
+ }
+ }
+
+ ///
+ /// Context supplied when executing a typed CultMesh query surface.
+ ///
+ public sealed class CultMeshQueryContext
+ {
+ /// Creates a query context.
+ public CultMeshQueryContext(string runtimeId, CultMeshRouteHint? routeHint = null)
+ {
+ RuntimeId = RequireNonEmpty(runtimeId, nameof(runtimeId));
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ }
+
+ /// Gets the runtime executing the query.
+ public string RuntimeId { get; }
+
+ /// Gets the preferred route for the query.
+ public CultMeshRouteHint RouteHint { get; }
+
+ /// Creates a query context for a runtime.
+ public static CultMeshQueryContext ForRuntime(string runtimeId)
+ {
+ return new CultMeshQueryContext(runtimeId);
+ }
+
+ /// Returns a copy with the supplied route hint.
+ public CultMeshQueryContext WithRoute(CultMeshRouteHint routeHint)
+ {
+ if (routeHint == null) throw new ArgumentNullException(nameof(routeHint));
+ return new CultMeshQueryContext(RuntimeId, routeHint);
+ }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Fluent builder for typed operation context. This is sugar over ,
+ /// intended for call sites that should read like native Verse operations instead of transport setup.
+ ///
+ public sealed class CultMeshOperationContextBuilder
+ {
+ private readonly string _runtimeId;
+ private readonly List _claims = new();
+ private CultMeshRouteHint _routeHint = CultMeshRouteHint.Automatic;
+ private string? _idempotencyKey;
+
+ /// Creates a builder for one runtime.
+ public CultMeshOperationContextBuilder(string runtimeId)
+ {
+ _runtimeId = RequireNonEmpty(runtimeId, nameof(runtimeId));
+ }
+
+ /// Adds an authority claim.
+ public CultMeshOperationContextBuilder Claim(string role, string? shardId = null, string? leaseId = null)
+ {
+ _claims.Add(new CultMeshAuthorityClaim(role, shardId, leaseId));
+ return this;
+ }
+
+ /// Adds an authority claim.
+ public CultMeshOperationContextBuilder Claim(CultMeshAuthorityClaim claim)
+ {
+ _claims.Add(claim ?? throw new ArgumentNullException(nameof(claim)));
+ return this;
+ }
+
+ /// Adds many authority claims.
+ public CultMeshOperationContextBuilder Claims(IEnumerable claims)
+ {
+ if (claims == null) throw new ArgumentNullException(nameof(claims));
+ _claims.AddRange(claims);
+ return this;
+ }
+
+ /// Sets the preferred route hint.
+ public CultMeshOperationContextBuilder Route(CultMeshLocalityKind kind, string? description = null)
+ {
+ _routeHint = new CultMeshRouteHint(kind, description);
+ return this;
+ }
+
+ /// Sets the operation idempotency key.
+ public CultMeshOperationContextBuilder Idempotency(string idempotencyKey)
+ {
+ _idempotencyKey = RequireNonEmpty(idempotencyKey, nameof(idempotencyKey));
+ return this;
+ }
+
+ /// Creates the immutable operation context.
+ public CultMeshOperationContext Build()
+ {
+ return new CultMeshOperationContext(_runtimeId, _claims, _routeHint, _idempotencyKey);
+ }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Fluent builder for typed query context.
+ ///
+ public sealed class CultMeshQueryContextBuilder
+ {
+ private readonly string _runtimeId;
+ private CultMeshRouteHint _routeHint = CultMeshRouteHint.Automatic;
+
+ /// Creates a builder for one runtime.
+ public CultMeshQueryContextBuilder(string runtimeId)
+ {
+ _runtimeId = RequireNonEmpty(runtimeId, nameof(runtimeId));
+ }
+
+ /// Sets the preferred route hint.
+ public CultMeshQueryContextBuilder Route(CultMeshLocalityKind kind, string? description = null)
+ {
+ _routeHint = new CultMeshRouteHint(kind, description);
+ return this;
+ }
+
+ /// Creates the immutable query context.
+ public CultMeshQueryContext Build()
+ {
+ return new CultMeshQueryContext(_runtimeId, _routeHint);
+ }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Typed derived-state query surface.
+ ///
+ public sealed class CultMeshQuerySurface
+ {
+ private readonly Func> _execute;
+ private readonly Func>? _watch;
+
+ /// Creates a query surface.
+ public CultMeshQuerySurface(
+ string queryId,
+ Func> execute,
+ Func>? watch = null,
+ IEnumerable? sources = null,
+ CultMeshRouteHint? routeHint = null)
+ {
+ QueryId = RequireNonEmpty(queryId, nameof(queryId));
+ _execute = execute ?? throw new ArgumentNullException(nameof(execute));
+ _watch = watch;
+ Sources = sources?.ToArray() ?? Array.Empty();
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ }
+
+ /// Gets the semantic query id.
+ public string QueryId { get; }
+
+ /// Gets the typed state sources this query depends on, when known.
+ public IReadOnlyList Sources { get; }
+
+ /// Gets the preferred or observed route for the query.
+ public CultMeshRouteHint RouteHint { get; }
+
+ /// Executes the query once.
+ public Task ExecuteAsync(TParameters parameters, CultMeshQueryContext context)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
+ return _execute(parameters, context);
+ }
+
+ /// Executes the query once for one runtime using default context.
+ public Task ExecuteAsync(TParameters parameters, string runtimeId)
+ {
+ return ExecuteAsync(parameters, CultMeshQueryContext.ForRuntime(runtimeId));
+ }
+
+ /// Watches query results when the surface supports reactive execution.
+ public Observable Watch(TParameters parameters, CultMeshQueryContext context)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
+ if (_watch == null)
+ {
+ throw new NotSupportedException($"Query surface '{QueryId}' does not support reactive watches.");
+ }
+
+ return _watch(parameters, context);
+ }
+
+ /// Binds this query surface to a Verse context.
+ public CultMeshBoundQuerySurface Bind(CultMeshVerseContext context)
+ {
+ return new CultMeshBoundQuerySurface(context, this);
+ }
+
+ /// Binds this query surface to a Verse.
+ public CultMeshBoundQuerySurface Bind(CultMeshVerse verse)
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return Bind(verse.Context);
+ }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Query surface pre-bound to a Verse so generated domain sugar can execute without context plumbing.
+ ///
+ public sealed class CultMeshBoundQuerySurface
+ {
+ /// Creates a Verse-bound query surface.
+ public CultMeshBoundQuerySurface(
+ CultMeshVerseContext context,
+ CultMeshQuerySurface query)
+ {
+ Context = context ?? throw new ArgumentNullException(nameof(context));
+ Query = query ?? throw new ArgumentNullException(nameof(query));
+ }
+
+ /// Gets the bound Verse context.
+ public CultMeshVerseContext Context { get; }
+
+ /// Gets the underlying query surface.
+ public CultMeshQuerySurface Query { get; }
+
+ /// Gets the semantic query id.
+ public string QueryId => Query.QueryId;
+
+ /// Gets the typed state sources this query depends on, when known.
+ public IReadOnlyList Sources => Query.Sources;
+
+ /// Gets the preferred or observed route for the query.
+ public CultMeshRouteHint RouteHint => Query.RouteHint;
+
+ /// Executes the query through the bound Verse.
+ public Task ExecuteAsync(TParameters parameters)
+ {
+ return Query.ExecuteAsync(parameters, Context.QueryContext());
+ }
+
+ /// Watches query results through the bound Verse.
+ public Observable Watch(TParameters parameters)
+ {
+ return Query.Watch(parameters, Context.QueryContext());
+ }
+ }
+
+ ///
+ /// Typed live view surface for composed client snapshots.
+ ///
+ public sealed class CultMeshLiveFeed
+ {
+ private readonly Func> _snapshot;
+ private readonly Func>? _watch;
+
+ /// Creates a live feed surface.
+ public CultMeshLiveFeed(
+ string feedId,
+ Func> snapshot,
+ Func>? watch = null,
+ IEnumerable? sources = null,
+ CultMeshRouteHint? routeHint = null)
+ {
+ FeedId = RequireNonEmpty(feedId, nameof(feedId));
+ _snapshot = snapshot ?? throw new ArgumentNullException(nameof(snapshot));
+ _watch = watch;
+ Sources = sources?.ToArray() ?? Array.Empty();
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ }
+
+ /// Gets the semantic feed id.
+ public string FeedId { get; }
+
+ /// Gets the typed state sources this live feed depends on, when known.
+ public IReadOnlyList Sources { get; }
+
+ /// Gets the preferred or observed route for the feed.
+ public CultMeshRouteHint RouteHint { get; }
+
+ /// Reads one coherent feed snapshot.
+ public Task SnapshotAsync(TParameters parameters, CultMeshQueryContext context)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
+ return _snapshot(parameters, ResolveContext(context));
+ }
+
+ /// Reads one coherent feed snapshot for one runtime using default context.
+ public Task SnapshotAsync(TParameters parameters, string runtimeId)
+ {
+ return SnapshotAsync(parameters, CultMeshQueryContext.ForRuntime(runtimeId));
+ }
+
+ /// Watches coherent feed snapshots when the feed supports reactive execution.
+ public Observable Watch(TParameters parameters, CultMeshQueryContext context)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
+ if (_watch == null)
+ {
+ throw new NotSupportedException($"Live feed '{FeedId}' does not support reactive watches.");
+ }
+
+ return _watch(parameters, ResolveContext(context));
+ }
+
+ /// Binds this live feed to a Verse context.
+ public CultMeshBoundLiveFeed Bind(CultMeshVerseContext context)
+ {
+ return new CultMeshBoundLiveFeed(context, this);
+ }
+
+ /// Binds this live feed to a Verse.
+ public CultMeshBoundLiveFeed Bind(CultMeshVerse verse)
+ {
+ if (verse == null) throw new ArgumentNullException(nameof(verse));
+ return Bind(verse.Context);
+ }
+
+ private CultMeshQueryContext ResolveContext(CultMeshQueryContext context)
+ {
+ return context.RouteHint.Kind == CultMeshLocalityKind.Automatic &&
+ RouteHint.Kind != CultMeshLocalityKind.Automatic
+ ? context.WithRoute(RouteHint)
+ : context;
+ }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Live feed pre-bound to a Verse so generated domain sugar can snapshot or watch without context plumbing.
+ ///
+ public sealed class CultMeshBoundLiveFeed
+ {
+ /// Creates a Verse-bound live feed.
+ public CultMeshBoundLiveFeed(
+ CultMeshVerseContext context,
+ CultMeshLiveFeed feed)
+ {
+ Context = context ?? throw new ArgumentNullException(nameof(context));
+ Feed = feed ?? throw new ArgumentNullException(nameof(feed));
+ }
+
+ /// Gets the bound Verse context.
+ public CultMeshVerseContext Context { get; }
+
+ /// Gets the underlying live feed.
+ public CultMeshLiveFeed Feed { get; }
+
+ /// Gets the semantic feed id.
+ public string FeedId => Feed.FeedId;
+
+ /// Gets the typed state sources this live feed depends on, when known.
+ public IReadOnlyList Sources => Feed.Sources;
+
+ /// Gets the preferred or observed route for the feed.
+ public CultMeshRouteHint RouteHint => Feed.RouteHint;
+
+ /// Reads one coherent feed snapshot through the bound Verse.
+ public Task SnapshotAsync(TParameters parameters)
+ {
+ return Feed.SnapshotAsync(parameters, Context.QueryContext());
+ }
+
+ /// Watches coherent feed snapshots through the bound Verse.
+ public Observable Watch(TParameters parameters)
+ {
+ return Feed.Watch(parameters, Context.QueryContext());
+ }
+ }
+
+ ///
+ /// Empty parameter object for document handles that expose one typed document as a live feed.
+ ///
+ public readonly struct CultMeshDocumentQueryParameters
+ {
+ /// Gets the singleton empty document query.
+ public static CultMeshDocumentQueryParameters Empty { get; } = new();
+ }
+
+ ///
+ /// Inspectable typed document handle exposed by CultMesh.
+ ///
+ public interface ICultMeshDocumentHandle
+ {
+ /// Gets the CLR document type presented by this handle.
+ Type DocumentType { get; }
+
+ /// Gets the semantic document id.
+ string DocumentId { get; }
+
+ /// Gets the stable CultCache schema name.
+ string SchemaName { get; }
+
+ /// Gets the stable CultCache schema version.
+ string SchemaVersion { get; }
+
+ /// Gets the preferred or observed route for document access.
+ CultMeshRouteHint RouteHint { get; }
+
+ /// Gets typed state sources this document handle depends on, when known.
+ IReadOnlyList Sources { get; }
+
+ /// Creates a same-schema alias presentation for another CLR document type.
+ CultMeshDocumentHandle AsSchemaAlias() where TAlias : class;
+ }
+
+ ///
+ /// Typed reactive document handle with schema-aware alias conversion.
+ ///
+ public sealed class CultMeshDocumentHandle : ICultMeshDocumentHandle
+ where TDocument : class
+ {
+ private static readonly CultDocumentDescriptor Descriptor =
+ CultDocumentRegistry.Shared.GetRequired();
+
+ private readonly CultMeshBoundLiveFeed _feed;
+
+ /// Creates a document handle from a Verse-bound live feed.
+ public CultMeshDocumentHandle(CultMeshBoundLiveFeed feed)
+ {
+ _feed = feed ?? throw new ArgumentNullException(nameof(feed));
+ }
+
+ /// Gets the semantic document id.
+ public string DocumentId => _feed.FeedId;
+
+ /// Gets the CLR document type presented by this handle.
+ public Type DocumentType => typeof(TDocument);
+
+ /// Gets the stable CultCache schema name.
+ public string SchemaName => Descriptor.SchemaName;
+
+ /// Gets the stable CultCache schema version.
+ public string SchemaVersion => Descriptor.SchemaVersion;
+
+ /// Gets the content-derived schema identifier.
+ public string SchemaId => Descriptor.SchemaId;
+
+ /// Gets the preferred or observed route for document access.
+ public CultMeshRouteHint RouteHint => _feed.RouteHint;
+
+ /// Gets typed state sources this document handle depends on, when known.
+ public IReadOnlyList Sources => _feed.Sources;
+
+ /// Gets the bound Verse context.
+ public CultMeshVerseContext Context => _feed.Context;
+
+ /// Gets the underlying live feed used by this document handle.
+ public CultMeshLiveFeed Feed => _feed.Feed;
+
+ /// Reads one coherent document snapshot.
+ public Task LatestAsync()
+ {
+ return _feed.SnapshotAsync(CultMeshDocumentQueryParameters.Empty);
+ }
+
+ /// Watches coherent document snapshots.
+ public Observable Watch()
+ {
+ return _feed.Watch(CultMeshDocumentQueryParameters.Empty);
+ }
+
+ /// Subscribes to coherent document snapshots.
+ public IDisposable Watch(Action onNext)
+ {
+ if (onNext == null) throw new ArgumentNullException(nameof(onNext));
+ return Watch().Subscribe(onNext);
+ }
+
+ /// Creates a same-schema alias presentation for another CLR document type.
+ public CultMeshDocumentHandle AsSchemaAlias() where TAlias : class
+ {
+ var aliasDescriptor = CultDocumentRegistry.Shared.GetRequired();
+ if (!string.Equals(Descriptor.SchemaName, aliasDescriptor.SchemaName, StringComparison.Ordinal) ||
+ !string.Equals(Descriptor.SchemaVersion, aliasDescriptor.SchemaVersion, StringComparison.Ordinal))
+ {
+ throw new InvalidOperationException(
+ $"Document type {typeof(TAlias).FullName} uses schema '{aliasDescriptor.SchemaName}' " +
+ $"version '{aliasDescriptor.SchemaVersion}', but handle '{DocumentId}' exposes " +
+ $"schema '{SchemaName}' version '{SchemaVersion}'.");
+ }
+
+ var aliasFeed = new CultMeshLiveFeed(
+ DocumentId,
+ async (parameters, context) => ConvertDocument(
+ await Feed.SnapshotAsync(parameters, context).ConfigureAwait(false)),
+ (parameters, context) => Feed
+ .Watch(parameters, context)
+ .Select(ConvertDocument),
+ Sources,
+ RouteHint);
+
+ return new CultMeshDocumentHandle(aliasFeed.Bind(Context));
+ }
+
+ private static TAlias ConvertDocument(TDocument document) where TAlias : class
+ {
+ if (document == null) throw new ArgumentNullException(nameof(document));
+ var payload = CultDocumentMessagePackSerialization.SerializeUntyped(document, typeof(TDocument));
+ return (TAlias)CultDocumentMessagePackSerialization.DeserializeUntyped(typeof(TAlias), payload);
+ }
+ }
+
+ ///
+ /// Inspectable metadata for a typed live feed surface.
+ ///
+ public sealed class CultMeshLiveFeedDiagnostic
+ {
+ /// Creates live feed diagnostics.
+ public CultMeshLiveFeedDiagnostic(
+ string feedId,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? sources = null)
+ {
+ FeedId = RequireNonEmpty(feedId, nameof(feedId));
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ Sources = sources?.ToArray() ?? Array.Empty();
+ }
+
+ /// Gets the semantic feed id.
+ public string FeedId { get; }
+
+ /// Gets the preferred or observed route for the feed.
+ public CultMeshRouteHint RouteHint { get; }
+
+ /// Gets the typed state sources this live feed depends on, when known.
+ public IReadOnlyList Sources { get; }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Inspectable metadata for a typed query surface.
+ ///
+ public sealed class CultMeshQuerySurfaceDiagnostic
+ {
+ /// Creates query surface diagnostics.
+ public CultMeshQuerySurfaceDiagnostic(
+ string queryId,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? sources = null)
+ {
+ QueryId = RequireNonEmpty(queryId, nameof(queryId));
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ Sources = sources?.ToArray() ?? Array.Empty();
+ }
+
+ /// Gets the semantic query id.
+ public string QueryId { get; }
+
+ /// Gets the preferred or observed route for the query.
+ public CultMeshRouteHint RouteHint { get; }
+
+ /// Gets the typed state sources this query depends on, when known.
+ public IReadOnlyList Sources { get; }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Inspectable metadata for a typed operation handle.
+ ///
+ public sealed class CultMeshOperationHandleDiagnostic
+ {
+ /// Creates operation handle diagnostics.
+ public CultMeshOperationHandleDiagnostic(string operationId)
+ {
+ OperationId = RequireNonEmpty(operationId, nameof(operationId));
+ }
+
+ /// Gets the semantic operation id.
+ public string OperationId { get; }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Inspectable metadata for a typed state pointer.
+ ///
+ public sealed class CultMeshStatePointerDiagnostic
+ {
+ /// Creates state pointer diagnostics.
+ public CultMeshStatePointerDiagnostic(
+ string pointerId,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? sources = null)
+ {
+ PointerId = RequireNonEmpty(pointerId, nameof(pointerId));
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ Sources = sources?.ToArray() ?? Array.Empty();
+ }
+
+ /// Gets the semantic pointer id.
+ public string PointerId { get; }
+
+ /// Gets the preferred or observed route for pointer resolution.
+ public CultMeshRouteHint RouteHint { get; }
+
+ /// Gets typed state sources this pointer depends on, when known.
+ public IReadOnlyList Sources { get; }
+
+ private static string RequireNonEmpty(string value, string paramName)
+ {
+ return string.IsNullOrWhiteSpace(value)
+ ? throw new ArgumentException("Value must be non-empty.", paramName)
+ : value;
+ }
+ }
+
+ ///
+ /// Inspectable metadata for a typed projection recipe.
+ ///
+ public sealed class CultMeshProjectionRecipeDiagnostic
+ {
+ /// Creates projection recipe diagnostics.
+ public CultMeshProjectionRecipeDiagnostic(
+ string projectionId,
+ CultMeshRouteHint? routeHint = null,
+ IEnumerable? sources = null)
+ {
+ ProjectionId = RequireNonEmpty(projectionId, nameof(projectionId));
+ RouteHint = routeHint ?? CultMeshRouteHint.Automatic;
+ Sources = sources?.ToArray() ?? Array.Empty();
+ }
+
+ ///