from __future__ import annotations import uuid from pathlib import Path import pytest from pydantic import ValidationError from modelforge_api.domain.external_creative import ( ExternalActionAttestation, ExternalAllocationCreate, ExternalAllocationReconcile, ExternalProfileObservation, ExternalResourceApproval, ) from modelforge_api.services.external_creative import PRIORITY, _digest AUDIO_WORKLOADS = ( "speech_generation", "voice_clone", "music_generation", "sound_generation", "foley_generation", "transcription", "audio_enhancement", "lip_sync", ) def test_priority_order_keeps_production_before_interactive_and_background() -> None: assert PRIORITY["production"] < PRIORITY["interactive"] < PRIORITY["background"] assert PRIORITY["background"] < PRIORITY["benchmark"] def test_resource_binding_requires_bounded_positive_profile() -> None: binding = ExternalResourceApproval( project_id=uuid.uuid4(), resource_ref="wan.video@2.2", workload="video", provider_resource_id="configured-comfyui", configured_vram_bytes=12 * 1024**3, ) assert binding.approved is True with pytest.raises(ValidationError): binding.model_copy(update={"configured_vram_bytes": 0}).model_validate( binding.model_copy(update={"configured_vram_bytes": 0}).model_dump() ) @pytest.mark.parametrize("workload", AUDIO_WORKLOADS) def test_audio_workloads_are_explicitly_admitted_by_the_contract(workload: str) -> None: binding = ExternalResourceApproval( project_id=uuid.uuid4(), resource_ref="candidate.audio@exact-revision", workload=workload, provider_resource_id="configured-audio-provider", approved=False, configured_vram_bytes=4 * 1024**3, ) assert binding.workload == workload assert binding.approved is False def test_unknown_audio_workload_is_rejected() -> None: with pytest.raises(ValidationError): ExternalResourceApproval( project_id=uuid.uuid4(), resource_ref="candidate.audio@exact-revision", workload="generic_audio", provider_resource_id="configured-audio-provider", approved=False, configured_vram_bytes=4 * 1024**3, ) def test_workload_is_part_of_the_idempotent_allocation_identity() -> None: common = { "request_id": "director-shot-42", "idempotency_key": "director-shot-42-sound", "installation_id": "private-muse", "resource_ref": "candidate.audio@exact-revision", "provider_resource_id": "configured-audio-provider", "required_vram_bytes": 4 * 1024**3, } speech = ExternalAllocationCreate(**common, workload="speech_generation") clone = ExternalAllocationCreate(**common, workload="voice_clone") assert _digest(speech) != _digest(clone) def test_attestation_and_reconciliation_are_closed_enums() -> None: attestation = ExternalActionAttestation( action="release_idle_comfy", observed_before=10, observed_after=4, completed_at="2026-09-09T12:00:00Z", ) assert attestation.observed_before - attestation.observed_after == 6 assert ExternalAllocationReconcile(action="confirm_released", reason="provider verified idle") with pytest.raises(ValidationError): ExternalAllocationReconcile(action="force", reason="provider verified idle") def test_profile_observation_is_bounded_and_allocation_bound() -> None: observation = ExternalProfileObservation( allocation_id=uuid.uuid4(), resource_ref="flux.image@9b", provider_resource_id="configured-comfyui", workload="image", observed_peak_vram_bytes=14 * 1024**3, reserved_vram_bytes=16 * 1024**3, duration_ms=120_000, outcome="succeeded", ) assert observation.observed_peak_vram_bytes <= observation.reserved_vram_bytes def test_migration_retains_each_profile_observation() -> None: repository_root = Path(__file__).resolve().parents[2] migration = ( repository_root / "backend/alembic/versions/20260909_0031_external_creative_governance.py" ).read_text() assert '"external_creative_profile_observations"' in migration assert '"uq_external_creative_profile_observation_allocation"' in migration assert 'down_revision = "20260909_0030"' in migration def test_audio_workload_migration_widens_every_persisted_route_component() -> None: repository_root = Path(__file__).resolve().parents[2] migration = ( repository_root / "backend/alembic/versions/20260909_0032_audio_creative_workloads.py" ).read_text() assert 'down_revision = "20260909_0031"' in migration assert '"external_creative_allocations"' in migration assert '"external_creative_resources"' in migration assert '"external_creative_profile_observations"' in migration assert "type_=sa.String(32)" in migration