#!/usr/bin/env python3 """Build and verify the frozen eight-source objective-only evaluation.""" from __future__ import annotations import argparse import hashlib import json from pathlib import Path from typing import Sequence from music3lab.eval import ( canonical_json_bytes, evaluate_objective_only, load_objective_config, make_synthetic_candidate, prepare_corpus, publication_order, publish_evaluation, verify_evaluation_bundle, ) def _parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( description=( "Freeze eight opaque audio sources, run deterministic objective " "metrics/canaries, and publish canonical JSON plus Markdown." ) ) parser.add_argument("--config", required=True) parser.add_argument( "--source", action="append", required=True, help="Input audio path; pass exactly eight times.", ) parser.add_argument("--ffmpeg", default="/usr/bin/ffmpeg") parser.add_argument("--corpus-root", required=True) parser.add_argument("--candidate-root", required=True) parser.add_argument("--bundle-root", required=True) parser.add_argument("--staging-root", required=True) parser.add_argument( "--corruption", default="identity", choices=( "identity", "clipping", "noise", "silence", "phase_inversion", "lowpass", "duplicate", "shuffle", "nan", "short", "missing", ), ) return parser def run(arguments: argparse.Namespace) -> dict[str, object]: loaded = load_objective_config(arguments.config) optional = tuple( sorted( loaded.config.metric_policy.optional_evaluators.model_dump( mode="json" ) ) ) with prepare_corpus( sources=arguments.source, output_root=arguments.corpus_root, ffmpeg_path=arguments.ffmpeg, config_path=arguments.config, ) as authority: candidate = make_synthetic_candidate( authority, output_root=arguments.candidate_root, corruption=arguments.corruption, ) result = evaluate_objective_only( authority=authority, candidate_root=candidate, protected_baseline=None, optional_evaluators=optional, ) published = publish_evaluation( result=result, output_root=arguments.bundle_root, staging_root=arguments.staging_root, ) verified = verify_evaluation_bundle(published, authority=authority) report = Path(published, "report.md").read_bytes() return { "bundle_root": str(published), "candidate_semantic_digest": verified.candidate_semantic_digest, "corpus_aggregate_sha256": verified.corpus_aggregate_sha256, "optional_evaluators": verified.optional, "promotion": verified.promotion, "publication_order": publication_order(published), "report_sha256": hashlib.sha256(report).hexdigest(), "result_semantic_digest": verified.semantic_digest, "status": verified.status, } def main(argv: Sequence[str] | None = None) -> int: arguments = _parser().parse_args(argv) print(canonical_json_bytes(run(arguments)).decode("utf-8"), end="") return 0 if __name__ == "__main__": raise SystemExit(main())