Commit graph CultLib/packages/cultnet-ts/test
Author SHA1 Message Date
Meta Vens
95493862bd 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
Meta Vens
2041a0e0ed Bound the TypeScript fragment reassembly map
cultnet-ts removed a fragment buffer only on successful reassembly, with
no cap, no eviction and no timeout. A fragment set that loses one
fragment was stranded for the life of the session, so the map grew
without bound under any loss on a fragmenting channel. cultnet-rs at
least fails closed at 64 pending sets; TypeScript just consumes memory.

This is live, not theoretical. Ghostlight sends Heimdall sealed envelopes
over CultMesh RUDP with max_fragment_bytes = 2048
(Ghostlight/crates/ghostlight-dungeon/src/heimdall.rs:697), and Heimdall's
private command plane reassembles them through this path. Every lost
fragment on that link left a buffer nothing would ever collect, on a
long-running auth service.

Caps pending sets at 64 to match cultnet-rs's max_pending_fragment_sets,
and evicts the oldest stranded set rather than refusing the payload:
a receiver that stops accepting fragmented traffic after a bounded number
of losses is a denial of service delivered by the network. Map iteration
is insertion-ordered, so the first key is the oldest. fragmentSetsEvicted
and pendingFragmentSetCount make it observable.

Found by the Muninn media load test, which hit the Rust half of the same
defect; cultcache-py has the same unbounded map and is not touched here.

  npm run test --workspace=packages/cultnet-ts -> pass 54, fail 0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 11:42:13 +02:00
Meta Vens
d1a9edad3a Port gamecult.runtime_presence_health.v2 to cultnet-ts
The dual-proved runtime presence contract existed only in cultnet-rs, so no
TypeScript service could make a statement Odin admits as presence. Odin files
anything else away as an ordinary document and never produces a topology
correlation for it, which is why Heimdall could warm forever without being
promoted.

The port is what it should be: the same fields at the same key slots. The Rust
derive serialises a positional tuple indexed by those slots, so the TypeScript
side names the slots and fills the same 24. Both proofs cover one payload --
the complete record with both signature fields empty -- and the two signing
messages use the domain separation their respective identities already define.

Conformance is against vectors emitted by cultnet-rs, not a fixture written
for both sides at once, which would agree with itself and prove nothing:
`cargo run --example runtime_presence_vector -p cultnet-rs` regenerates them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 21:42:54 +02:00
Meta Vens
77313ed48c Stop the interop harness leaking peers and hanging after it passes
The suite finished its work in about 60 seconds and then never exited. Four runs
were left alive for hours, holding 11 node and 2 dotnet peers, and a stranded
peer holding cultnet_interop_peer.exe is what made two unrelated cargo builds
fail with LNK1104. In CI this is a job that burns its whole timeout on green
tests.

Two real defects, found by asking the stuck process what it was waiting on
rather than by guessing. process.getActiveResourcesInfo reported four UDPWraps
and two PipeWraps still held after the last test.

The four UDP sockets: eight tests bind a server socket with bindUdpSocket and
close only the transport wrapper in their finally, never the socket itself. Four
leaked per run, matching the four Python lanes that fail on a machine without
msgpack -- the wrapper is built inside the try, so when the peer's readiness
rejects it never exists to be closed, and the raw socket is orphaned. Now closed
through a guarded helper that tolerates a transport having adopted it.

The teardown registration: t.after was registered after every `await ready`, so
a peer whose readiness rejected skipped the registration entirely and stranded
every peer already spawned. Moved ahead of the spawns at all four sites.

With those fixed the suite still does not drain on its own, so test:interop now
passes --test-force-exit. That is safe only because cleanup demonstrably
completes first: a forced run now leaves zero peers behind, where before it left
nine. Forcing the exit without the fixes above would have guaranteed orphans
rather than prevented them.

Verified: 65 seconds, exit 1, the expected 15 pass and 12 fail, no surviving
processes. The 12 failures are the Python lanes, which cannot run on this
machine and are unrelated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 16:32:10 +02:00
Meta Vens
8cb3b7282b Publish the non-Rust packages and make the licensing uniform
Rust consumers pin a CultLib revision through cargo git dependencies, which is
how Ghostlight, Epiphany, CodexConnector and Odin already consume the core
stack. npm and pip cannot take a package from a subdirectory of a git repo at
all, which is why the TypeScript and Python consumers vendored forks instead:
there was nothing else to depend on. This gives them a versioned artifact.

Tagging cultcache-ts-v* or cultcache-py-v* builds, tests and publishes. The tag
version must match the manifest version or the workflow refuses rather than
shipping a mislabelled artifact. PyPI uses trusted publishing, so no long-lived
token is stored; npm needs an NPM_TOKEN secret.

cultcache-ts is now @gamecult/cultcache-ts. The scope is not cosmetic: it makes
the package unambiguously org-owned on a public registry, and it is what lets
CultLib hold the name rather than racing for an unscoped one. CultLib's own
cultmesh-ts and cultnet-ts and their imports move with it; all three packages
typecheck and cultcache-ts passes 12 of 13 tests, the exception being the
cross-runtime store test that shells out to Python, which cannot run on this
machine because its Python has no msgpack.

