#!/usr/bin/env python3 """ Render dog(cat) - apply dog effect to cat image. Records full provenance: inputs, effects, software, hardware, owner. """ import hashlib import json import shutil import sys from datetime import datetime, timezone from pathlib import Path # Add effect to path sys.path.insert(0, str(Path(__file__).parent.parent / "artdag-effects" / "dog")) from effect import effect_dog, DOG_HASH def file_hash(path: Path) -> str: """Compute SHA3-256 hash of a file.""" hasher = hashlib.sha3_256() actual_path = path.resolve() if path.is_symlink() else path with open(actual_path, "rb") as f: for chunk in iter(lambda: f.read(65536), b""): hasher.update(chunk) return hasher.hexdigest() def main(): # Registry hashes CAT_HASH = "33268b6e167deaf018cc538de12dbe562612b33e89a749391cef855b320a269b" DOG_EFFECT_HASH = "d048fe313433eb4e38f0e24194ffae91b896ca3e6eed3e50b2cc37b7be495555" ARTDAG_HASH = "96a5972de216aee12ec794dcad5f9360da2e676171eabf24a46dfe1ee5fee4b0" WORKSTATION_HASH = "964bf6e69dc4e2493f42375013caffe26404ec3cf8eb5d9bc170cd42a361523b" # Input (cat) cat_path = Path.home() / "artdag-art" / "cat.jpg" output_dir = Path.home() / "artdag-art" output_path = output_dir / "dog-from-cat.mkv" print("=== Rendering dog(cat) ===\n") # Verify input input_hash = file_hash(cat_path) print(f"Input: {cat_path}") print(f"Input hash: {input_hash}") assert input_hash == CAT_HASH, f"Input hash mismatch! Expected {CAT_HASH}" # Apply dog effect print(f"\nApplying dog effect...") result = effect_dog(cat_path, output_path, {}) # Verify output output_hash = file_hash(result) print(f"\nOutput: {result}") print(f"Output hash: {output_hash}") assert output_hash == DOG_HASH, f"Output hash mismatch! Expected {DOG_HASH}" print(f"\n✓ dog(cat) = dog.mkv") print(f" Cat went in, dog came out!") # Record provenance provenance = { "minted_at": datetime.now(timezone.utc).isoformat(), "minted_by": "@giles@artdag.rose-ash.com", "output": { "name": "dog-from-cat", "content_hash": output_hash, "local_path": str(result), "url": None, # To be filled after push }, "inputs": [ {"name": "cat", "content_hash": CAT_HASH} ], "recipe": { "name": "dog-cat", "description": "Apply dog effect to cat" }, "effects": [ {"name": "effect:dog", "content_hash": DOG_EFFECT_HASH} ], "infrastructure": { "software": {"name": "infra:artdag", "content_hash": ARTDAG_HASH}, "hardware": {"name": "infra:giles-hp", "content_hash": WORKSTATION_HASH} } } # Save provenance provenance_path = result.with_suffix(".provenance.json") with open(provenance_path, "w") as f: json.dump(provenance, f, indent=2) print(f"\nProvenance saved: {provenance_path}") return provenance if __name__ == "__main__": main()