Builds. The ./content subpath is the only way to reach it, so the package root gains no node:fs import.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The RUDP put handler and the browser payload reader decoded a codec document with plain msgpack. cultcache-ts now
exports decodeDocumentPayload (definition or plain), the RUDP server reads a put through the registry's definition,
and decodeCultNetPayload takes the formatter. cultmesh-ts and cultmesh-browser no longer depend on @msgpack/msgpack:
frames and commands use cultnet-ts/wire, and a test per package scans src and the manifest. The envelope probe fixture
now runs the plain record first and last. Not yet built or tested on this commit; the verify job follows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UTF-8 detail bound calls String.prototype.toWellFormed, which
Node 20 introduced. Node 18 reached end of life in April 2025, and CI
runs Node 24. All four TypeScript packages move together so the family
keeps one floor.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The committed QUIC native binaries only reach a consumer if `files` carries
them: pnpm materialises a file: dependency from `files` alone, and the same
allowlist gates `npm pack` and the deploy `git archive`. Cut 6 (packaging).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Calls the runtime's private `nextEvent` directly (0 ms timeout, no
listener/connection open, so each round trip returns immediately with
status 0) 200,000 times after a warm-up, then asserts RSS growth
across the run stays under 5 MiB with `global.gc()` forced before and
after. The old per-call `koffi.alloc` code allocates a ~64 B event
struct plus a 4 B int32 every iteration and never frees either, so it
clears this bound by roughly 2x; the fixed code, which allocates
nothing per call, stays flat. Skips when no native bridge is built or
when Node wasn't started with `--expose-gc`; `npm test` now passes
`--expose-gc` so the check runs by default instead of always skipping.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds packages/cultmesh-ts/src/realtime-quic-native.ts: a lazy koffi binding
over the twelve v2 queue exports plus cultmesh_quic_last_status
(native/GameCult.Mesh.Quic.Native/include/cultmesh_quic_native.h). koffi is
required only inside loadBindings(), so a consumer that never touches QUIC
loads no native module. CultMeshQuicNativeRuntime is a process-wide,
reference-counted singleton running one event pump (a loop awaiting
nextEvent.async with a 250ms timeout, no koffi callbacks) that dispatches
decoded events to registered listener/connection handlers by id.
Also: add the koffi 3.3.0 dependency to cultmesh-ts's package.json, and switch
its tsconfig from classic Node resolution to Node16 so `cultnet-ts/contracts`
(a package.json `exports` subpath) actually resolves — a gap Cut 1 recorded
and left for this cut ("until Cut 4 changes it").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cut 5 (TypeScript). The cache no longer mirrors: StoreRoute and its mirrors
list are gone, #resolveRoute returns the single home store (the store that
claims the type, else the generic store), and put, putEnvelope and delete write
exactly one store.
addBackingStore now refuses a second generic store and a type already claimed
by another store, attaching nothing when it refuses, matching C#. No bytes
change; nothing in CultLib attached more than one store.
Tests: rejects a second generic backing store, rejects a type registered to
two stores, routes each type to its home store. The writer-by-reader interop
test now runs the C# write-routed mode and checks that catalog.cc and run.cc
are each a complete v1 snapshot holding only their own record, and that every
reader (TS, Rust, C#, Python) reads the routed catalog store.
Version 0.13.5 -> 0.14.0; cultnet-ts and cultmesh-ts depend on ^0.14.0 so the
workspace link still satisfies their range.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>