mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-18 15:50:25 +02:00
* feat: bundle standalone taste distillation and application workflows * docs: fix imported taste skill markdown lint * docs: align Turkish agent catalog with taste skills * refactor: make ECC the canonical reusable video engine * fix: preserve video duration when applying image overlays * fix: preserve background colors in image compositing * fix: report best-effort duration targets and shortfalls * feat: ship verified Fusion presets with compatibility provenance * feat(tasteforge): preserve native edits in application bundles * feat(tasteforge): compile local preservation without hosted input * fix: update js-yaml to patched 4.3.2 * test: report bounded Stop wrapper failure diagnostics * fix(tasteforge): fail closed on unsafe output names, missing overlays and cadence - cli: default report and spec paths are derived from pack name and profile genre; require the manifest's name pattern before using either as a filename part so a traversal string cannot write outside cwd/out. - apply_local: a pack without cadence.json, or with no measured shots and no explicit mean_shot, raises instead of silently planning 1.0s shots and reporting a measured cadence. - legacy apply: a missing overlay aborts before any paid upload; forge() would have rejected it after every take was generated. - requirements-live: pin fal-client>=0.13.0, the first release whose subscribe() accepts client_timeout. Addresses the five P1 findings from the independent review of #3033. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015fxHRsydPqEcYngGbqkgt1 --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
80 lines
3.0 KiB
Python
80 lines
3.0 KiB
Python
"""Verification must distinguish an absent target from a measured zero."""
|
|
|
|
import importlib.util
|
|
import json
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
from unittest.mock import patch
|
|
|
|
if any(
|
|
importlib.util.find_spec(name) is None for name in ("numpy", "cv2", "scenedetect")
|
|
):
|
|
raise unittest.SkipTest(
|
|
"Install taste-application/scripts/requirements.txt for the creative verification tests"
|
|
)
|
|
|
|
import numpy as np
|
|
|
|
SCRIPTS = Path(__file__).resolve().parents[1] / "skills/taste-application/scripts"
|
|
sys.path.insert(0, str(SCRIPTS))
|
|
spec = importlib.util.spec_from_file_location("taste_verify", SCRIPTS / "verify.py")
|
|
verify = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(verify)
|
|
|
|
|
|
class BackgroundTargetTests(unittest.TestCase):
|
|
def check_background(self, grade, luminance):
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
path = Path(directory) / "grade.json"
|
|
path.write_text(json.dumps(grade))
|
|
stats = SimpleNamespace(
|
|
contrast=0,
|
|
black_point=0,
|
|
white_point=100,
|
|
zones=[],
|
|
bg_share=grade.get("bg_share", 0),
|
|
)
|
|
pack = SimpleNamespace(grade_path=path, cadence_path="cadence.json")
|
|
lab = np.array([[luminance, 0, 0]] * 100, dtype=np.float32)
|
|
with (
|
|
patch.object(verify.pack_mod, "load", return_value=pack),
|
|
patch.object(verify.grade_mod, "load_stats", return_value=stats),
|
|
patch.object(verify.cad_mod, "load"),
|
|
patch.object(verify, "_lab", return_value=lab),
|
|
):
|
|
result = verify.verify("output.mp4", "look", check_cadence=False)
|
|
return next(c for c in result["checks"] if c["check"] == "background")
|
|
|
|
def test_measured_zero_is_checked_and_passes_light_output(self):
|
|
result = self.check_background({"bg_share": 0.0}, 50)
|
|
self.assertIs(result["pass"], True)
|
|
self.assertEqual(result["want"], "0.0% +/- 20")
|
|
|
|
def test_measured_zero_fails_black_output(self):
|
|
self.assertIs(self.check_background({"bg_share": 0.0}, 0)["pass"], False)
|
|
|
|
def test_absent_target_is_skipped_despite_dataclass_default_zero(self):
|
|
self.assertIsNone(self.check_background({}, 0)["pass"])
|
|
|
|
def test_null_target_is_skipped(self):
|
|
self.assertIsNone(self.check_background({"bg_share": None}, 0)["pass"])
|
|
|
|
def test_positive_target_retains_existing_metric(self):
|
|
result = self.check_background({"bg_share": 0.9}, 0)
|
|
self.assertIs(result["pass"], True)
|
|
self.assertEqual(result["want"], "90.0% +/- 20")
|
|
|
|
def test_invalid_target_fails_instead_of_skipping(self):
|
|
for value in [float("nan"), float("inf"), -0.1, 1.1, "invalid", True]:
|
|
with self.subTest(value=value):
|
|
self.assertIs(
|
|
self.check_background({"bg_share": value}, 0)["pass"], False
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|