85453da49f
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
156 lines
5.9 KiB
JavaScript
156 lines
5.9 KiB
JavaScript
import { test } from "node:test";
|
|
import { strict as assert } from "node:assert";
|
|
import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { tmpdir } from "node:os";
|
|
import { listCandidates, formatCandidates, CANDIDATE_CAP } from "./candidates.mjs";
|
|
import { findGlobalBySha } from "./cache.mjs";
|
|
|
|
// candidates + findGlobalBySha are offline (no heygen), so we can override HOME
|
|
// to a temp dir and seed a fake global ~/.media manifest deterministically.
|
|
function sandbox() {
|
|
const root = mkdtempSync(join(tmpdir(), "mu-cand-"));
|
|
const project = join(root, "proj");
|
|
const home = join(root, "home");
|
|
process.env.HOME = home;
|
|
return { root, project, home };
|
|
}
|
|
function seedManifest(dir, records) {
|
|
const md = join(dir, ".media");
|
|
mkdirSync(md, { recursive: true });
|
|
writeFileSync(md + "/manifest.jsonl", records.map((r) => JSON.stringify(r)).join("\n") + "\n");
|
|
}
|
|
function proj(id, type, description, prompt) {
|
|
return { id, type, path: `.media/audio/bgm/${id}.wav`, description, provenance: { prompt } };
|
|
}
|
|
function glob(id, type, description, prompt, sha) {
|
|
return {
|
|
id,
|
|
type,
|
|
sha,
|
|
reusable: true,
|
|
cached_path: `/x/${sha}/${id}.wav`,
|
|
description,
|
|
provenance: { prompt, provider: "heygen.audio.sounds" },
|
|
};
|
|
}
|
|
|
|
test("ranks project + global by overlap, tags scope", () => {
|
|
const { root, project, home } = sandbox();
|
|
try {
|
|
seedManifest(project, [proj("bgm_001", "bgm", "calm ambient piano", "calm ambient piano")]);
|
|
seedManifest(home, [
|
|
glob("bgm_009", "bgm", "energetic tech launch", "energetic tech launch", "a".repeat(64)),
|
|
glob("bgm_010", "bgm", "sad corporate piano", "sad corporate piano", "b".repeat(64)),
|
|
]);
|
|
const { candidates } = listCandidates({
|
|
projectDir: project,
|
|
type: "bgm",
|
|
intent: "tech launch",
|
|
});
|
|
assert.equal(candidates[0].scope, "project"); // project listed first
|
|
const g = candidates.filter((c) => c.scope === "global");
|
|
assert.equal(g[0].description, "energetic tech launch"); // higher overlap ranks first
|
|
assert.ok(g[0].score >= g[1].score);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("zero-overlap intent still lists candidates (no hard filter)", () => {
|
|
const { root, project, home } = sandbox();
|
|
try {
|
|
seedManifest(project, []);
|
|
seedManifest(home, [glob("bgm_009", "bgm", "driving synth", "driving synth", "c".repeat(64))]);
|
|
const { candidates, similar } = listCandidates({
|
|
projectDir: project,
|
|
type: "bgm",
|
|
intent: "totally unrelated words xyz",
|
|
});
|
|
assert.equal(candidates.length, 1, "listed despite zero overlap");
|
|
assert.equal(candidates[0].score, 0);
|
|
assert.equal(similar, 0, "similar counts only overlap>0");
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("caps per scope and reports truncation + totals", () => {
|
|
const { root, project, home } = sandbox();
|
|
try {
|
|
const many = Array.from({ length: CANDIDATE_CAP + 3 }, (_, i) =>
|
|
glob(`bgm_${i}`, "bgm", `track ${i}`, `track ${i}`, String(i).padStart(64, "0")),
|
|
);
|
|
seedManifest(project, []);
|
|
seedManifest(home, many);
|
|
const { candidates, truncated, total } = listCandidates({ projectDir: project, type: "bgm" });
|
|
assert.equal(candidates.length, CANDIDATE_CAP);
|
|
assert.equal(truncated, true);
|
|
assert.equal(total.global, CANDIDATE_CAP + 3);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("honors icon<->image adjacency", () => {
|
|
const { root, project, home } = sandbox();
|
|
try {
|
|
seedManifest(project, []);
|
|
seedManifest(home, [glob("image_1", "image", "rocket logo", "rocket logo", "d".repeat(64))]);
|
|
const { candidates } = listCandidates({ projectDir: project, type: "icon", intent: "rocket" });
|
|
assert.equal(candidates.length, 1, "image asset surfaces for icon request");
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("sha only on global, path only on project", () => {
|
|
const { root, project, home } = sandbox();
|
|
try {
|
|
seedManifest(project, [proj("bgm_001", "bgm", "x", "x")]);
|
|
seedManifest(home, [glob("bgm_009", "bgm", "y", "y", "e".repeat(64))]);
|
|
const { candidates } = listCandidates({ projectDir: project, type: "bgm" });
|
|
const p = candidates.find((c) => c.scope === "project");
|
|
const g = candidates.find((c) => c.scope === "global");
|
|
assert.ok(p.path && !p.sha);
|
|
assert.ok(g.sha && !g.path);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("findGlobalBySha resolves unique prefix, flags ambiguity, misses cleanly", () => {
|
|
const { root, project, home } = sandbox();
|
|
try {
|
|
seedManifest(project, []);
|
|
seedManifest(home, [
|
|
glob("bgm_1", "bgm", "a", "a", "abc" + "0".repeat(61)),
|
|
glob("bgm_2", "bgm", "b", "b", "abd" + "0".repeat(61)),
|
|
glob("bgm_3", "bgm", "c", "c", "fff" + "0".repeat(61)),
|
|
]);
|
|
assert.equal(findGlobalBySha("fff").id, "bgm_3", "unique prefix resolves");
|
|
assert.deepEqual(
|
|
{ ambiguous: findGlobalBySha("ab").ambiguous, count: findGlobalBySha("ab").count },
|
|
{ ambiguous: true, count: 2 },
|
|
"ambiguous prefix flagged",
|
|
);
|
|
assert.equal(findGlobalBySha("zzz"), null, "miss returns null");
|
|
assert.equal(findGlobalBySha(""), null, "empty returns null");
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("formatCandidates shows reuse handles by scope; empty message", () => {
|
|
const { candidates } = {
|
|
candidates: [
|
|
{ scope: "project", description: "p", path: ".media/audio/bgm/bgm_001.wav" },
|
|
{ scope: "global", description: "g", sha: "f".repeat(64) },
|
|
],
|
|
};
|
|
const out = formatCandidates(candidates, {});
|
|
assert.match(out, /\.media\/audio\/bgm\/bgm_001\.wav/);
|
|
assert.match(out, /--reuse ffffffffffffffff/);
|
|
assert.match(formatCandidates([], {}), /no reuse candidates/);
|
|
});
|