CultMeshContentVectorTests writes content-acceptance-vectors.json (what the reference accepts, refuses, rewrites and keys over nil, arity, trailing, integer/float, string-family and invalid-UTF-8 shapes), extends the record-key vectors with the prefix-fold, fallback-hash traps, and the TS writer adds a whitespace-version, padded kind and MIME pack vector. GameCult.Mesh exposes internals to its test project so the judge can call ValidateManifest. The generated files follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
63 lines
3.4 KiB
JavaScript
63 lines
3.4 KiB
JavaScript
// The TypeScript -> C# direction of the CultMesh content parity check.
|
|
//
|
|
// `contracts/cultmesh/content-vectors.cs-written.json` and `.rs-written.json` are written by the reference and by Rust
|
|
// and decoded by TypeScript. This script writes the mirror file, `contracts/cultmesh/content-vectors.ts-written.json`:
|
|
// `packages/cultnet-ts/src/content.ts` packs each declared input and encodes the manifest, and the C# test
|
|
// `CultMeshContentVectorTests.TypeScriptManifestVectorsMatchTheReference` judges the committed file with the reference
|
|
// only (it decodes the bytes, packs the same input itself and compares, and derives the record key).
|
|
//
|
|
// Deliberately not the C# file's inputs: a multi-byte artifact id, no version, integer-like metadata keys that a JS object
|
|
// would reorder, a different body and chunk size. Agreeing on a copy of the other side's inputs would prove less.
|
|
//
|
|
// npm run build --workspace packages/cultnet-ts
|
|
// node scripts/write-cultmesh-content-vectors.mjs
|
|
//
|
|
// Nothing here is randomised: rerunning on an unchanged codec rewrites the same bytes.
|
|
|
|
import { existsSync, writeFileSync } from "node:fs";
|
|
import { createRequire } from "node:module";
|
|
import { dirname, join, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const modulePath = join(repoRoot, "packages", "cultnet-ts", "dist", "content.js");
|
|
const outputPath = join(repoRoot, "contracts", "cultmesh", "content-vectors.ts-written.json");
|
|
if (!existsSync(modulePath)) {
|
|
throw new Error(`${modulePath} is missing; run 'npm run build --workspace packages/cultnet-ts' first.`);
|
|
}
|
|
const { packContent, encodeManifest, artifactRecordKey } = createRequire(import.meta.url)(modulePath);
|
|
|
|
const common = {
|
|
artifactId: "Pixel Heroes/H\u00fct \u2603",
|
|
kind: "asset",
|
|
version: "",
|
|
mimeType: "application/x-cultnet-ts-vector",
|
|
createdAtUtc: "2026-10-19T00:00:00.0000000+00:00",
|
|
chunkSizeBytes: 131072,
|
|
tags: ["a", "b"],
|
|
metadata: [["10", "x"], ["alpha", "y"], ["2", "z"]],
|
|
};
|
|
const inputs = [
|
|
["ts multi-chunk body", { ...common, body: { length: 777777, multiplier: 7, modulus: 256 } }],
|
|
["ts empty body", { ...common, body: { length: 0, multiplier: 7, modulus: 256 } }],
|
|
["ts single chunk, versioned", { ...common, version: "V1 Beta", chunkSizeBytes: 4194304, tags: [], metadata: [], body: { length: 1000, multiplier: 7, modulus: 256 } }],
|
|
// Padding the reference keeps: a whitespace version stays as written (the key reads it as unversioned), kind and MIME are
|
|
// only replaced when blank.
|
|
["ts whitespace version, padded kind and mime", { ...common, kind: " build ", version: " ", mimeType: " text/plain; charset=utf-8 ", chunkSizeBytes: 4194304, tags: [], metadata: [], body: { length: 1000, multiplier: 7, modulus: 256 } }],
|
|
];
|
|
|
|
const vectors = [];
|
|
for (const [label, input] of inputs) {
|
|
const { body, ...options } = input;
|
|
const bytes = Uint8Array.from({ length: body.length }, (_, index) => (index * body.multiplier) % body.modulus);
|
|
const { manifest } = await packContent(input.artifactId, bytes, options);
|
|
vectors.push({
|
|
label,
|
|
kind: "manifest",
|
|
input,
|
|
recordKey: await artifactRecordKey(manifest.artifactId, manifest.version, manifest.contentHash),
|
|
messagePackBase64: Buffer.from(encodeManifest(manifest)).toString("base64"),
|
|
});
|
|
}
|
|
writeFileSync(outputPath, `${JSON.stringify({ vectors }, null, 2)}\n`);
|
|
console.log(`wrote ${vectors.length} vectors to ${outputPath}`);
|