The TS provider runs in its own process on node:https with the fixture credential. The TS reader and the C# transfer service over the unmodified HTTPS connector (CustomRootTrust, fixture certificate only) each fetch from it; the orchestrator judges URL parity, the empty chunk, corrupt-store faults and the untrusted control. test:interop is wired in cultmesh-browser and the workflow, and the cultmesh-ts step now precedes the browser step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Self-signed P-256 pair for 127.0.0.1, CA:FALSE, serverAuth, with the openssl recipe in the README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mutation sweep survivors: manifest-invalid causes now asserted by field and rule, escaped-unreserved and
broken-escape endpoint rows added from .NET probes, and the two {once:true} options that the finally removal
already makes redundant are deleted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No await separates the read from the return there, and the failure race already rejects an abort that lands during the chunk hash; a mutant deleting the line survived every test because no window exists to pin.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Releasing once freed only the four running opens; the queued four blocked again
and the reverted-open run still hung. The writer now outlives all started reads.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The finally block hashed (a pool job) before releasing, so under a reverted
non-blocking open it deadlocked behind the full pool; the path is now kept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wrong-bytes refusals at 1..4 MiB+1 for both exports and mid-manifest; the .NET URL table (accepted rows
equal, divergent rows refused); redirect, late abort, stalled fetch and unallocatable size cases; port,
trailing-empty, 2xx and multi-chunk length rows; waits are bounded and abort waits fail on timeout.
Test types adapted to C1's nullable chunk refs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- redirect: "error" on every request, so no byte comes from a place the endpoint gate did not see
- endpoints on which .NET UriBuilder and WHATWG URL differ are refused (insecure-endpoint) instead of translated
- the first failure or caller abort rejects without waiting for a fetch that ignores its signal
- a caller abort landing after the last byte rejects instead of returning bytes
- an unallocatable size is too-large, not a raw RangeError
- the reader's own whole-number size rule is deleted; validateManifest owns it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A manifest or chunk size that is a fraction, NaN or Infinity is refused in the one
validator. C# sizes are long, so the wire cannot carry one; the rule guards hand-built
manifests. The reader's private copy is deleted in the next commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
U+FEFF/U+0085 key cases; microtask sweep 0..10 asserting never 200 with other
bytes; /dev/null and /dev/zero symlinks refused as non-regular; the FIFO test
releases blocked opens in finally so a blocking-open revert fails in seconds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cultnet-ts/content re-exports isNullOrWhiteSpaceCSharp; the provider uses it
instead of key.trim(), which disagreed with C# on U+FEFF and U+0085.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
encodeManifest wrote a lone surrogate as CESU bytes for short strings and
U+FFFD past the msgpack TextEncoder threshold; C# writes U+FFFD always.
utf8-bound.ts now exports wellFormed (truncateUtf8Bytes uses it) and the
manifest encoder routes every string slot through it. Test crosses the
short/long boundary for every slot. Builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A nil manifest, chunks slot or chunk element reaches the array header read, which refuses it with the same field
name; the three pre-checks were equivalent mutants in the Stryker sweep.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stryker found 30 survivors in the reader. Those that were real gaps get C#-judged vectors (early ends, a fixint or
fixmap where an array or map header must be, every integer family at a value needing its width and sign, zero-filled
fixext, extras at the header-family edges) and a test that a refusal names its true cause (negative size, nil chunk,
reserved code, early end). The null checks ahead of isNullOrWhiteSpaceCSharp were redundant with it and are gone.
Vectors regenerate in the next commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The handler copies the store's bytes before hashing and sends that copy, so a
reused store buffer cannot change the answer. The directory store opens with
O_NONBLOCK so a FIFO named by a hash is refused by fstat instead of holding a
libuv thread. New tests: exact record-key compare and blank keys, empty-hash
prefix lookalikes, single store read, buffer reuse, FIFO (POSIX, uid-independent).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BuildChunkUri trims all leading '?' of an existing query; the reader trimmed one.
Chunk placement is by offset, so sorting the refs decided nothing and is gone;
the size guard checks sizes, which fix the offsets. New behavioural tests for
the mutation survivors: absent recordKey, fractional/infinite sizes, the
fetchVerifiedChunk byte-cap boundary, undefined crypto, error messages,
abort-listener removal.
Builds and passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The encoder writes a number past uint32 as float64 under useBigInt64; the old tests leaned on the decoder accepting
that float. The reference refuses a float, so the fixtures now use bigint (uint64/int64) encodings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A purpose-built reader replaces the generic decoder: the integer rule sees the wire family (float-encoded
integers refused), nil in a reference slot reads as null and writes back as nil, missing trailing slots take the
reference's initialisers, extra slots and trailing bytes are skipped, invalid UTF-8 decodes to U+FFFD with the BOM
kept, and a map-form manifest is refused as 'manifest'. Validation still refuses nil chunks. Public type change:
string, tags and metadata fields are nullable. The acceptance vectors that judge this land in the next commits, so
content.test.ts is red until the C# writer has produced them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Builds. Tests added for error bodies and content type, maxChunkBytes 1, a non-ENOENT open failure, the not-a-file message and handle closing; the dead ?? fallbacks in toNodeListener and the unread parameter name are removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README section for fetchVerifiedContent / fetchVerifiedChunk; the CI comment
records that the content reader is proved to release only verified bytes.
Builds unaffected (docs and a comment).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reader judges received bytes: each chunk streams into its slot of a private
buffer, is cut at the first byte past its size, and is hashed; the whole body is
hashed before the buffer is returned. Length and coding headers are never read.
URLs equal the C# BuildChunkUri; concurrency 1..32, maxBytes, AbortSignal, typed
errors. Hashing, hex, keys and the loopback rule stay in cultnet-ts.
Builds and passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
Source: stableToken carries no blank check of its own (artifactRecordKey owns the artifactId refusal, a blank version
never reaches it), the single-unit regex loses its anchors, and the integer reader is Number.isSafeInteger over a decoder
without useBigInt64 (a 64-bit value a JS number cannot hold rounds to 2^53 or beyond and is refused either way).
Tests: error messages name their field (table), map-header bytes at 0/15/16/65535/65536, WebCrypto absent, schema id and
default chunk size, chunk size 1, int32 chunk-size boundary, depth error subject, default parameter names.
Builds. Co-Authored-By below.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cultmesh-portability.yml gains 'Verify the content vectors with the C# reference' (CultMeshContentVectorTests), the first
CI run of the C#/Rust content parity and of the TypeScript manifest vectors. The README describes what cultnet-ts/content
owns and how the ts-written file is regenerated.
Builds. Co-Authored-By below.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One browser-safe module owns the manifest and chunk-ref shapes, their MessagePack form (positional ten-array, metadata as
ordered entries, duplicate keys and unsafe integers refused, payload depth through cultcache-ts's own checkPayloadDepth),
normalizeHash/parseSha256Hex, both record-key grammars (StableToken per UTF-16 unit), WebCrypto sha256Hex and packContent.
cultcache-ts/document re-exports checkPayloadDepth. scripts/write-cultmesh-content-vectors.mjs writes the TypeScript
manifest vectors for the C# reference to judge.
Builds. Co-Authored-By below.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Selection is by name, so a non-site 128 array is legitimate output. The shape check is a function and the array-128 variant passes it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SPIRV-Cross names the macro from the SpecId and offers no option to rename it, so the SpecId is CultMath's own
('CMS1'); partition.py reads it from spvedit.py.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wrappers.py compiles the library with CULTMATH_MAX_SITES defined as a sentinel no shader file spells, so the three
site arrays get an array length id of their own and spvedit.py converts exactly that constant to the overridable
specialization constant (default from the HLSL guard). A library array of literal length 128 keeps its own id and
stays a plain constant. build-glsl.sh gains the pipeline function and scratch variants: a macro outside a declarator,
a folded expression reaching the capacity id, and a non-site float4 x[128] parameter that a consumer's override must
not resize. The [128] shape arm goes: a non-site 128 array is legitimate output.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cultmath-unity [Unreleased] and cultlib [Unreleased] carry the Breaking entries; no version bump, no tag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Written by CULTMATH_WRITE_GLSL=1 on Yggdrasil (sdk:10.0) at d605c70b; sha256 21eef3c38cc609909444c906a1ef965f01b541f2301023a722e64ecc4c846387. glsl-parity.json and device-bounds-lavapipe.txt are untouched by the regeneration.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SPIRV-Cross renames members matching GLSL builtins, so the source names change. Resolver and JSON writer accessors follow the members; the wire (positional MessagePack, JSON keys) is untouched in this commit. The committed GLSL is stale until its regeneration commit, so CommittedGlslEqualsLowering fails here.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>