#!/usr/bin/env node
import { createHash } from "node:crypto";
import { spawnSync } from "node:child_process";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { arch, platform } from "node:os";
import { basename, dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const generatorPath = fileURLToPath(import.meta.url);
const root = join(dirname(generatorPath), "..");
const rendererPath = join(root, "src", "lib", "audio", "editor.ts");
const fixtureDir = join(root, "public", "fixtures", "audio", "v1");
const publicGeneratorSnapshot = join(
fixtureDir,
"generate-audio-flagship-evidence.mjs.txt"
);
const publicManifest = join(fixtureDir, "evidence.json");
const sourceManifest = join(
root,
"src",
"lib",
"flagships",
"audio-evidence.generated.json"
);
const researchDir = join(root, "public", "research");
const publicFindingsCsv = join(researchDir, "audio-v1-findings.csv");
const publicDurationChart = join(researchDir, "audio-v1-duration.svg");
const publicFrequencyChart = join(researchDir, "audio-v1-frequency.svg");
const publicSignalChart = join(researchDir, "audio-v1-signal-checks.svg");
const sampleRate = 44_100;
function commandResult(binary, args) {
return spawnSync(binary, args, {
cwd: root,
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});
}
function resolveBinary(environmentValue, name, fallbacks) {
const candidates = [
environmentValue,
name,
...fallbacks,
].filter(Boolean);
for (const candidate of candidates) {
const result = commandResult(candidate, ["-version"]);
if (result.status === 0) return candidate;
}
throw new Error(
`Unable to find ${name}. Set FILEMORF_EVIDENCE_${name.toUpperCase()} to an executable path.`
);
}
const ffmpeg = resolveBinary(process.env.FILEMORF_EVIDENCE_FFMPEG, "ffmpeg", [
"/opt/homebrew/bin/ffmpeg",
"/usr/local/bin/ffmpeg",
"/usr/bin/ffmpeg",
]);
const ffprobe = resolveBinary(
process.env.FILEMORF_EVIDENCE_FFPROBE,
"ffprobe",
[
"/opt/homebrew/bin/ffprobe",
"/usr/local/bin/ffprobe",
"/usr/bin/ffprobe",
]
);
function run(binary, args) {
const result = commandResult(binary, args);
if (result.status !== 0) {
throw new Error(
`${basename(binary)} failed (${result.status}): ${result.stderr || result.stdout}`
);
}
return result.stdout.trim();
}
function pcmWav(durationSec, sampleFn) {
const frames = Math.round(durationSec * sampleRate);
const channels = 2;
const bytesPerSample = 2;
const dataBytes = frames * channels * bytesPerSample;
const buffer = Buffer.alloc(44 + dataBytes);
buffer.write("RIFF", 0);
buffer.writeUInt32LE(36 + dataBytes, 4);
buffer.write("WAVE", 8);
buffer.write("fmt ", 12);
buffer.writeUInt32LE(16, 16);
buffer.writeUInt16LE(1, 20);
buffer.writeUInt16LE(channels, 22);
buffer.writeUInt32LE(sampleRate, 24);
buffer.writeUInt32LE(sampleRate * channels * bytesPerSample, 28);
buffer.writeUInt16LE(channels * bytesPerSample, 32);
buffer.writeUInt16LE(bytesPerSample * 8, 34);
buffer.write("data", 36);
buffer.writeUInt32LE(dataBytes, 40);
for (let frame = 0; frame < frames; frame += 1) {
const time = frame / sampleRate;
const value = Math.max(-1, Math.min(1, sampleFn(time, frame)));
const integer = Math.round(value * 32_767);
const offset = 44 + frame * channels * bytesPerSample;
buffer.writeInt16LE(integer, offset);
buffer.writeInt16LE(integer, offset + bytesPerSample);
}
return buffer;
}
function envelope(time, duration, attack = 0.015, release = 0.025) {
return Math.min(1, time / attack, (duration - time) / release);
}
function tone(frequency, duration, amplitude = 0.35) {
return pcmWav(
duration,
(time) =>
Math.sin(2 * Math.PI * frequency * time) *
amplitude *
Math.max(0, envelope(time, duration))
);
}
function speedFixture() {
const duration = 2.4;
return pcmWav(duration, (time) => {
const base = Math.sin(2 * Math.PI * 523.25 * time) * 0.24;
const beatPhase = time % 0.6;
const tick =
beatPhase < 0.025
? Math.sin(2 * Math.PI * 1_400 * beatPhase) *
(1 - beatPhase / 0.025) *
0.45
: 0;
return (base + tick) * Math.max(0, envelope(time, duration));
});
}
function slowedFixture() {
const duration = 2;
return pcmWav(duration, (time) => {
const toneValue =
(Math.sin(2 * Math.PI * 330 * time) +
0.3 * Math.sin(2 * Math.PI * 660 * time)) *
0.2;
const pulsePhase = time % 0.5;
const pulse =
pulsePhase < 0.012
? Math.sin(2 * Math.PI * 1_000 * pulsePhase) *
(1 - pulsePhase / 0.012) *
0.6
: 0;
return (toneValue + pulse) * Math.max(0, envelope(time, duration));
});
}
function voiceLikeFixture() {
const duration = 2.2;
return pcmWav(duration, (time) => {
const syllable =
0.25 + 0.75 * Math.max(0, Math.sin(2 * Math.PI * 2.2 * time));
const voice =
Math.sin(2 * Math.PI * 180 * time) +
0.42 * Math.sin(2 * Math.PI * 360 * time) +
0.18 * Math.sin(2 * Math.PI * 540 * time);
return voice * syllable * 0.16 * Math.max(0, envelope(time, duration));
});
}
async function sha256(path) {
return createHash("sha256").update(await readFile(path)).digest("hex");
}
function probe(path) {
const parsed = JSON.parse(
run(ffprobe, [
"-v",
"error",
"-select_streams",
"a:0",
"-show_entries",
"stream=sample_rate,channels,duration:format=duration,size",
"-of",
"json",
path,
])
);
const stream = parsed.streams?.[0] ?? {};
return {
bytes: Number(parsed.format?.size ?? 0),
durationSec: Number(
Number(parsed.format?.duration ?? stream.duration).toFixed(4)
),
sampleRate: Number(stream.sample_rate),
channels: Number(stream.channels),
};
}
async function describe(path) {
return {
href: `/fixtures/audio/v1/${basename(path)}`,
sha256: await sha256(path),
...probe(path),
mime: "audio/wav",
};
}
async function decodePcm16Wav(path) {
const buffer = await readFile(path);
if (buffer.toString("ascii", 0, 4) !== "RIFF") {
throw new Error(`${path} is not a RIFF file`);
}
let offset = 12;
let format;
let data;
while (offset + 8 <= buffer.length) {
const id = buffer.toString("ascii", offset, offset + 4);
const size = buffer.readUInt32LE(offset + 4);
const payload = offset + 8;
if (id === "fmt ") {
format = {
encoding: buffer.readUInt16LE(payload),
channels: buffer.readUInt16LE(payload + 2),
sampleRate: buffer.readUInt32LE(payload + 4),
bitsPerSample: buffer.readUInt16LE(payload + 14),
};
}
if (id === "data") {
data = { payload, size };
break;
}
offset = payload + size + (size % 2);
}
if (
!format ||
!data ||
format.encoding !== 1 ||
format.bitsPerSample !== 16
) {
throw new Error(`${path} is not supported 16-bit PCM WAV`);
}
const bytesPerFrame = format.channels * 2;
const samples = [];
for (
let frameOffset = data.payload;
frameOffset < data.payload + data.size;
frameOffset += bytesPerFrame
) {
let mixed = 0;
for (let channel = 0; channel < format.channels; channel += 1) {
mixed += buffer.readInt16LE(frameOffset + channel * 2) / 32_768;
}
samples.push(mixed / format.channels);
}
return { ...format, samples };
}
function sliceSamples(decoded, startSec, endSec) {
return decoded.samples.slice(
Math.max(0, Math.floor(startSec * decoded.sampleRate)),
Math.min(decoded.samples.length, Math.ceil(endSec * decoded.sampleRate))
);
}
function rms(decoded, startSec, endSec) {
const samples = sliceSamples(decoded, startSec, endSec);
if (samples.length === 0) throw new Error("Cannot measure an empty window");
return Math.sqrt(
samples.reduce((total, sample) => total + sample * sample, 0) /
samples.length
);
}
function dominantFrequency(
decoded,
startSec,
endSec,
minimumHz,
maximumHz
) {
const samples = sliceSamples(decoded, startSec, endSec);
let bestFrequency = minimumHz;
let bestPower = -Infinity;
for (
let frequency = minimumHz;
frequency <= maximumHz;
frequency += 0.1
) {
let real = 0;
let imaginary = 0;
for (let index = 0; index < samples.length; index += 1) {
const phase =
(2 * Math.PI * frequency * index) / decoded.sampleRate;
real += samples[index] * Math.cos(phase);
imaginary -= samples[index] * Math.sin(phase);
}
const power = real * real + imaginary * imaginary;
if (power > bestPower) {
bestPower = power;
bestFrequency = frequency;
}
}
return bestFrequency;
}
function alignedDifferenceRms(source, output, sourceStartSec) {
const start = Math.round(sourceStartSec * source.sampleRate);
if (
source.sampleRate !== output.sampleRate ||
start + output.samples.length > source.samples.length
) {
throw new Error("Cannot compare unaligned PCM windows");
}
let total = 0;
for (let index = 0; index < output.samples.length; index += 1) {
const difference = output.samples[index] - source.samples[start + index];
total += difference * difference;
}
return Math.sqrt(total / output.samples.length);
}
function rounded(value, digits = 6) {
return Number(value.toFixed(digits));
}
function relativePath(value) {
return value.startsWith(root) ? value.slice(root.length + 1) : value;
}
function assertion(id, comparator, expected, actual, unit, tolerance) {
return {
id,
comparator,
expected,
actual: rounded(actual),
...(tolerance === undefined ? {} : { tolerance }),
unit,
};
}
function assertionPasses(value) {
if (
!Number.isFinite(value.actual) ||
!Number.isFinite(value.expected)
) {
return false;
}
if (value.comparator === "within") {
return (
Number.isFinite(value.tolerance) &&
Math.abs(value.actual - value.expected) <= value.tolerance
);
}
if (value.comparator === "gte") return value.actual >= value.expected;
if (value.comparator === "lte") return value.actual <= value.expected;
return false;
}
function csvCell(value) {
if (value === undefined || value === null) return "";
const text = String(value);
return /[",\n\r]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text;
}
function findingCategory(value) {
if (value.unit === "s") return "duration";
if (value.unit === "Hz") return "frequency";
return "signal";
}
function buildFindingsCsv(records, baseCommit, generatedAt) {
const header = [
"corpus_version",
"tool",
"scope",
"category",
"metric",
"comparator",
"expected",
"actual",
"tolerance",
"unit",
"source_manifest",
"source_commit",
"generated_at",
];
const rows = [];
const sourceManifestHref = "/fixtures/audio/v1/evidence.json";
for (const [tool, record] of Object.entries(records)) {
rows.push([
"audio-v1",
tool,
record.scope,
"duration",
"input-duration",
"observed",
"",
rounded(
record.inputs.reduce((total, file) => total + file.durationSec, 0),
4
),
"",
"s",
sourceManifestHref,
baseCommit,
generatedAt,
]);
const durationAssertions = record.assertions.filter(
(value) => value.unit === "s"
);
if (durationAssertions.length > 1) {
throw new Error(`${tool} has more than one duration assertion`);
}
const durationAssertion = durationAssertions[0];
rows.push([
"audio-v1",
tool,
record.scope,
"duration",
durationAssertion?.id ?? "output-duration-observed",
durationAssertion?.comparator ?? "observed",
durationAssertion?.expected ?? "",
record.output.durationSec,
durationAssertion?.tolerance ?? "",
"s",
sourceManifestHref,
baseCommit,
generatedAt,
]);
for (const value of record.assertions.filter((entry) => entry.unit !== "s")) {
rows.push([
"audio-v1",
tool,
record.scope,
findingCategory(value),
value.id,
value.comparator,
value.expected,
value.actual,
value.tolerance ?? "",
value.unit,
sourceManifestHref,
baseCommit,
generatedAt,
]);
}
}
return `${[header, ...rows]
.map((row) => row.map(csvCell).join(","))
.join("\n")}\n`;
}
function svgEscape(value) {
return String(value)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
function chartShell({ title, description, body, generatedAt }) {
return `
`;
}
function buildDurationChart(records, generatedAt) {
const rows = [
{
label: "Audio Joiner",
input: records["audio-joiner"].inputs.reduce(
(total, file) => total + file.durationSec,
0
),
output: records["audio-joiner"].output.durationSec,
},
{
label: "Speed Changer",
input: records["audio-speed-changer"].inputs[0].durationSec,
output: records["audio-speed-changer"].output.durationSec,
},
{
label: "Slowed and Reverb",
input: records["slowed-and-reverb"].inputs[0].durationSec,
output: records["slowed-and-reverb"].output.durationSec,
},
{
label: "Voice Recorder edit",
input: records["voice-recorder"].inputs[0].durationSec,
output: records["voice-recorder"].output.durationSec,
},
];
const max = Math.max(...rows.flatMap((row) => [row.input, row.output]));
const plotX = 340;
const plotWidth = 720;
const rowHeight = 112;
const body = rows
.map((row, index) => {
const y = 184 + index * rowHeight;
const inputWidth = (row.input / max) * plotWidth;
const outputWidth = (row.output / max) * plotWidth;
return `
${svgEscape(row.label)}
${row.input.toFixed(4)} s input
${row.output.toFixed(4)} s output
`;
})
.join("\n");
return chartShell({
title: "Audio v1 duration outcomes",
description:
"Measured input and output durations for deterministic synthetic reference fixtures.",
body,
generatedAt,
});
}
function assertionById(record, id) {
const matches = record.assertions.filter((entry) => entry.id === id);
if (matches.length !== 1) {
throw new Error(
`Expected exactly one evidence assertion named ${id}; found ${matches.length}`
);
}
return matches[0];
}
function buildFrequencyChart(records, generatedAt) {
const rows = [
{
label: "Join segment 1",
value: assertionById(
records["audio-joiner"],
"first-segment-frequency"
),
},
{
label: "Join segment 2",
value: assertionById(
records["audio-joiner"],
"second-segment-frequency"
),
},
{
label: "Pitch preserved at 0.75x",
value: assertionById(
records["audio-speed-changer"],
"preserved-frequency"
),
},
{
label: "Tape-style pitch at 0.8x",
value: assertionById(records["slowed-and-reverb"], "tape-frequency"),
},
];
const max = 700;
const plotX = 340;
const plotWidth = 720;
const rowHeight = 112;
const body = rows
.map(({ label, value }, index) => {
const y = 184 + index * rowHeight;
const expectedWidth = (value.expected / max) * plotWidth;
const actualWidth = (value.actual / max) * plotWidth;
return `
${svgEscape(label)}
${value.expected} Hz target
${value.actual} Hz measured
`;
})
.join("\n");
return chartShell({
title: "Audio v1 frequency checks",
description:
"Measured dominant frequencies compared with the declared reference targets.",
body,
generatedAt,
});
}
function buildSignalChart(records, generatedAt) {
const rows = [
{
label: "Join boundary RMS",
value: assertionById(records["audio-joiner"], "join-boundary-rms"),
rule: "at or below",
},
{
label: "Echo tail RMS",
value: assertionById(records["slowed-and-reverb"], "echo-tail-rms"),
rule: "at or above",
},
{
label: "Trim alignment RMS",
value: assertionById(
records["voice-recorder"],
"source-alignment-rms"
),
rule: "at or below",
},
];
const body = rows
.map(({ label, value, rule }, index) => {
const y = 182 + index * 142;
const ratio =
value.expected === 0
? 0
: Math.min(3.5, value.actual / value.expected);
const width = ratio * 190;
const thresholdX = 340 + 190;
return `
${svgEscape(label)}
${value.actual} FS measured · ${svgEscape(rule)} ${value.expected} FS
PASS
`;
})
.join("\n");
return chartShell({
title: "Audio v1 signal acceptance checks",
description:
"Full-scale RMS measurements shown against their declared acceptance thresholds.",
body,
generatedAt,
});
}
async function describePublication(id, kind, path, mime) {
const content = await readFile(path);
return {
id,
kind,
href: `/research/${basename(path)}`,
mime,
bytes: content.byteLength,
sha256: createHash("sha256").update(content).digest("hex"),
};
}
async function main() {
const baseCommit = run("git", ["rev-parse", "HEAD"]);
const generatedPaths = [
"public/fixtures/audio/v1/evidence.json",
"public/fixtures/audio/v1/generate-audio-flagship-evidence.mjs.txt",
"public/fixtures/audio/v1/join-a-440hz.wav",
"public/fixtures/audio/v1/join-b-660hz.wav",
"public/fixtures/audio/v1/joined-reference.wav",
"public/fixtures/audio/v1/slowed-080-hall-reference.wav",
"public/fixtures/audio/v1/slowed-impulse-330hz.wav",
"public/fixtures/audio/v1/speed-075-keep-pitch-reference.wav",
"public/fixtures/audio/v1/speed-metronome-523hz.wav",
"public/fixtures/audio/v1/synthetic-voice-like-source.wav",
"public/fixtures/audio/v1/voice-edit-trim-reference.wav",
"public/research/audio-v1-findings.csv",
"public/research/audio-v1-duration.svg",
"public/research/audio-v1-frequency.svg",
"public/research/audio-v1-signal-checks.svg",
"src/lib/flagships/audio-evidence.generated.json",
];
const workingTree =
run("git", [
"status",
"--porcelain=v1",
"--untracked-files=all",
"--",
".",
...generatedPaths.map((path) => `:(exclude)${path}`),
]).length > 0;
if (workingTree) {
throw new Error(
"Evidence generation requires a clean source commit. Commit source changes first."
);
}
await mkdir(fixtureDir, { recursive: true });
await mkdir(dirname(sourceManifest), { recursive: true });
await mkdir(researchDir, { recursive: true });
await writeFile(publicGeneratorSnapshot, await readFile(generatorPath));
const inputPaths = {
joinA: join(fixtureDir, "join-a-440hz.wav"),
joinB: join(fixtureDir, "join-b-660hz.wav"),
speed: join(fixtureDir, "speed-metronome-523hz.wav"),
slowed: join(fixtureDir, "slowed-impulse-330hz.wav"),
recorder: join(fixtureDir, "synthetic-voice-like-source.wav"),
};
await writeFile(inputPaths.joinA, tone(440, 1, 0.34));
await writeFile(inputPaths.joinB, tone(660, 1.25, 0.3));
await writeFile(inputPaths.speed, speedFixture());
await writeFile(inputPaths.slowed, slowedFixture());
await writeFile(inputPaths.recorder, voiceLikeFixture());
const outputPaths = {
joiner: join(fixtureDir, "joined-reference.wav"),
speed: join(fixtureDir, "speed-075-keep-pitch-reference.wav"),
slowed: join(fixtureDir, "slowed-080-hall-reference.wav"),
recorder: join(fixtureDir, "voice-edit-trim-reference.wav"),
};
const common = ["-y", "-hide_banner", "-loglevel", "error"];
const commands = {
joiner: [
...common,
"-i",
inputPaths.joinA,
"-i",
inputPaths.joinB,
"-filter_complex",
"[0:a]atrim=start=0:end=1.000,asetpts=PTS-STARTPTS,aresample=44100,aformat=sample_fmts=fltp:channel_layouts=stereo,afade=t=out:st=0.9940:d=0.006[c0];[1:a]atrim=start=0:end=1.250,asetpts=PTS-STARTPTS,aresample=44100,aformat=sample_fmts=fltp:channel_layouts=stereo,afade=t=in:st=0:d=0.006[c1];[c0][c1]concat=n=2:v=0:a=1[out]",
"-map",
"[out]",
"-vn",
"-c:a",
"pcm_s16le",
"-map_metadata",
"-1",
"-bitexact",
outputPaths.joiner,
],
speed: [
...common,
"-i",
inputPaths.speed,
"-filter:a",
"atempo=0.7500",
"-vn",
"-c:a",
"pcm_s16le",
"-map_metadata",
"-1",
"-bitexact",
outputPaths.speed,
],
slowed: [
...common,
"-i",
inputPaths.slowed,
"-filter:a",
"aecho=0.8:0.9:300|450:0.4|0.25,aresample=44100,asetrate=35280,aresample=44100",
"-vn",
"-c:a",
"pcm_s16le",
"-map_metadata",
"-1",
"-bitexact",
outputPaths.slowed,
],
recorder: [
...common,
"-i",
inputPaths.recorder,
"-filter:a",
"atrim=start=0.200:end=2.000,asetpts=PTS-STARTPTS,aresample=44100,aformat=sample_fmts=fltp:channel_layouts=stereo",
"-vn",
"-c:a",
"pcm_s16le",
"-map_metadata",
"-1",
"-bitexact",
outputPaths.recorder,
],
};
for (const args of Object.values(commands)) run(ffmpeg, args);
const joinerPcm = await decodePcm16Wav(outputPaths.joiner);
const speedPcm = await decodePcm16Wav(outputPaths.speed);
const slowedPcm = await decodePcm16Wav(outputPaths.slowed);
const recorderInputPcm = await decodePcm16Wav(inputPaths.recorder);
const recorderOutputPcm = await decodePcm16Wav(outputPaths.recorder);
const records = {
"audio-joiner": {
scope: "ffmpeg-cli-reference",
inputs: [
await describe(inputPaths.joinA),
await describe(inputPaths.joinB),
],
output: await describe(outputPaths.joiner),
operation:
"Two synthetic tones, ordered 440 Hz then 660 Hz, normalized to 44.1 kHz stereo, with 6 ms internal microfades.",
demonstrates: [
"ordered concatenation",
"6 ms boundary attenuation",
"44.1 kHz stereo PCM output",
],
doesNotDemonstrate: [
"browser performance",
"cross-device equivalence",
],
assertions: [
assertion("output-duration", "within", 2.25, probe(outputPaths.joiner).durationSec, "s", 0.02),
assertion("first-segment-frequency", "within", 440, dominantFrequency(joinerPcm, 0.2, 0.8, 430, 450), "Hz", 1),
assertion("second-segment-frequency", "within", 660, dominantFrequency(joinerPcm, 1.3, 2, 650, 670), "Hz", 1),
assertion("join-boundary-rms", "lte", 0.01, rms(joinerPcm, 0.998, 1.002), "FS"),
],
command: commands.joiner.map(relativePath),
},
"audio-speed-changer": {
scope: "ffmpeg-cli-reference",
inputs: [await describe(inputPaths.speed)],
output: await describe(outputPaths.speed),
operation: "0.75× tempo with pitch-preserving FFmpeg atempo.",
demonstrates: [
"0.75× duration change",
"523.25 Hz reference-tone preservation",
],
doesNotDemonstrate: [
"browser performance",
"artifact-free output for arbitrary sources",
],
assertions: [
assertion("output-duration", "within", 3.2, probe(outputPaths.speed).durationSec, "s", 0.04),
assertion("preserved-frequency", "within", 523.25, dominantFrequency(speedPcm, 1, 1.5, 510, 535), "Hz", 1),
],
command: commands.speed.map(relativePath),
},
"slowed-and-reverb": {
scope: "ffmpeg-cli-reference",
inputs: [await describe(inputPaths.slowed)],
output: await describe(outputPaths.slowed),
operation:
"FFmpeg hall aecho followed by the 0.8× tape-style resampling chain.",
demonstrates: [
"0.8× tape-style pitch shift",
"measurable echo tail after the dry slowed source",
],
doesNotDemonstrate: [
"measured room convolution",
"browser performance",
],
assertions: [
assertion("tape-frequency", "within", 264, dominantFrequency(slowedPcm, 0.05, 0.45, 250, 278), "Hz", 1),
assertion("echo-tail-rms", "gte", 0.01, rms(slowedPcm, 2.7, 3), "FS"),
],
command: commands.slowed.map(relativePath),
},
"voice-recorder": {
scope: "ffmpeg-cli-edit-reference",
inputs: [await describe(inputPaths.recorder)],
output: await describe(outputPaths.recorder),
operation:
"Synthetic voice-like signal with 0.2 s trimmed from each edge and PCM WAV output.",
demonstrates: [
"deterministic timeline trim",
"sample-aligned PCM WAV output",
],
doesNotDemonstrate: [
"microphone permission",
"MediaRecorder capture",
"browser performance",
],
assertions: [
assertion("trimmed-duration", "within", 1.8, probe(outputPaths.recorder).durationSec, "s", 0.02),
assertion("source-alignment-rms", "lte", 0.000001, alignedDifferenceRms(recorderInputPcm, recorderOutputPcm, 0.2), "FS"),
],
command: commands.recorder.map(relativePath),
},
};
const ffmpegVersion = run(ffmpeg, ["-version"]).split("\n")[0];
const ffprobeVersion = run(ffprobe, ["-version"]).split("\n")[0];
const failedAssertions = Object.entries(records).flatMap(
([tool, record]) =>
record.assertions
.filter((value) => !assertionPasses(value))
.map((value) => `${tool}:${value.id}`)
);
if (failedAssertions.length > 0) {
throw new Error(
`Evidence assertions failed: ${failedAssertions.join(", ")}`
);
}
const requestedTimestamp =
process.env.FILEMORF_EVIDENCE_GENERATED_AT || new Date().toISOString();
if (Number.isNaN(Date.parse(requestedTimestamp))) {
throw new Error("FILEMORF_EVIDENCE_GENERATED_AT must be an ISO timestamp");
}
await writeFile(
publicFindingsCsv,
buildFindingsCsv(records, baseCommit, new Date(requestedTimestamp).toISOString())
);
await writeFile(
publicDurationChart,
buildDurationChart(records, new Date(requestedTimestamp).toISOString())
);
await writeFile(
publicFrequencyChart,
buildFrequencyChart(records, new Date(requestedTimestamp).toISOString())
);
await writeFile(
publicSignalChart,
buildSignalChart(records, new Date(requestedTimestamp).toISOString())
);
const evidence = {
schema: "filemorf-audio-flagship-evidence/3",
generatedAt: new Date(requestedTimestamp).toISOString(),
corpusVersion: "audio-v1",
rights: {
license: "CC0-1.0",
provenance:
"Deterministic PCM signals generated from mathematical functions. No customer or third-party audio.",
},
source: {
repository: "https://github.com/jddelia/file-convert",
baseCommit,
workingTree: false,
generatorPath: "scripts/generate-audio-flagship-evidence.mjs",
publicGeneratorHref:
"/fixtures/audio/v1/generate-audio-flagship-evidence.mjs.txt",
generatorSha256: await sha256(generatorPath),
rendererPath: "src/lib/audio/editor.ts",
rendererSha256: await sha256(rendererPath),
},
environment: {
runner: `${platform()} ${arch()}`,
node: process.version,
referenceRuntime: "FFmpeg CLI",
engine: ffmpegVersion,
probeEngine: ffprobeVersion,
browserRuntime: "@ffmpeg/ffmpeg 0.12.15 with @ffmpeg/core 0.12.10",
browserEvidenceStatus: "separate-release-gate",
},
review: {
automatedContract: "passed-at-generation",
technical: "pending-independent-human-review",
nativeLanguage: "pending-human-review",
},
publications: [
await describePublication(
"audio-v1-findings",
"aggregate",
publicFindingsCsv,
"text/csv"
),
await describePublication(
"audio-v1-duration",
"chart",
publicDurationChart,
"image/svg+xml"
),
await describePublication(
"audio-v1-frequency",
"chart",
publicFrequencyChart,
"image/svg+xml"
),
await describePublication(
"audio-v1-signal-checks",
"chart",
publicSignalChart,
"image/svg+xml"
),
],
records,
};
const text = `${JSON.stringify(evidence, null, 2)}\n`;
await writeFile(publicManifest, text);
await writeFile(sourceManifest, text);
process.stdout.write(
`Generated ${Object.keys(records).length} evidence records in ${fixtureDir}\n`
);
}
await main();