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>
93 lines
3.4 KiB
Python
93 lines
3.4 KiB
Python
"""Failing-first tests for offline style-pack inspect/validate."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1] / "scripts"
|
|
sys.path.insert(0, str(REPO_ROOT))
|
|
|
|
from tasteforge import pack as pack_mod # noqa: E402
|
|
|
|
FIXTURE = Path(__import__("tasteforge").__file__).resolve().parent / "fixtures" / "flashethereal"
|
|
|
|
|
|
class FixturePackTests(unittest.TestCase):
|
|
def test_fixture_pack_loads_and_inspecks(self):
|
|
sp = pack_mod.load(FIXTURE)
|
|
self.assertEqual(sp.name, "flashethereal")
|
|
report = sp.inspect()
|
|
self.assertEqual(report["name"], "flashethereal")
|
|
self.assertEqual(report["manifest_version"], 1)
|
|
self.assertEqual(len(report["refs"]), 3)
|
|
self.assertTrue(report["artifacts"]["grade"])
|
|
self.assertTrue(report["artifacts"]["cadence"])
|
|
self.assertTrue(report["artifacts"]["spec"])
|
|
|
|
def test_inspect_reports_validation_status(self):
|
|
report = pack_mod.load(FIXTURE).inspect()
|
|
self.assertEqual(report["validation"]["status"], "valid")
|
|
self.assertEqual(report["validation"]["errors"], [])
|
|
# The fixture deliberately ships metadata only; missing stills must be
|
|
# a warning, never silently ignored.
|
|
self.assertTrue(
|
|
any("stills" in w for w in report["validation"]["warnings"])
|
|
)
|
|
|
|
def test_inspect_includes_cadence_and_grade_summary(self):
|
|
report = pack_mod.load(FIXTURE).inspect()
|
|
self.assertAlmostEqual(report["cadence"]["mean_shot"], 0.78, places=1)
|
|
self.assertGreater(report["cadence"]["n_shots"], 50)
|
|
self.assertIn("contrast", report["grade"])
|
|
|
|
def test_fixture_spec_is_dry_run(self):
|
|
sp = pack_mod.load(FIXTURE)
|
|
spec = sp.read_json(sp.spec_path)
|
|
self.assertTrue(spec["source"]["dry_run"])
|
|
|
|
|
|
class BrokenPackTests(unittest.TestCase):
|
|
def _write(self, tmp, manifest) -> Path:
|
|
d = Path(tmp) / "brokenpack"
|
|
d.mkdir(parents=True)
|
|
(d / "pack.json").write_text(json.dumps(manifest))
|
|
return d
|
|
|
|
def test_missing_manifest_raises(self):
|
|
with tempfile.TemporaryDirectory() as td:
|
|
with self.assertRaises(FileNotFoundError):
|
|
pack_mod.load(Path(td) / "nowhere")
|
|
|
|
def test_invalid_manifest_reports_errors(self):
|
|
with tempfile.TemporaryDirectory() as td:
|
|
d = self._write(td, {"name": "broken", "version": 99})
|
|
report = pack_mod.load(d).inspect()
|
|
self.assertEqual(report["validation"]["status"], "invalid")
|
|
self.assertTrue(report["validation"]["errors"])
|
|
|
|
def test_corrupt_cadence_reported(self):
|
|
with tempfile.TemporaryDirectory() as td:
|
|
d = self._write(
|
|
td,
|
|
{
|
|
"name": "broken",
|
|
"version": 1,
|
|
"created": "2026-08-16T05:53:05Z",
|
|
"updated": "2026-08-16T07:10:42Z",
|
|
"refs": [],
|
|
"artifacts": {},
|
|
},
|
|
)
|
|
(d / "cadence.json").write_text(json.dumps({"shots": "nope"}))
|
|
report = pack_mod.load(d).inspect()
|
|
self.assertEqual(report["validation"]["status"], "invalid")
|
|
self.assertTrue(any("cadence" in e for e in report["validation"]["errors"]))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|