import pytest from sqlalchemy import create_engine, select from sqlalchemy.orm import Session from modelforge_api.persistence.models import ( Base, Capability, CapabilityContract, Project, ProjectBinding, ) from modelforge_api.services.manifest_registry import ManifestRegistry from modelforge_api.services.project_registry import sync_project_registry def test_project_registry_materializes_only_real_contracts_and_is_idempotent() -> None: engine = create_engine("sqlite+pysqlite:///:memory:") Base.metadata.create_all(engine) with Session(engine) as session: manifests = ManifestRegistry() enabled_capabilities = {"rag.embedding", "rag.reranking", "vision.embedding"} for manifest in manifests.capabilities(): if manifest.capability not in enabled_capabilities: continue capability = Capability(key=manifest.capability, description=manifest.description) session.add(capability) session.flush() session.add( CapabilityContract( capability_id=capability.id, version=manifest.version, input_schema=manifest.input_schema, output_schema=manifest.output_schema, contract=manifest.model_dump(mode="json"), upgrade_class=manifest.upgrade_class.value, ) ) session.commit() first = sync_project_registry(session, manifests) second = sync_project_registry(session, manifests) assert first.projects_created == 3 assert first.bindings_created == 3 assert first.unavailable_contracts assert second.projects_created == 0 assert second.bindings_created == 0 assert session.query(Project).count() == 3 bindings = session.execute( select(Project.key, Capability.key) .join(ProjectBinding, ProjectBinding.project_id == Project.id) .join( CapabilityContract, CapabilityContract.id == ProjectBinding.capability_contract_id, ) .join(Capability, Capability.id == CapabilityContract.capability_id) ).all() assert set(bindings) == { ("examplerag", "rag.embedding"), ("examplerag", "rag.reranking"), ("examplevision", "vision.embedding"), } @pytest.mark.parametrize("declared_stability", ["planned", "blocked"]) def test_project_registry_skips_unavailable_capabilities_and_preserves_operator_bindings( declared_stability: str, monkeypatch: pytest.MonkeyPatch ) -> None: engine = create_engine("sqlite+pysqlite:///:memory:") Base.metadata.create_all(engine) with Session(engine) as session: manifests = ManifestRegistry() capability_manifest = next( item for item in manifests.capabilities() if item.capability == "assistant.general" and item.version == 1 ) project_manifest = next( item for item in manifests.projects() if item.project.id == "example-ops" ) capability_manifest = capability_manifest.model_copy( update={ "estate": capability_manifest.estate.model_copy( update={"stability": declared_stability} ) } ) monkeypatch.setattr(manifests, "capabilities", lambda: [capability_manifest]) monkeypatch.setattr(manifests, "projects", lambda: [project_manifest]) capability = Capability( key=capability_manifest.capability, description=capability_manifest.description ) session.add(capability) session.flush() contract = CapabilityContract( capability_id=capability.id, version=capability_manifest.version, input_schema=capability_manifest.input_schema, output_schema=capability_manifest.output_schema, contract=capability_manifest.model_dump(mode="json"), upgrade_class=capability_manifest.upgrade_class.value, ) session.add(contract) session.commit() first = sync_project_registry(session, manifests) assert first.bindings_created == 0 assert session.scalar(select(ProjectBinding.id)) is None assert [ ( item.project_key, item.capability, item.contract_version, item.declared_stability, ) for item in first.unavailable_bindings ] == [("example-ops", "assistant.general", 1, declared_stability)] project = session.scalar(select(Project).where(Project.key == "example-ops")) assert project is not None operator_binding = ProjectBinding( project_id=project.id, capability_contract_id=contract.id, channel="stable", priority="interactive", ) session.add(operator_binding) session.commit() operator_binding_id = operator_binding.id second = sync_project_registry(session, manifests) assert second.bindings_created == 0 assert session.scalar(select(ProjectBinding.id)) == operator_binding_id