A variant record stores [baseKey, overrides[]] in record slot 4 and an empty payload; the cache resolves it against its base inside the hold that admits it or any record on its base chain, and re-resolves dependents in the same Apply, so a base change reaches its variants with contiguous sequences and no stamp. Plain Upsert at a variant key is refused (Flatten is the explicit way); cycle, missing base, different concrete type, evicted base with survivors and a name that shadows the base are refused naming the keys. Overrides of a dropped slot or an undecodable value are ignored with a warning and reported as compatible drift. The store writes cultcache.store.v2 only when it holds a variant and reads v1 and v2. The codec pair CultInspectorModel took becomes CultCodec, shared with the cache, which needs it to clone documents and overlay override values. The directory store, CultMesh single-file reads and CultNet row building refuse a variant by name until their own cuts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
11 KiB
Runtime Parity Scope
This is the claim CultLib can make without turning evidence into incense. Parity means the targeted runtimes speak the same wire language and expose similar developer-facing entrypoints for the roles they own. It does not mean every runtime clones the C# production server, LiteNetLib history, or hot-loop memory layout.
Objective
Cross-runtime parity has three layers:
- Wire parity: shared CultCache file/state contracts, schema-v0 MessagePack
documents, transport profiles, and RUDP packets must cross runtime boundaries
without translation folklore.
Every store reader refuses, by name, a header or record slot it does not
understand (vectors:
tests/vectors/document-variants-c0). Document variants: C# resolves them (cultcache.store.v2); every other runtime, CultMesh single-file reads, the directory store and CultNet refuse a variant by name (vector written by C#:tests/vectors/document-variants-c1). - Feature parity: each runtime must expose the CultCache/CultNet/CultMesh surfaces needed for its intended role, with unsupported production-server ownership called out plainly.
- Ergonomic parity: callers should find a branded
CultMeshentrypoint, typed catalogs, discovery helpers, authority checks, stream surfaces, and transport helpers instead of assembling raw maps and channel strings.
SoA performance parity is deliberately not a cross-runtime requirement. C#
owns the shared-memory streaming body path. The C# CultCache SoA table (ECS-style
structure-of-arrays columns over cached documents) is parked at the tag
parked/cultcache-soa: it was built for hot-loop performance, had no consumer
outside tests, and is restorable from that tag (docs/parked-features.md).
It is not a supported surface in the current tree. Other runtimes may add native hot paths when their
runtime role earns them, but they do not need to mimic Unity/C# memory layout
to speak CultNet or participate in CultMesh.
Current Targeted Runtimes
| Runtime | Role | Claimed parity | Not claimed |
|---|---|---|---|
| C# | Reference implementation and production game/server substrate | CultCache typed documents, CultNet schema-v0, LiteNetLib production path with adapter profile, shared transport profiles, shared RUDP socket transport, C# multi-peer RUDP listener and schema service host, C# interop RUDP serve/dial path, connected RUDP CultMesh client helpers, RUDP-backed schema-client selection for rudp:// service endpoints, RUDP reconnect policy/controller and reconnect-loop helper, LiteNetLib client reconnect-controller adoption, schema-client transport port for service request/response clients, CultMesh node/session/catalog/stream/simulation/RUDP surfaces, authorized peer lookup |
No need to abandon LiteNetLib before the CultNet adapter fully owns production service adoption |
| Python | Package runtime, local daemon endpoint, raw interop peer, typed state participant | CultCache/CultNet/CultMesh package surface, branded CultMesh node/schema/shard/Verse/peer/authority/stream/RUDP ergonomics, authorized peer lookup, shard catalogs/logs, schema-transport factory for raw client request/subscription flows, local TCP and RUDP CultMesh server listeners, Python interop RUDP serve/dial path, session/prediction/simulation fact helpers, RUDP codec/session/socket transport, RUDP reconnect policy/controller and reconnect-loop helper, schema-v0 MessagePack over RUDP evidence, benchmark evidence against C# cache paths | Universal C# throughput, full C# daemon/server stack, and RUDP as the only public service pipe |
| TypeScript | Node/browser-adjacent projection and interop runtime | CultCache parity tests, CultNet schema-v0 peer, advertised schema/shard catalog wire contracts plus request/sync helpers, transport profiles, TCP-framed transport port and peer helper, shared RUDP socket transport, RUDP interop serve/dial path, RUDP reconnect policy/controller, RUDP reconnect-loop helper, branded CultMesh node/schema/shard/Verse/peer/authority/stream/RUDP ergonomics, authorized peer lookup | Full C# game session/server stack |
| Rust | Low-level cache/transport/runtime substrate | CultCache/CultNet interop lane, schema and shard catalog helpers, typed same-schema alias hydration from raw snapshots, transport profiles, TCP-framed port, shared RUDP codec/session/socket transport, Rust interop RUDP serve/dial path, connected RUDP CultMesh client helpers, RUDP reconnect policy/controller and reconnect-loop helper, schema-v0 MessagePack over RUDP evidence, small CultMesh facade for schema registry, shard catalog, peer cards, authority leases, authorized peer lookup, RUDP endpoint parsing, and peer-card/authorized-peer RUDP client construction | Full CultMesh game-session/server facade or production game-session server. packages/cultmesh-rs now holds a Rust stream and session surface -- node, document sets, RUDP document publication, stream descriptors, negotiation, stream catalog, and shared-memory frame rings -- but no interop lane exercises it, so it carries no cross-runtime parity claim |
| Kotlin | JVM/Android client substrate | Typed MessagePack cache, one-call typed snapshot document sync through local same-schema aliases, built-in schema catalog advertisement, schema/shard catalogs with shared schema-message transport fetch/sync helpers, authority leases, authorized peer lookup, stream catalog, branded CultMesh facade, WebSocket transport profile/connection helper, RUDP client/server sugar, connected RUDP CultMesh client helpers, Kotlin interop RUDP serve/dial path, RUDP reconnect policy/controller and reconnect-loop helper, schema-v0 MessagePack over RUDP evidence |
C# SoA store (parked at parked/cultcache-soa), full C# server daemon, or Unity hot-loop memory layout |
Evidence Gates
.github/workflows/cultnet-interop.ymlis the hosted CI witness for the cross-runtime wire claim. It builds the TypeScript workspace, Kotlin interop peer, Rust/C# interop peers through the TypeScript harness, installs the Python package dependencies, then runs named RUDP lanes for Python, Rust, C#, and Kotlin, the RUDP impairment matrix, and the schema-v0 discovery lane.packages/cultnet-ts/test/interop/cultnet-interop.test.tsis the main live wire harness. It covers schema-v0 interop and RUDP exchange across C#, TypeScript, Rust, Python, and Kotlin, including loss, reordering, fragmentation, disconnect reason propagation, ping/pong, and schema-v0 MessagePack over RUDP for C#, Rust, Python, and Kotlin peers against TypeScript. Those RUDP schema-message tests also assert the advertisedreconnectPolicyprofile field from C#, Rust, Python, and Kotlin peers. Runtime-local tests cover the deterministic delay helper and reconnect controller in C#, TypeScript, Rust, Python, and Kotlin.docs/python-runtime-parity.mdis the Python-specific audit ledger. Its "Still Not Claimed" section is part of the contract, not an apology.docs/cultnet-transport-parity.mdis the transport ownership map. It tracks the remaining work to lower older LiteNetLib/WebSocket bodies behind the shared transport port and expand RUDP adoption beyond the core proof.packages/cultmesh-kotlin/README.mdrecords Kotlin's runtime role and ergonomic surface, including the explicit non-claim around C# SoA storage.- CultNet typed selection (
cultnet.snapshot_response_raw.v1, C#/Rust only; docs/cultnet-selection-cut.md, R-AY): byte parity for thesnapshot_response_raw.v1envelope and its nested record types, verified at populated and absent optional values, plus semantic parity over the named field subset.packages/cultnet-rs/tests/selection_wire_parity.rsandtests/GameCult.Networking.Tests/SelectionWireParityTests.cscarry the byte vectors;packages/cultnet-rs/tests/selection.rs'swrite_selection_vectors_for_the_referenceandtests/GameCult.Networking.Tests/SelectionParityVectorTests.cscarry the semantic ones. A single rows-to-bytes path driving both halves in one call remains its own cut (R-AR) and is not part of this claim.
Expansion Work Outside The Current Parity Claim
The current claim is role-scoped feature, wire, and ergonomic parity across the targeted runtimes. The stronger claim that every production daemon/service body has already moved to native RUDP, or that every runtime clones the C# production server body, is deliberately not made.
- Broaden production service adoption so remaining daemon paths use the shared
transport port consistently. The C# built-in LiteNetLib service wrappers now
register transport-aware
CultNetServerPeerlisteners instead of requiringNetPeercallbacks, and TypeScript TCP peer creation has a transport-first helper. C# Verse discovery, peer exchange, shard-log fetch, shard-snapshot fetch, and shard write forwarding clients now consume a schema-client transport port and select the C# RUDP schema client forrudp://endpoints while keeping LiteNetLib forcultnet://endpoints. Broader daemon adoption remains the unclaimed layer. - Extend RUDP adoption through daemon/socket reconnect loops. RUDP profiles now advertise the portable reconnect policy, runtime-local tests prove the shared controller across the targeted runtimes, and the C# LiteNetLib client plus C#/TypeScript/Rust/Python/Kotlin RUDP reconnect loops use that controller; broader service adoption remains a separate claim.
- Keep Kotlin ergonomic parity moving with Android/JVM-shaped APIs instead of
backfilling C# server responsibilities it should not own. Kotlin WebSocket
and RUDP adapters now share one
CultNetSchemaMessageTransporthelper shape for schema/shard catalog request and sync flows. - Bring
packages/cultmesh-rsunder the wire claim. It arrived from a consumer repo where it grew outside any conformance harness, and its stream, negotiation, and shared-memory frame-ring surfaces have never been checked against the browser, Kotlin, and TypeScript CultMesh bodies they must interoperate with. Runtime-local tests pass; that is not a parity claim. - Carry the RUDP receive-path bounds to the other runtimes. Rust now caps tracked ordered and sequenced channels, caps the out-of-order hold buffer by frames and bytes, refuses a packet far ahead of the highest received so a forged sequence cannot starve a session, and reports reliable sequence exhaustion instead of aborting. C#, TypeScript, Python and Kotlin still accept all of it. These are refusals rather than wire-format changes, so the interop lanes stay green either way -- which is exactly why the gap will not announce itself.
- Keep performance claims evidence-bound: C# owns SoA; Python has benchmark comparison gates; other runtimes should advertise measured native hot paths only when those paths exist.