Something went wrong. Try again.
A functional toolkit for authoring resource-leveling algorithms — compose constraint and scoring blocks, enumerate feasible schedules
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347import { readFileSync } from "node:fs";
import { test, expect, describe } from "bun:test";
import { parseConf, serializeConf, lintRegistryForConf, type ParseConfResult,} from "../../src/conf/index.ts";import { runConfigSchema, runFromConfig, type RunConfig,} from "../../src/level-blocks/runConfig.ts";import { standardBlockDefs, standardRegistry, STANDARD_CODES,} from "../../src/level-blocks/standard.ts";import { MON_JAN_5, SAT_JAN_10, makeAssignment, makeProject, makeResource, makeTask,} from "../level-core/fixtures.ts";
const registry = standardRegistry();const FIXTURES = [ "lexicographic", "variadic-nested-disabled", "minimal",] as const;
function fixtureText(name: string): string { return readFileSync(`${import.meta.dir}/fixtures/${name}.conf`, "utf8");}
function unwrap(result: ParseConfResult): RunConfig { if (!result.ok) throw new Error(`parse failed: ${JSON.stringify(result.issues, null, 2)}`); return result.config;}
/** parse(serialize(c)) reproduces c through the schema (value-lossless). */function roundTrips(config: RunConfig): void { const text = serializeConf(config); const reparsed = parseConf(text); expect(reparsed.ok).toBe(true); expect(runConfigSchema.parse(unwrap(reparsed))).toEqual( runConfigSchema.parse(config), );}
describe("serializeConf — byte-exact goldens", () => { for (const name of FIXTURES) { test(`${name} serializes to its exact fixture bytes`, () => { const text = fixtureText(name); const config = unwrap(parseConf(text, { registry })); expect(serializeConf(config)).toBe(text); }); }
test("output is deterministic", () => { const config = unwrap( parseConf(fixtureText("lexicographic"), { registry }), ); expect(serializeConf(config)).toBe(serializeConf(config)); });});
describe("serializeConf — options", () => { test("header emits top-of-file comment lines", () => { const config = unwrap(parseConf(fixtureText("minimal"), { registry })); const text = serializeConf(config, { header: ["generated by test", "do not edit"], }); expect( text.startsWith("# generated by test\n# do not edit\n\n[levelset]"), ).toBe(true); // Comments are ignored on the way back in — round trip still holds. expect(unwrap(parseConf(text))).toEqual(config); });
test("annotate comments each block with its rendered assumption", () => { const config = unwrap( parseConf(fixtureText("variadic-nested-disabled"), { registry }), ); const text = serializeConf(config, { annotate: registry }); // PeakCap's assumptionTemplate, with {resourceUniqueId}/{cap} substituted. expect(text).toContain( "# peak demand on resource 3 capped at 5 units\n[blocks.peak]", ); expect(unwrap(parseConf(text))).toEqual(config); });});
describe("serializeConf — round-trip guarantee", () => { test("every standard block at its defaultShadow round-trips", () => { for (const def of standardBlockDefs()) { const config = runConfigSchema.parse({ formatVersion: 1, pipeline: { formatVersion: 1, blocks: [ { instanceId: "b", code: def.code, params: def.defaultShadow }, { instanceId: "s", code: STANDARD_CODES.serialSGS, params: {} }, ], }, }); roundTrips(config); } });
test("each golden fixture round-trips", () => { for (const name of FIXTURES) { roundTrips(unwrap(parseConf(fixtureText(name), { registry }))); } });
test("sweep points preserve nested arrays and inline records", () => { const config = runConfigSchema.parse({ formatVersion: 1, pipeline: { formatVersion: 1, blocks: [ { instanceId: "search", code: STANDARD_CODES.serialSGS, params: {} }, ], }, sweep: { axes: [ { id: "structured", targets: [{ instanceId: "search", paramPath: "options" }], values: [[1, 2], { mode: "fast", limits: [3, 4] }], }, ], }, }); roundTrips(config); });
test("weighted lexicographic tiers preserve their inline weight maps", () => { const config = runConfigSchema.parse({ formatVersion: 1, pipeline: { formatVersion: 1, blocks: [ { instanceId: "search", code: STANDARD_CODES.serialSGS, params: {} }, ], }, objective: { lexicographic: [ "lateness", { weightedSum: { labor: 2, earliness: 0.25 } }, ], }, }); roundTrips(config); });
test("a generated corpus of random subsets/weights/tiers round-trips", () => { // Deterministic PRNG (mulberry32) — no new dev deps, reproducible corpus. let state = 0x9e3779b9; const rand = (): number => { state |= 0; state = (state + 0x6d2b79f5) | 0; let t = Math.imul(state ^ (state >>> 15), 1 | state); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; const defs = standardBlockDefs(); const scorers = defs.filter((d) => d.family === "scorer"); const constraints = defs.filter((d) => d.family === "constraint");
for (let iter = 0; iter < 40; iter++) { const chosen = [...constraints, ...scorers].filter(() => rand() < 0.5); const blocks = chosen.map((def, i) => ({ instanceId: `${def.family}-${String(i)}`, code: def.code, params: def.defaultShadow, // Randomly disable some (never enabled:true — it is the absent default). ...(rand() < 0.25 ? { enabled: false } : {}), ...(rand() < 0.2 ? { provenance: "candidate" as const } : {}), ...(rand() < 0.2 ? { shadow: true } : {}), })); blocks.push({ instanceId: "search", code: STANDARD_CODES.serialSGS, params: {}, });
const scorerIds = blocks .filter((b) => scorers.some((d) => d.code === b.code)) .map((b) => b.instanceId); const weights: Record<string, number | null> = {}; for (const id of scorerIds) { const r = rand(); if (r < 0.33) weights[id] = null; // report-only else if (r < 0.66) weights[id] = Math.round(rand() * 100) / 10; // e.g. 4.2 }
const config: Record<string, unknown> = { formatVersion: 1, pipeline: { formatVersion: 1, blocks }, }; if (Object.keys(weights).length > 0) config["weights"] = weights; if (scorerIds.length > 0 && rand() < 0.4) { config["objective"] = { lexicographic: scorerIds.slice(0, 2) }; } roundTrips(runConfigSchema.parse(config)); } });});
describe("serializeConf — schema coverage", () => { test("the conf mapping handles every runConfigSchema top-level key", () => { // If a new top-level key lands on runConfigSchema (collectors, sweep, …), // this fails loudly until the conf parse/serialize mapping covers it. expect(Object.keys(runConfigSchema.shape).sort()).toEqual( [ "formatVersion", "levelset", "objective", "pipeline", "resolve", "seed", "sweep", "weights", ].sort(), ); });
test("a config exercising every top-level key round-trips", () => { const config = runConfigSchema.parse({ formatVersion: 1, levelset: "0.1.0", seed: 99, resolve: { epoch: "2026-03-01", horizonDays: 60, workUnits: [{ id: 1, location: "bay-1", taskUniqueIds: [10, 11] }], }, pipeline: { formatVersion: 1, systemCode: "CNV", blocks: [ { instanceId: "make", code: STANDARD_CODES.makespan, params: {} }, { instanceId: "sgs", code: STANDARD_CODES.serialSGS, params: {} }, ], }, weights: { make: null }, objective: { lexicographic: ["make"] }, sweep: { maxCombinations: 4, axes: [ { id: "make-enabled", targets: [{ instanceId: "make", paramPath: "$enabled" }], values: [true, false], }, { id: "zip", targets: [ { instanceId: "make", paramPath: "$enabled", valueKey: "enabled", }, ], values: [{ enabled: true }, { enabled: false }], }, ], }, }); roundTrips(config); });});
describe("lintRegistryForConf", () => { test("the standard registry is conf-clean", () => { expect(lintRegistryForConf(standardRegistry())).toEqual([]); });});
describe("conf integration — schedule + provenance stability across a round trip", () => { function crewProject() { const t1 = makeTask({ uniqueId: 1, start: MON_JAN_5, finish: SAT_JAN_10 }); const t2 = makeTask({ uniqueId: 2, start: MON_JAN_5, finish: SAT_JAN_10 }); return makeProject([t1, t2], { resources: [makeResource(100, "Crew")], assignments: [makeAssignment(1, 100), makeAssignment(2, 100)], }); }
const confText = `[levelset]format = 1
[blocks.crew-cap]code = "levelset.MaxConcurrentResource.v1"resourceUniqueId = 100max = 1
[blocks.makespan]code = "levelset.Makespan.v1"
[blocks.search]code = "levelset.SerialSGS.v1"
[objective]lexicographic = ["makespan"]`;
test("conf → run → serialize(filled) → parse → run yields the same schedule, scores, and provenance", async () => { const project = crewProject();
const run1 = runFromConfig( project, unwrap(parseConf(confText, { registry })), { registry }, ); const best1 = await run1.best(); expect(best1).not.toBeNull();
// Serialize the *filled* config (provenance artifact) and run it again. const text2 = serializeConf(run1.config); const run2 = runFromConfig( project, unwrap(parseConf(text2, { registry })), { registry }, ); const best2 = await run2.best(); expect(best2).not.toBeNull();
expect(best2!.makespan).toBe(best1!.makespan); expect(run2.scores(best2!)).toEqual(run1.scores(best1!)); // The filled config is what provenance embeds; it must be identical. expect(run2.config).toEqual(run1.config); expect(run2.materialize(best2!).levelset!.runConfig).toEqual( run1.materialize(best1!).levelset!.runConfig, ); });});