import { test } from "node:test"; import assert from "node:assert/strict"; import { laneRootFromScope, migrateSweepsToLanes, } from "../lib/laneMigration"; import { sanitizeAutoQueue } from "./autoQueuePolicy"; // The migration is asserted THROUGH THE SANITIZER, because that is how it is // used: it produces raw nodes and `sanitizeAutoQueue` normalizes them. Testing // the raw output alone would pass on a shape the sanitizer then coerced into // something else. // // IT LIVES IN jobs/ THOUGH THE MODULE LIVES IN lib/, and that is the layering // guard rather than an accident: architecture.test.ts forbids lib/ importing // jobs/, so a test beside the module could not reach the sanitizer it has to // assert through. jobs/ importing lib/ is the legal direction. const migrate = (file: unknown) => sanitizeAutoQueue(migrateSweepsToLanes(file)); // The two lanes as the live settings.json carries them, minus the sweep fields // under test. const LIVE_LANES = { transcription: { enabled: true, maxWorkers: null, order: "listed", root: { id: "t-root", mode: "strict", children: [{ id: "t-all", match: { type: "all" } }], }, }, download: { enabled: true, maxWorkers: null, order: "listed", root: { id: "d-root", mode: "strict", children: [{ id: "d-all", match: { type: "all" } }], }, }, }; test("the live shape: both sweeps disarmed, no channel scope", () => { const out = migrate({ autoQueue: LIVE_LANES, digest: { sweepEnabled: false, sweepChannels: [], recencyOrder: "newest", recencyReach: "corpus", }, backfill: { enabled: true, sweepEnabled: false, sweepKinds: [], sweepChannels: [], order: "newest", reach: "corpus", }, }); // THE HEADLINE ASSERTION OF THE WHOLE SLICE. A migration that enabled a lane // the flag did not would arm ~66,540 audio re-downloads on this corpus. assert.equal(out.digest.enabled, false); assert.equal(out.backfill.enabled, false); // The digest lane keeps `cheapest` — the composition — rather than taking // `recencyOrder`, which is only its date half. assert.equal(out.digest.order, "cheapest"); // The backfill lane's order had no second term, so it is carried verbatim. assert.equal(out.backfill.order, "newest"); // An empty channel list is one catch-all leaf, which is what an empty // `sweepChannels` meant to `startDigestSweep`. for (const lane of ["digest", "backfill"] as const) { assert.equal(out[lane].root.mode, "strict"); assert.deepEqual( out[lane].root.children.map((c) => ("match" in c ? c.match : null)), [{ type: "all" }], ); } // The two runner lanes are untouched by any of it. assert.equal(out.transcription.enabled, true); assert.equal(out.transcription.root.children.length, 1); assert.equal(out.download.root.id, "d-root"); }); test("an armed digest sweep with three channels becomes three channel leaves", () => { const out = migrate({ autoQueue: LIVE_LANES, digest: { sweepEnabled: true, sweepChannels: ["teamrcn", "ObviousRises-rumble", "HasanAbiVODs3"], }, }); assert.equal(out.digest.enabled, true); assert.deepEqual( out.digest.root.children.map((c) => ("match" in c ? c.match : null)), [ { type: "channel", value: "teamrcn" }, { type: "channel", value: "ObviousRises-rumble" }, { type: "channel", value: "HasanAbiVODs3" }, ], ); // Ids are derived from the scope, not generated, so re-arming the same scope // keeps the fairness memory and pick log that leaf already had. assert.deepEqual( out.digest.root.children.map((c) => c.id), ["digest-teamrcn", "digest-ObviousRises-rumble", "digest-HasanAbiVODs3"], ); // Scope ORDER is priority: a strict root walks its children in order, and the // sweep visited its scope in the order it was given. assert.equal(out.digest.root.mode, "strict"); }); test("an armed backfill sweep with two kinds and one channel is a leaf per pair", () => { const out = migrate({ autoQueue: LIVE_LANES, backfill: { sweepEnabled: true, sweepKinds: ["diarization", "attribution-diarized"], sweepChannels: ["teamrcn"], order: "oldest", }, }); assert.equal(out.backfill.enabled, true); assert.equal(out.backfill.order, "oldest"); assert.deepEqual( out.backfill.root.children.map((c) => ("match" in c ? c.match : null)), [ { type: "channel", value: "teamrcn", operation: "diarization" }, { type: "channel", value: "teamrcn", operation: "attribution-diarized" }, ], ); assert.deepEqual( out.backfill.root.children.map((c) => c.id), ["backfill-teamrcn-diarization", "backfill-teamrcn-attribution-diarized"], ); }); test("an operation scope with no channel scope is a catch-all leaf per operation", () => { const out = migrate({ backfill: { sweepEnabled: true, sweepKinds: ["diarization"] }, }); assert.deepEqual( out.backfill.root.children.map((c) => ("match" in c ? c.match : null)), [{ type: "all", operation: "diarization" }], ); }); test("a file that already carries the blocks is untouched", () => { const already = { autoQueue: { ...LIVE_LANES, digest: { enabled: true, maxWorkers: 2, order: "newest", root: { id: "kept", mode: "round-robin", children: [{ id: "kept-leaf", match: { type: "channel", value: "keep" } }], }, }, backfill: { enabled: false, maxWorkers: null, order: "listed", root: { id: "kept-b", mode: "strict", children: [] }, }, }, // Sweep fields still on disk — tolerated, and deliberately NOT allowed to // overwrite a lane block that exists. A file mid-migration has both. digest: { sweepEnabled: false, sweepChannels: ["ignored"] }, backfill: { sweepEnabled: true, sweepChannels: ["ignored"], order: "newest" }, }; const out = migrate(already); assert.equal(out.digest.enabled, true); assert.equal(out.digest.maxWorkers, 2); assert.equal(out.digest.order, "newest"); assert.equal(out.digest.root.mode, "round-robin"); assert.deepEqual( out.digest.root.children.map((c) => ("match" in c ? c.match : null)), [{ type: "channel", value: "keep" }], ); // The armed sweep flag does NOT reach a lane that already has a block. assert.equal(out.backfill.enabled, false); assert.equal(out.backfill.order, "listed"); assert.deepEqual(out.backfill.root.children, []); // Idempotent: running it over its own output changes nothing. assert.deepEqual(migrate({ ...already, autoQueue: out }), out); }); test("a settings file with no digest or backfill block at all migrates to the lane defaults", () => { const out = migrate({}); assert.equal(out.digest.enabled, false); assert.equal(out.digest.order, "cheapest"); assert.equal(out.backfill.enabled, false); assert.equal(out.backfill.order, "listed"); for (const lane of ["digest", "backfill"] as const) { assert.deepEqual( out[lane].root.children.map((c) => ("match" in c ? c.match : null)), [{ type: "all" }], ); } }); // THE CHECK THE SLICE PLAN ASKS FOR, as a unit test rather than as an e2e // assertion: arming a lane from the console with channels X must produce the // tree the migration would have produced from `sweepChannels: X`. It holds by // construction — both sides call `laneRootFromScope` — and this is what says so, // so that a second leaf builder added later fails here rather than in // production. test("a scope naming EVERY operation collapses to a leaf naming none", () => { // The rule that makes a scope track the registry: a leaf naming no operation // draws the lane's whole union, so "all three ticked" must not freeze today's // three into the tree and silently exclude the fourth when it is enabled. const all = ["diarization", "attribution-diarized", "attribution-text"]; assert.deepEqual( laneRootFromScope("backfill", { operations: all, available: all, }).children.map((c) => ("match" in c ? c.match : null)), [{ type: "all" }], ); // A STRICT subset still reaches the leaves. assert.deepEqual( laneRootFromScope("backfill", { operations: ["diarization"], available: all, }).children.map((c) => ("match" in c ? c.match : null)), [{ type: "all", operation: "diarization" }], ); // And the migration collapses on the same rule, through the same builder — // which is the point of it being one function rather than two. const out = migrateSweepsToLanes( { backfill: { sweepEnabled: true, sweepKinds: all } }, { backfill: all }, ).backfill as { root: { children: { match?: unknown }[] } }; assert.deepEqual( out.root.children.map((c) => c.match), [{ type: "all" }], ); }); test("without an `available` list the migration carries the scope verbatim", () => { // getSettings cannot ask the registry, so it passes none — and that is a // no-op on every settings file that exists, because the live `sweepKinds` is // empty and an empty list already means the union. const out = migrateSweepsToLanes({ backfill: { sweepEnabled: true, sweepKinds: ["diarization"] }, }).backfill as { root: { children: { match?: unknown }[] } }; assert.deepEqual( out.root.children.map((c) => c.match), [{ type: "all", operation: "diarization" }], ); }); test("arming a lane with a scope equals migrating the same scope", () => { const channels = ["teamrcn", "ObviousRises-rumble"]; const armed = laneRootFromScope("digest", { channels }); const migrated = migrateSweepsToLanes({ digest: { sweepEnabled: true, sweepChannels: channels }, }).digest as { root: unknown }; assert.deepEqual(armed, migrated.root); const armedBackfill = laneRootFromScope("backfill", { channels, operations: ["diarization"], }); const migratedBackfill = migrateSweepsToLanes({ backfill: { sweepEnabled: true, sweepChannels: channels, sweepKinds: ["diarization"], }, }).backfill as { root: unknown }; assert.deepEqual(armedBackfill, migratedBackfill.root); }); test("blank and duplicate scope entries are dropped rather than becoming leaves", () => { const root = laneRootFromScope("digest", { channels: ["a", " ", "a", " b "], }); assert.deepEqual( root.children.map((c) => ("match" in c ? c.match : null)), [ { type: "channel", value: "a" }, { type: "channel", value: "b" }, ], ); });