2026-06-14 01:03:39 +01:00
|
|
|
# Python Runtime Parity Map
|
|
|
|
|
|
Split the Python runtime into cultcache-py, cultnet-py, cultmesh-py
One distribution named cultcache-py carried three libraries. Rust and
TypeScript layer them as cultcache < cultnet < cultmesh; Python now does
the same, one package per layer, module names unchanged so every
`from cultmesh_py import ...` keeps working.
Two imports ran against that layering and are resolved by moving code to
where the dependency direction says it lives, not by adding a shim:
- cultnet_py.interop_peer imported the Verse/peer catalog, authority
lease, stream, and simulation-fact contracts from cultmesh_py. They are
wire contracts a bare peer has to speak without owning a node, which is
why cultnet-rs and cultnet-ts keep them in the net layer. They now live
in cultnet_py.cultmesh_contracts; cultmesh_py re-exports them.
- cultcache_py.benchmark imported cultnet_py. It measures framed CultNet
parse beside cache paths, so it and compare_csharp move to cultnet_py.
verify checks all three packages and moves to cultmesh_py.
The single 6,693-line test module is split by what each test touches: a
test using any cultmesh_py name lands in cultmesh-py, else cultnet_py in
cultnet-py, else cultcache-py. Each suite runs with only its layer and the
layers below on the path, so a test that reaches up fails to import
rather than quietly binding the packages back together. 11 / 53 / 78 =
the same 142.
Workflows install all three; the publish job is one matrix over the
three packages keyed by tag prefix. The TS test harnesses put all three
src directories on PYTHONPATH. cultcache-py bumps to 0.2.0 because it no
longer contains cultnet_py or cultmesh_py; the new packages start at
0.1.0. Nothing was ever published, so no PyPI consumer moves.
cultcache-py 11 tests, path: cultcache-py/src
cultnet-py 53 tests, path: + cultnet-py/src
cultmesh-py 78 tests, path: + cultmesh-py/src
python -m cultmesh_py.verify -> ok, all five checks
cultnet_py.interop_peer imports with cultmesh_py absent
Not run here: the cultnet-ts interop ring and cultcache-ts store matrix
need dotnet/kotlin peers; their PYTHONPATH change is four lines.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 13:10:47 +02:00
|
|
|
This file is the current audit map for the Python runtime packages
|
|
|
|
|
`cultcache-py`, `cultnet-py`, and `cultmesh-py`. It is evidence, not confetti.
|
2026-06-14 01:03:39 +01:00
|
|
|
|
|
|
|
|
## Proven Surfaces
|
|
|
|
|
|
|
|
|
|
- CultCache v1 store parity:
|
|
|
|
|
`packages/cultcache-ts/test/cult-cache.test.ts` includes Python in the shared
|
|
|
|
|
TypeScript/Rust/C#/Python store matrix.
|
|
|
|
|
- CultNet schema-v0 live interop:
|
|
|
|
|
`packages/cultnet-ts/test/interop/cultnet-interop.test.ts` runs a live
|
|
|
|
|
TS/Rust/C#/Python peer ring.
|
2026-06-14 05:33:01 +01:00
|
|
|
The Python interop peer filters shard-scoped raw snapshots by its live
|
|
|
|
|
shard-log membership before stamping shard cursor metadata.
|
2026-06-14 01:03:39 +01:00
|
|
|
- Python CultNet raw client:
|
|
|
|
|
Fetches schema catalogs, raw snapshots, shard catalogs, shard logs, and live
|
2026-06-14 14:08:19 +01:00
|
|
|
database subscription changes. Request-response reads and database
|
|
|
|
|
subscription streams raise typed `CultNetPeerError` values for
|
|
|
|
|
`cultnet.error.v0` peer responses while preserving the raw error document for
|
2026-06-16 16:13:56 +01:00
|
|
|
callers that need the wire evidence. `CultNetRawClient` and database
|
|
|
|
|
subscriptions now consume a caller-provided `CultNetSchemaTransport` factory,
|
|
|
|
|
with `create_tcp_framed_schema_transport(...)` as the default, so request and
|
|
|
|
|
subscription semantics are no longer owned by inline TCP socket setup.
|
2026-06-16 23:37:59 +01:00
|
|
|
`create_rudp_schema_transport(...)` opens the same raw-client request path
|
|
|
|
|
over a socket-backed RUDP reliable ordered `schema` channel, and the branded
|
|
|
|
|
`CultMesh.create_client(endpoint="rudp://...")` helper selects that transport
|
|
|
|
|
from a RUDP endpoint without making callers assemble a factory closure.
|
2026-06-14 04:21:05 +01:00
|
|
|
- Python CultNet raw snapshot:
|
|
|
|
|
Provides typed `CultNetRawSnapshotResponse` and `CultNetRawDocumentRecord`
|
|
|
|
|
helpers plus `CultNetRawClient.fetch_snapshot_response(...)` for inspecting
|
|
|
|
|
peer snapshots before handing them to the existing replication helpers.
|
2026-06-14 04:50:05 +01:00
|
|
|
`apply_raw_document_record(...)`, `apply_raw_snapshot(...)`,
|
|
|
|
|
`CultMeshDatabase.apply_snapshot_response(...)`, and sync paths accept typed
|
|
|
|
|
records/responses while preserving the existing replication owner.
|
2026-06-14 04:36:46 +01:00
|
|
|
`CultMeshDatabase.build_snapshot_response(...)` projects local envelopes into
|
|
|
|
|
the same typed response shape; the older `create_snapshot_response(...)`
|
|
|
|
|
remains the wire-dict compatibility projection.
|
2026-06-14 03:45:19 +01:00
|
|
|
- Python CultNet schema catalog:
|
|
|
|
|
Exposes shared wire-message schema descriptors from the package surface so
|
|
|
|
|
both the interop peer and CultMesh local server describe the CultNet/CultMesh
|
2026-06-14 03:51:50 +01:00
|
|
|
messages they speak through the same catalog authority. Python callers can
|
|
|
|
|
also ingest and filter remote schema catalog responses through typed
|
|
|
|
|
`CultNetSchemaCatalog` and `CultNetSchemaDescriptor` helpers, including
|
2026-06-14 14:16:41 +01:00
|
|
|
`CultNetRawClient.sync_schema_catalog(...)`. The catalog includes
|
|
|
|
|
`cultnet.error.v0`, and the local server advertises that version in hello
|
|
|
|
|
responses because oversized snapshots and other peer failures use that
|
2026-06-14 20:32:25 +01:00
|
|
|
contract on the wire. It also advertises the shared
|
|
|
|
|
`cultnet.transport_profile.v0` contract so Python peers can describe their
|
2026-06-16 00:06:56 +01:00
|
|
|
TCP-framed and RUDP transport capabilities honestly.
|
2026-06-14 17:39:07 +01:00
|
|
|
- Python CultNet security/session primitives:
|
|
|
|
|
`CultNetClientSecurityOptions`, `CultNetServerSecurityOptions`, and
|
|
|
|
|
`CultNetSecret` mirror the C#/TS connection-key, server signing-secret,
|
|
|
|
|
development-default, environment-validation, base64url, and HMAC-SHA256
|
|
|
|
|
session-token helper surface. Python creates C#-compatible versioned session
|
|
|
|
|
tokens with `userGuidN|expiresUnix|sessionVersion` payloads and still
|
|
|
|
|
validates legacy two-field tokens with session version `0`. AES-GCM string
|
|
|
|
|
and byte helpers use the same tag-prefix payload shape when the optional
|
|
|
|
|
`cryptography` dependency is available; without that dependency they fail
|
|
|
|
|
explicitly instead of pretending plaintext is secure.
|
2026-06-14 03:59:20 +01:00
|
|
|
- Python CultNet shard catalog:
|
|
|
|
|
Provides typed `CultNetShardCatalog` and `CultNetShardDescriptor` helpers for
|
|
|
|
|
ingesting, filtering, and emitting shard topology responses, plus
|
|
|
|
|
`CultNetRawClient.sync_shard_catalog(...)` for peer topology discovery over
|
|
|
|
|
the same framed CultNet pipe.
|
2026-06-14 04:06:38 +01:00
|
|
|
- Python CultNet shard log:
|
|
|
|
|
Provides typed `CultNetShardLogResponse` and `CultNetShardLogEntry` helpers
|
|
|
|
|
for inspecting mutation-log entries, resync pressure, and sequence cursors,
|
2026-06-14 05:09:17 +01:00
|
|
|
including typed put-document and delete identity projections on individual
|
|
|
|
|
entries while cache mutation remains owned by the existing replication
|
|
|
|
|
helpers.
|
2026-06-14 04:50:05 +01:00
|
|
|
`apply_shard_log_response(...)`, `CultMeshDatabase`, and
|
|
|
|
|
`CultMeshGameSession` can consume typed shard-log responses directly for
|
|
|
|
|
database sync and prediction reconciliation.
|
2026-06-14 04:36:46 +01:00
|
|
|
`CultMeshDatabase.build_shard_log_response(...)` creates the typed response
|
2026-06-14 05:38:25 +01:00
|
|
|
from the package-local mutation log and reports resync-required responses for
|
|
|
|
|
unknown shards or stale epoch cursors; `create_shard_log_response(...)`
|
|
|
|
|
remains the raw wire-dict compatibility projection.
|
2026-06-14 06:27:50 +01:00
|
|
|
- Python CultNet shard replication:
|
2026-06-14 06:39:31 +01:00
|
|
|
Provides schema-v0 shard-log and shard-snapshot fetchers, a schema-v0
|
2026-06-14 11:41:41 +01:00
|
|
|
write-forwarder for raw put/delete messages, plus a
|
2026-06-14 06:27:50 +01:00
|
|
|
`CultNetShardReplicator` that tracks replica cursors, applies log responses
|
2026-06-14 11:41:41 +01:00
|
|
|
through the existing database owner, runs explicit background pull loops for
|
|
|
|
|
non-primary shards with advertised primaries, reports loop errors through a
|
|
|
|
|
caller-owned callback, and recovers from compacted-history resync pressure by
|
|
|
|
|
fetching a shard snapshot. Replica cursor storage can be in-memory or
|
2026-06-14 16:31:32 +01:00
|
|
|
restart-safe through a local MessagePack cursor file. The write-forwarder is
|
|
|
|
|
also exercised against a launched Python daemon endpoint: forwarded raw
|
|
|
|
|
put/delete messages mutate daemon state and are recorded in the daemon-served
|
|
|
|
|
shard log.
|
2026-06-14 04:13:44 +01:00
|
|
|
- Python CultNet database subscription changes:
|
|
|
|
|
Provides typed `CultNetDatabaseChange` parsing plus
|
|
|
|
|
`CultNetDatabaseSubscription.read_next_change(...)` / `iter_changes(...)` for
|
2026-06-14 04:44:51 +01:00
|
|
|
live raw database subscriptions. Put/update changes expose their contained
|
|
|
|
|
raw document as a typed `CultNetRawDocumentRecord` while preserving the legacy
|
|
|
|
|
dict-shaped `document` projection. Initial snapshot frames can be read as
|
|
|
|
|
typed `CultNetRawSnapshotResponse` values through
|
|
|
|
|
`read_next_snapshot_response(...)` / `iter_snapshot_responses(...)`, while
|
|
|
|
|
raw message reads remain available for callers that own their own dispatch
|
|
|
|
|
loop.
|
2026-06-14 05:04:06 +01:00
|
|
|
- Python CultNet witness artifacts:
|
|
|
|
|
Provides typed `CultNetWitnessArtifactBundle` ownership for the C#-compatible
|
|
|
|
|
8-slot witness artifact payload while preserving dict helpers for existing
|
|
|
|
|
wire callers.
|
2026-06-16 00:06:56 +01:00
|
|
|
- Python CultNet RUDP transport:
|
|
|
|
|
Provides the shared `cultnet.transport.rudp.v0` packet codec, deterministic
|
|
|
|
|
RUDP session state machine, socket-backed single-peer transport connection,
|
|
|
|
|
transport profile advertisement, ping/pong, disconnect reason propagation,
|
|
|
|
|
timeout state, fragmentation/reassembly, reliable ordered `schema` delivery,
|
|
|
|
|
unreliable sequenced `latest`, unreliable unordered `realtime`, resend
|
2026-06-16 03:07:31 +01:00
|
|
|
pressure, bounded reliable-send backpressure, and the portable
|
2026-06-16 05:29:45 +01:00
|
|
|
`cultnet.reconnect_policy.v0` delay-policy helper plus reconnect controller
|
2026-06-16 06:28:22 +01:00
|
|
|
advertised through RUDP transport profiles. `CultNetRudpReconnectLoop`
|
|
|
|
|
consumes that controller for caller-owned RUDP transport factories, matching
|
|
|
|
|
the TypeScript/Kotlin reconnect-loop shape without making the socket factory
|
|
|
|
|
a hidden global. The TypeScript interop harness proves bidirectional Python/TypeScript RUDP socket exchange,
|
2026-06-16 00:06:56 +01:00
|
|
|
packet-loss recovery, reordering recovery, fragmentation, ping/pong, and
|
|
|
|
|
disconnect reason propagation through the shared wire language.
|
2026-06-14 01:03:39 +01:00
|
|
|
- Python CultMesh discovery client:
|
2026-06-14 06:18:58 +01:00
|
|
|
Fetches Verse catalogs and peer exchange responses from live endpoints over
|
|
|
|
|
CultNet frames. It can also parse `cultnet://host:port` endpoints, discover
|
2026-06-14 12:15:39 +01:00
|
|
|
from endpoint lists, de-duplicate discovery targets, fan out one-shot
|
|
|
|
|
discovery from endpoints already advertised in local Verse and peer catalogs,
|
2026-06-14 13:17:50 +01:00
|
|
|
fan out raw snapshot fetches and simulation observations to peer-card
|
2026-06-14 13:34:50 +01:00
|
|
|
endpoints, apply peer snapshots through a caller-owned database, run
|
2026-06-14 13:44:57 +01:00
|
|
|
lightweight scheduled snapshot and simulation-observation fanout loops, probe
|
2026-06-14 14:30:15 +01:00
|
|
|
peer-card endpoints for hello-level reachability, preserve hello capability
|
2026-06-14 15:58:48 +01:00
|
|
|
metadata on health results including document types, message versions, and
|
|
|
|
|
mutation contracts, run immediate scheduled health probes on start, and
|
|
|
|
|
upsert results into local catalogs with the same count-returning ergonomics
|
|
|
|
|
as the C# discovery clients.
|
2026-06-14 01:50:15 +01:00
|
|
|
- Python CultMesh facade:
|
|
|
|
|
Exposes C#-matching client entrypoints for Verse discovery, peer exchange,
|
2026-06-16 16:31:13 +01:00
|
|
|
raw CultNet client construction, local nodes, Verse catalogs, peer catalogs,
|
|
|
|
|
schema catalogs, built-in schema catalogs, shard catalogs, sessions, streams,
|
2026-06-16 16:42:03 +01:00
|
|
|
authority leases, local TCP node serving, simulation fact commits, RUDP
|
|
|
|
|
endpoint parsing, and RUDP client/server construction from endpoint or
|
2026-06-16 16:52:20 +01:00
|
|
|
peer-card contact hints. Peer catalogs expose authorized-peer lookup, and the
|
|
|
|
|
branded facade can open a RUDP client from the first peer authorized by the
|
|
|
|
|
authority lease catalog for a Verse role, keeping endpoint contact separate
|
|
|
|
|
from trust. The durable shard-log node option attaches a file-backed
|
|
|
|
|
authoritative log store beside the cache file by default. Schema, shard, and
|
|
|
|
|
RUDP factories delegate to the existing `cultnet_py` owners, so the branded
|
|
|
|
|
entrypoint does not create a second source of discovery or transport truth.
|
|
|
|
|
The `cultmesh-py-daemon` /
|
2026-06-14 15:28:25 +01:00
|
|
|
`python -m cultmesh_py.daemon` entrypoint launches that same local TCP server
|
|
|
|
|
body and emits a bounded readiness document for process supervisors while the
|
2026-06-14 16:44:21 +01:00
|
|
|
served CultNet endpoint remains the capability owner. Readiness now mirrors
|
|
|
|
|
the served hello capability metadata, shard ids, and configured snapshot
|
|
|
|
|
limits so supervisors can inspect startup state without inventing a second
|
2026-06-14 17:26:34 +01:00
|
|
|
protocol truth. Readiness also includes the same Verse descriptors and peer
|
|
|
|
|
cards served by the live discovery endpoints, keeping operator and agent
|
|
|
|
|
inspection tied to the catalogs that own mesh identity. The daemon can
|
|
|
|
|
register and seed the package interop-note
|
2026-06-14 16:44:21 +01:00
|
|
|
document so launched processes advertise a real payload schema and serve both
|
|
|
|
|
a real snapshot and a real shard-log entry over the same CultNet lane. When
|
|
|
|
|
launched with a Verse id, it publishes its actual bound endpoint in the Verse
|
|
|
|
|
and peer catalogs so discovery clients can find the running Python peer
|
|
|
|
|
without embedding code-owned catalogs. With a cache file and durable shard-log
|
|
|
|
|
path, a restarted daemon can rehydrate the persisted interop-note snapshot and
|
|
|
|
|
shard-log entry without reseeding. The launched daemon also accepts raw puts
|
|
|
|
|
over a live database subscription stream, emits the matching change
|
|
|
|
|
notification, and records the mutation in the served shard log. If its durable
|
|
|
|
|
shard log has been compacted, stale shard-log requests return the same
|
|
|
|
|
explicit `compacted_history` resync boundary over the daemon wire endpoint
|
2026-06-14 16:51:30 +01:00
|
|
|
instead of silently looking empty. Simulation observation serving is opt-in:
|
|
|
|
|
the daemon only advertises `cultnet.simulation_observation.v0` when an
|
|
|
|
|
observation hub is attached, and an opt-in launched daemon answers witness
|
2026-06-14 16:57:48 +01:00
|
|
|
observations with schema-v0 consensus candidates. When such a daemon
|
|
|
|
|
self-advertises into a Verse, its peer card includes the `simulation-observer`
|
|
|
|
|
role so discovery clients can find the peer by the capability it actually
|
|
|
|
|
serves.
|
2026-06-14 16:37:48 +01:00
|
|
|
The daemon CLI snapshot document/byte limits feed the same public server edge;
|
|
|
|
|
oversized daemon snapshot responses are returned as structured
|
|
|
|
|
`cultnet.error.v0` peer errors rather than partial payloads.
|
2026-06-14 06:07:24 +01:00
|
|
|
- Python CultMesh authority leases:
|
|
|
|
|
Lease objects own validity and peer/role/shard coverage checks; the catalog
|
2026-06-14 12:46:30 +01:00
|
|
|
owns sorted listing, lookup, upsert, signature verification policy, and
|
|
|
|
|
authorization delegation, matching the C# reference authority boundary.
|
|
|
|
|
Callers can require verified signatures and use the packaged HMAC verifier to
|
|
|
|
|
issue and verify canonical lease payloads keyed by issuer runtime.
|
2026-06-14 03:18:38 +01:00
|
|
|
- Python CultMesh local server:
|
|
|
|
|
Serves a `CultMeshNode` plus Verse and peer catalogs over the same framed
|
|
|
|
|
MessagePack request/response lane used by `CultNetRawClient` and
|
2026-06-16 04:11:24 +01:00
|
|
|
`CultMeshDiscoveryClient`. Accepted connections now read and write through
|
|
|
|
|
the shared `TcpFramedTransportConnection` port rather than owning raw frame
|
|
|
|
|
I/O in the server loop. It also supports live raw database subscriptions for
|
|
|
|
|
snapshot, put, and delete notifications on a connected client stream.
|
2026-06-14 12:06:20 +01:00
|
|
|
When given a `CultNetSimulationObservationHub`, it accepts
|
|
|
|
|
`cultnet.simulation_observation.v0` messages and replies with current
|
|
|
|
|
`cultnet.simulation_consensus_candidate.v0` messages through the same framed
|
|
|
|
|
lane.
|
2026-06-14 03:45:19 +01:00
|
|
|
Its schema catalog includes both registered document payload schemas and
|
|
|
|
|
shared wire-message descriptors for the CultNet/CultMesh messages it handles.
|
2026-06-14 05:48:41 +01:00
|
|
|
Hello and payload schema descriptors advertise the raw snapshot, put, delete,
|
|
|
|
|
and shard-log mutation surfaces the server actually serves.
|
2026-06-14 14:23:03 +01:00
|
|
|
Unsupported request schemas, malformed raw put/delete messages, and snapshot
|
|
|
|
|
limit violations return structured `cultnet.error.v0` documents instead of
|
|
|
|
|
silent stream stalls.
|
2026-06-14 05:21:43 +01:00
|
|
|
Its shard catalog advertises the database-owned shard ids, schema ids, and
|
|
|
|
|
latest shard epochs so discovery and shard-log catch-up agree on the same
|
|
|
|
|
authority.
|
2026-06-14 12:32:22 +01:00
|
|
|
Public mesh edges can set snapshot document and encoded-byte limits; oversized
|
|
|
|
|
snapshot responses are rejected as `cultnet.error.v0` before the payload is
|
|
|
|
|
sent.
|
2026-06-14 02:43:36 +01:00
|
|
|
- Python CultMesh reactive catalogs:
|
|
|
|
|
Verse and peer catalogs expose sorted local views, `get(...)`, response
|
|
|
|
|
application, and `watch(...)` callbacks for local discovery updates. Verse
|
|
|
|
|
descriptors can evaluate transfer compatibility with the same transport/rules
|
|
|
|
|
shape as the C# reference surface.
|
2026-06-14 01:56:35 +01:00
|
|
|
- Python CultMesh database facade:
|
|
|
|
|
`node.database` owns the local typed document read/write/snapshot/sync surface
|
|
|
|
|
so Python callers do not need to reach through the node composition wrapper.
|
2026-06-14 02:24:21 +01:00
|
|
|
It includes global document helpers that delegate through the same singleton
|
|
|
|
|
key invariant as `CultCache`.
|
|
|
|
|
It also exposes local `watch(...)`, `watch_record(...)`, `watch_global(...)`,
|
|
|
|
|
`watch_by_name(...)`, and `watch_by_index(...)` callbacks for database changes,
|
|
|
|
|
including authoritative shard-log reconciliation applied through the session
|
|
|
|
|
facade.
|
2026-06-14 02:18:20 +01:00
|
|
|
Change notifications carry previous values when the database can observe the
|
|
|
|
|
old record before local or replicated application.
|
2026-06-14 02:31:41 +01:00
|
|
|
It can project local envelopes into schema-v0 raw snapshot responses and apply
|
2026-06-14 04:36:46 +01:00
|
|
|
those responses back through the shared CultNet replication path. Typed
|
|
|
|
|
builders own the local response shape and raw dict methods serialize that
|
|
|
|
|
shape for compatibility with older callers and wire handlers.
|
2026-06-14 05:27:09 +01:00
|
|
|
Shard-scoped raw snapshots filter by shard-log membership when the database
|
|
|
|
|
has an authoritative log for the requested shard.
|
2026-06-14 03:03:47 +01:00
|
|
|
Raw shard-scoped writes append a package-local mutation log that can be
|
|
|
|
|
projected into schema-v0 shard-log responses for peer catch-up.
|
2026-06-14 01:03:39 +01:00
|
|
|
- Python CultMesh committed simulation facts:
|
|
|
|
|
The live interop harness sends Python a simulation observation, receives a
|
|
|
|
|
consensus candidate, then requests the committed `gamecult.mesh.simulation_fact`
|
|
|
|
|
document back over the raw snapshot lane and checks its MessagePack slots.
|
2026-06-14 04:57:41 +01:00
|
|
|
Python exposes typed `CultNetSimulationObservation` and
|
|
|
|
|
`CultNetSimulationConsensusCandidate` objects for local consensus and
|
|
|
|
|
game-session commit paths while preserving the schema-v0 dict projections
|
2026-06-14 14:38:16 +01:00
|
|
|
used by the wire harness. Scheduled simulation-observation fanout keeps
|
|
|
|
|
queued observations pending when no peer produces a candidate, even when
|
|
|
|
|
endpoint failures are reported through a caller-owned error callback.
|
2026-06-14 01:12:03 +01:00
|
|
|
- Python CultMesh prediction reconciliation:
|
|
|
|
|
The live interop harness runs a Python CultMesh session client, writes a local
|
|
|
|
|
prediction, pulls the live Python peer shard log, applies the authoritative
|
|
|
|
|
entry, and verifies the session reports the record as reconciled.
|
2026-06-14 13:08:16 +01:00
|
|
|
Python sessions also expose pending prediction inspection, resimulation input
|
|
|
|
|
listing, explicit rollback of one or all pending predictions, and
|
|
|
|
|
authoritative-delete rollback when a shard log rejects speculative local
|
|
|
|
|
input.
|
2026-06-14 06:12:38 +01:00
|
|
|
- Python CultMesh session watches:
|
|
|
|
|
`CultMeshGameSession.watch_candidates(...)` and
|
|
|
|
|
`watch_simulation_facts(...)` expose the same gameplay-facing observation and
|
2026-06-14 17:11:43 +01:00
|
|
|
committed-fact watch points as the C# session facade. A game session can also
|
|
|
|
|
serve its own Verse catalog, peer catalog, and simulation observation hub over
|
|
|
|
|
the local framed CultMesh server so peer-facing session state uses the same
|
2026-06-14 17:19:19 +01:00
|
|
|
wire contracts as lower-level server callers. Session serving options can keep
|
|
|
|
|
individual discovery, peer exchange, or simulation surfaces unserved without
|
|
|
|
|
advertising disabled capabilities.
|
2026-06-14 01:03:39 +01:00
|
|
|
- Python package health:
|
Split the Python runtime into cultcache-py, cultnet-py, cultmesh-py
One distribution named cultcache-py carried three libraries. Rust and
TypeScript layer them as cultcache < cultnet < cultmesh; Python now does
the same, one package per layer, module names unchanged so every
`from cultmesh_py import ...` keeps working.
Two imports ran against that layering and are resolved by moving code to
where the dependency direction says it lives, not by adding a shim:
- cultnet_py.interop_peer imported the Verse/peer catalog, authority
lease, stream, and simulation-fact contracts from cultmesh_py. They are
wire contracts a bare peer has to speak without owning a node, which is
why cultnet-rs and cultnet-ts keep them in the net layer. They now live
in cultnet_py.cultmesh_contracts; cultmesh_py re-exports them.
- cultcache_py.benchmark imported cultnet_py. It measures framed CultNet
parse beside cache paths, so it and compare_csharp move to cultnet_py.
verify checks all three packages and moves to cultmesh_py.
The single 6,693-line test module is split by what each test touches: a
test using any cultmesh_py name lands in cultmesh-py, else cultnet_py in
cultnet-py, else cultcache-py. Each suite runs with only its layer and the
layers below on the path, so a test that reaches up fails to import
rather than quietly binding the packages back together. 11 / 53 / 78 =
the same 142.
Workflows install all three; the publish job is one matrix over the
three packages keyed by tag prefix. The TS test harnesses put all three
src directories on PYTHONPATH. cultcache-py bumps to 0.2.0 because it no
longer contains cultnet_py or cultmesh_py; the new packages start at
0.1.0. Nothing was ever published, so no PyPI consumer moves.
cultcache-py 11 tests, path: cultcache-py/src
cultnet-py 53 tests, path: + cultnet-py/src
cultmesh-py 78 tests, path: + cultmesh-py/src
python -m cultmesh_py.verify -> ok, all five checks
cultnet_py.interop_peer imports with cultmesh_py absent
Not run here: the cultnet-ts interop ring and cultcache-ts store matrix
need dotnet/kotlin peers; their PYTHONPATH change is four lines.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 13:10:47 +02:00
|
|
|
`cultmesh-py-verify --json` checks the public CultCache/CultNet/CultMesh
|
2026-06-14 14:56:11 +01:00
|
|
|
export surface declared by each package `__all__`, `py.typed` markers, a live
|
|
|
|
|
local CultMesh framed-wire smoke over hello/schema/snapshot/shard
|
|
|
|
|
catalog/shard log, typed peer-error export availability, peer-advertised
|
2026-06-14 17:05:19 +01:00
|
|
|
mutation contracts, payload schema wire contracts, simulation capability
|
|
|
|
|
truth, and benchmark sanity for Python-owned hot paths.
|
2026-06-14 01:30:50 +01:00
|
|
|
- Python/C# public cache baseline:
|
Split the Python runtime into cultcache-py, cultnet-py, cultmesh-py
One distribution named cultcache-py carried three libraries. Rust and
TypeScript layer them as cultcache < cultnet < cultmesh; Python now does
the same, one package per layer, module names unchanged so every
`from cultmesh_py import ...` keeps working.
Two imports ran against that layering and are resolved by moving code to
where the dependency direction says it lives, not by adding a shim:
- cultnet_py.interop_peer imported the Verse/peer catalog, authority
lease, stream, and simulation-fact contracts from cultmesh_py. They are
wire contracts a bare peer has to speak without owning a node, which is
why cultnet-rs and cultnet-ts keep them in the net layer. They now live
in cultnet_py.cultmesh_contracts; cultmesh_py re-exports them.
- cultcache_py.benchmark imported cultnet_py. It measures framed CultNet
parse beside cache paths, so it and compare_csharp move to cultnet_py.
verify checks all three packages and moves to cultmesh_py.
The single 6,693-line test module is split by what each test touches: a
test using any cultmesh_py name lands in cultmesh-py, else cultnet_py in
cultnet-py, else cultcache-py. Each suite runs with only its layer and the
layers below on the path, so a test that reaches up fails to import
rather than quietly binding the packages back together. 11 / 53 / 78 =
the same 142.
Workflows install all three; the publish job is one matrix over the
three packages keyed by tag prefix. The TS test harnesses put all three
src directories on PYTHONPATH. cultcache-py bumps to 0.2.0 because it no
longer contains cultnet_py or cultmesh_py; the new packages start at
0.1.0. Nothing was ever published, so no PyPI consumer moves.
cultcache-py 11 tests, path: cultcache-py/src
cultnet-py 53 tests, path: + cultnet-py/src
cultmesh-py 78 tests, path: + cultmesh-py/src
python -m cultmesh_py.verify -> ok, all five checks
cultnet_py.interop_peer imports with cultmesh_py absent
Not run here: the cultnet-ts interop ring and cultcache-ts store matrix
need dotnet/kotlin peers; their PYTHONPATH change is four lines.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 13:10:47 +02:00
|
|
|
`cultnet_py.compare_csharp` runs Python and C# `CultCache` upsert/get
|
2026-06-14 05:53:46 +01:00
|
|
|
benchmarks with the same operation names and reports median Python-to-C# ratios
|
2026-06-14 13:56:56 +01:00
|
|
|
from three samples by default. It also emits per-metric threshold checks and an
|
|
|
|
|
overall parity status so performance claims have an explicit evidence gate.
|
2026-06-14 20:08:25 +01:00
|
|
|
Both benchmark lanes precompute record keys before measuring public cache
|
|
|
|
|
reads and writes, matching the C# reference benchmark shape instead of
|
|
|
|
|
charging one runtime for key construction inside the hot path.
|
2026-06-14 15:12:40 +01:00
|
|
|
The Python in-memory record owner is type-partitioned so public `get(...)`
|
|
|
|
|
reads avoid per-call composite-key allocation on the hot path.
|
2026-06-14 01:03:39 +01:00
|
|
|
|
|
|
|
|
## Local Python Gates
|
|
|
|
|
|
|
|
|
|
```powershell
|
Split the Python runtime into cultcache-py, cultnet-py, cultmesh-py
One distribution named cultcache-py carried three libraries. Rust and
TypeScript layer them as cultcache < cultnet < cultmesh; Python now does
the same, one package per layer, module names unchanged so every
`from cultmesh_py import ...` keeps working.
Two imports ran against that layering and are resolved by moving code to
where the dependency direction says it lives, not by adding a shim:
- cultnet_py.interop_peer imported the Verse/peer catalog, authority
lease, stream, and simulation-fact contracts from cultmesh_py. They are
wire contracts a bare peer has to speak without owning a node, which is
why cultnet-rs and cultnet-ts keep them in the net layer. They now live
in cultnet_py.cultmesh_contracts; cultmesh_py re-exports them.
- cultcache_py.benchmark imported cultnet_py. It measures framed CultNet
parse beside cache paths, so it and compare_csharp move to cultnet_py.
verify checks all three packages and moves to cultmesh_py.
The single 6,693-line test module is split by what each test touches: a
test using any cultmesh_py name lands in cultmesh-py, else cultnet_py in
cultnet-py, else cultcache-py. Each suite runs with only its layer and the
layers below on the path, so a test that reaches up fails to import
rather than quietly binding the packages back together. 11 / 53 / 78 =
the same 142.
Workflows install all three; the publish job is one matrix over the
three packages keyed by tag prefix. The TS test harnesses put all three
src directories on PYTHONPATH. cultcache-py bumps to 0.2.0 because it no
longer contains cultnet_py or cultmesh_py; the new packages start at
0.1.0. Nothing was ever published, so no PyPI consumer moves.
cultcache-py 11 tests, path: cultcache-py/src
cultnet-py 53 tests, path: + cultnet-py/src
cultmesh-py 78 tests, path: + cultmesh-py/src
python -m cultmesh_py.verify -> ok, all five checks
cultnet_py.interop_peer imports with cultmesh_py absent
Not run here: the cultnet-ts interop ring and cultcache-ts store matrix
need dotnet/kotlin peers; their PYTHONPATH change is four lines.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 13:10:47 +02:00
|
|
|
$env:PYTHONPATH="$PWD\packages\cultcache-py\src;$PWD\packages\cultnet-py\src;$PWD\packages\cultmesh-py\src"
|
2026-06-14 01:03:39 +01:00
|
|
|
python -m unittest discover -s packages\cultcache-py\tests
|
Split the Python runtime into cultcache-py, cultnet-py, cultmesh-py
One distribution named cultcache-py carried three libraries. Rust and
TypeScript layer them as cultcache < cultnet < cultmesh; Python now does
the same, one package per layer, module names unchanged so every
`from cultmesh_py import ...` keeps working.
Two imports ran against that layering and are resolved by moving code to
where the dependency direction says it lives, not by adding a shim:
- cultnet_py.interop_peer imported the Verse/peer catalog, authority
lease, stream, and simulation-fact contracts from cultmesh_py. They are
wire contracts a bare peer has to speak without owning a node, which is
why cultnet-rs and cultnet-ts keep them in the net layer. They now live
in cultnet_py.cultmesh_contracts; cultmesh_py re-exports them.
- cultcache_py.benchmark imported cultnet_py. It measures framed CultNet
parse beside cache paths, so it and compare_csharp move to cultnet_py.
verify checks all three packages and moves to cultmesh_py.
The single 6,693-line test module is split by what each test touches: a
test using any cultmesh_py name lands in cultmesh-py, else cultnet_py in
cultnet-py, else cultcache-py. Each suite runs with only its layer and the
layers below on the path, so a test that reaches up fails to import
rather than quietly binding the packages back together. 11 / 53 / 78 =
the same 142.
Workflows install all three; the publish job is one matrix over the
three packages keyed by tag prefix. The TS test harnesses put all three
src directories on PYTHONPATH. cultcache-py bumps to 0.2.0 because it no
longer contains cultnet_py or cultmesh_py; the new packages start at
0.1.0. Nothing was ever published, so no PyPI consumer moves.
cultcache-py 11 tests, path: cultcache-py/src
cultnet-py 53 tests, path: + cultnet-py/src
cultmesh-py 78 tests, path: + cultmesh-py/src
python -m cultmesh_py.verify -> ok, all five checks
cultnet_py.interop_peer imports with cultmesh_py absent
Not run here: the cultnet-ts interop ring and cultcache-ts store matrix
need dotnet/kotlin peers; their PYTHONPATH change is four lines.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 13:10:47 +02:00
|
|
|
python -m unittest discover -s packages\cultnet-py\tests
|
|
|
|
|
python -m unittest discover -s packages\cultmesh-py\tests
|
|
|
|
|
python -m cultmesh_py.verify --json
|
|
|
|
|
python -m cultnet_py.benchmark --records 1000 --json
|
|
|
|
|
python -m cultnet_py.compare_csharp --records 1000 --samples 3 --json
|
|
|
|
|
python -m pip wheel --no-deps -w $env:TEMP packages\cultcache-py packages\cultnet-py packages\cultmesh-py
|
2026-06-14 01:03:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Cross-Runtime Gate
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
$env:PYTHON='C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe'
|
|
|
|
|
npx tsc -p packages\cultnet-ts\tsconfig.test.json --pretty false
|
|
|
|
|
node --test packages\cultnet-ts\dist-test\test\interop\cultnet-interop.test.js
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Still Not Claimed
|
|
|
|
|
|
2026-06-14 15:12:40 +01:00
|
|
|
- Python does not claim to match the C# runtime for every raw-throughput
|
|
|
|
|
workload. It has a measured local baseline plus a shared public `CultCache`
|
|
|
|
|
upsert/get comparison harness with threshold status, not a universal
|
|
|
|
|
performance victory certificate.
|
2026-06-14 17:39:07 +01:00
|
|
|
- Python does not implement the full LiteNetLib client/server auth flow. It now
|
|
|
|
|
owns the shared security/session primitives for helper parity, while the live
|
|
|
|
|
transport harness still speaks the schema-v0 interop lane.
|
2026-06-16 00:06:56 +01:00
|
|
|
- Python does not make RUDP the only public pipe yet. The local CultMesh server,
|
2026-06-17 08:05:41 +01:00
|
|
|
raw client, and interop peer still keep the TCP-framed schema lane for
|
|
|
|
|
compatibility, while the Python interop peer can now serve and dial schema-v0
|
|
|
|
|
over fragmented RUDP. `docs/cultnet-transport-parity.md` tracks the
|
2026-06-16 00:06:56 +01:00
|
|
|
remaining work to put broader server-side bodies behind the shared transport
|
2026-06-16 16:13:56 +01:00
|
|
|
port instead of cloning LiteNetLib. The raw client request/subscription layer
|
|
|
|
|
now routes through a schema-transport factory, so the caller-facing semantics
|
|
|
|
|
are transport-port-shaped even when the default factory opens TCP-framed
|
2026-06-16 23:37:59 +01:00
|
|
|
connections. Python raw clients can now use a RUDP schema transport directly
|
|
|
|
|
through `create_rudp_schema_transport(...)` or the `CultMesh.create_client`
|
|
|
|
|
RUDP endpoint helper. The reconnect policy/controller primitive is portable
|
|
|
|
|
and advertised by RUDP profiles, and `CultNetRudpReconnectLoop` gives Python
|
|
|
|
|
callers the same RUDP retry-scheduling helper as TypeScript/Kotlin. Automatic
|
|
|
|
|
reconnect use by Python service bodies is not yet claimed.
|
2026-06-14 01:03:39 +01:00
|
|
|
- Python does not implement the full C# daemon/server stack. Its current role is
|
2026-06-14 15:28:25 +01:00
|
|
|
package runtime, raw interop peer, launchable local CultMesh endpoint, local
|
|
|
|
|
CultMesh session facade, and typed state participant.
|
2026-06-14 02:31:41 +01:00
|
|
|
- Python does not claim the full C# shard mutation-log service surface. It can
|
2026-06-14 03:03:47 +01:00
|
|
|
create/apply raw snapshots, create/apply package-local raw shard-log
|
2026-06-14 06:27:50 +01:00
|
|
|
responses, consume remote shard-log responses, and run pull-once replica
|
2026-06-14 06:39:31 +01:00
|
|
|
catch-up with snapshot recovery, a file-backed replica cursor store, and
|
2026-06-14 11:41:41 +01:00
|
|
|
schema-v0 write forwarding. It also has an explicit package-level background
|
|
|
|
|
pull loop for caller-provided shard descriptors. Its authoritative shard-log
|
2026-06-14 11:54:44 +01:00
|
|
|
store is file-backed, supports compaction watermarks, and can be attached by
|
|
|
|
|
`CultMeshNodeOptions(enable_durable_shard_logs=True)`, but it is still
|
2026-06-14 11:41:41 +01:00
|
|
|
package-local rather than the full C# daemon/server stack.
|