Licensing was inconsistent with the repo. cultcache-py declared itself "Private
GameCult infrastructure" and cultcache-rs and cultmesh-rs declared nothing,
inside a repo whose LICENSE is MIT and whose every other package says MIT. All
three now say MIT. That was load-bearing here: a package that calls itself
private is not one to push to a public registry.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:41:44 +02:00
Meta Vens
0736ae4824 Separate RUDP reliable and lossy sequence domains 2026-09-04 00:33:16 +02:00
Meta Vens
334e60f192 Recover authority-bound CultMesh and atomic generations 2026-08-26 19:01:24 +02:00
Meta Vens
75c180782a Acknowledge retransmits across RUDP horizons 2026-08-23 19:15:22 +02:00
Meta Vens
fda51fad50 Acknowledge reliable RUDP windows cumulatively 2026-08-23 19:00:33 +02:00
Meta Vens
f4dabfefb0 Bound RUDP reliable transmission windows 2026-08-23 18:35:49 +02:00
Meta Vens
f622ee1b24 Authenticate CultMesh authority routes and replay operations 2026-08-18 19:02:46 +02:00
Meta Vens
6c848bd6c0 Bind CultMesh authority identity to physical routes 2026-08-18 17:21:58 +02:00
Meta Vens
d563a1ac64 Discover browser providers through Odin 2026-08-18 00:34:44 +02:00
Meta Vens
8eb89e38ec Add real browser CultMesh transport proof 2026-08-18 00:05:57 +02:00
Meta Vens
3fe2e9be1b Publish browser subscription wire contracts 2026-08-17 23:26:51 +02:00
Meta Vens
5c075bc212 Fence provider RUDP connection generations 2026-07-19 00:50:20 +01:00
Meta Vens
ddb5418e04 Add CultNet RUDP operation service host 2026-07-10 11:20:51 +01:00
Meta Vens
2272aeff08 Add CultNet operation service envelopes 2026-07-10 11:11:28 +01:00
Meta Vens
340df225d4 Align TypeScript RUDP acknowledgement sequencing 2026-07-10 06:56:49 +01:00
Meta Vens
94a8c5b104 Resolve TS shard discovery filters by schema alias 2026-06-27 21:57:54 +01:00
Meta Vens
aeb7a96bd3 Resolve TS typed document messages by schema alias 2026-06-27 21:56:02 +01:00
Meta Vens
2738f4c2db Resolve TS snapshot filters by schema alias 2026-06-27 21:46:05 +01:00
Meta Vens
af2bd4a82d Resolve TS snapshot aliases by payload shape 2026-06-27 21:17:07 +01:00
Meta Vens
b2f2e1a0ff Add Kotlin interop RUDP serve dial path 2026-06-17 12:45:30 +01:00
Meta Vens
cd3f3c28f6 Add C# interop RUDP serve dial path 2026-06-17 11:22:17 +01:00
Meta Vens
c80703172a Add Rust interop RUDP serve dial path 2026-06-17 10:07:37 +01:00
Meta Vens
91d9ecda93 Add Python interop RUDP serve dial path 2026-06-17 08:05:41 +01:00
Meta Vens
25847c0845 Add TypeScript interop RUDP serve dial path 2026-06-17 07:28:47 +01:00
Meta Vens
e9ee0b59a1 Harden interop lane diagnostics 2026-06-16 18:52:02 +01:00
Meta Vens
f0ae8aed7f Harden interop discovery lane timeouts 2026-06-16 18:05:23 +01:00
Meta Vens
7711edf930 Advertise TS shard catalog schemas 2026-06-16 15:12:12 +01:00
Meta Vens
8bc505f0c1 Add TypeScript shard catalog sync helpers 2026-06-16 13:53:12 +01:00
Meta Vens
30934fc776 Add TypeScript schema catalog sync helpers 2026-06-16 13:36:34 +01:00
Meta Vens
4335ab10bd Fix RUDP ordered control sequence parity 2026-06-16 13:18:39 +01:00
Meta Vens
805539384e Add TypeScript TCP peer helper 2026-06-16 12:15:23 +01:00
Meta Vens
fad79906be Route TS interop through transport port 2026-06-16 09:51:00 +01:00
Meta Vens
3805352dbb Add TypeScript RUDP reconnect loop 2026-06-16 05:58:28 +01:00
Meta Vens
4a54966b10 Add portable reconnect controllers 2026-06-16 05:29:45 +01:00
Meta Vens
8f50f2eece Assert RUDP reconnect policy in interop profiles 2026-06-16 04:22:19 +01:00
Meta Vens
9e97d94796 Advertise RUDP reconnect policy in profiles 2026-06-16 04:01:41 +01:00
Meta Vens
b3be836115 Add portable reconnect policy helpers 2026-06-16 03:07:31 +01:00
Meta Vens
0569462efd Prove Rust schema messages over RUDP 2026-06-16 02:23:02 +01:00
Meta Vens
409a42e0f7 Prove Python schema messages over RUDP 2026-06-16 01:42:02 +01:00
Meta Vens
6373f8126b Add C# RUDP schema message ergonomics 2026-06-15 23:38:42 +01:00
Meta Vens
cf7330f31b Add Kotlin schema-v0 RUDP ergonomics 2026-06-15 22:14:13 +01:00
Meta Vens
48135703e8 Preserve Libby persona state and database preverify flow 2026-06-15 19:45:34 +01:00
Meta Vens
c85b5fb561 Add RUDP reliable queue bounds across runtimes 2026-06-15 15:24:11 +01:00
Meta Vens
8287926921 Add RUDP ping timeout parity 2026-06-15 03:26:40 +01:00
Meta Vens
59146888c0 Propagate RUDP disconnect reasons across runtimes 2026-06-15 03:11:46 +01:00
Meta Vens
436654de75 Prove RUDP reordering across runtimes 2026-06-15 02:52:01 +01:00