from __future__ import annotations import ast from dataclasses import FrozenInstanceError from pathlib import Path import pytest import generate.foundational_families as foundational_families from generate.foundational_families import ( FoundationalFamilySpec, get_foundational_family, get_foundational_family_by_relation_type, iter_foundational_families, require_foundational_family, ) EXPECTED_FAMILY_IDS = ( "binding.quantity_entity", "state_change.transition", "state_change.unary_delta", ) def test_registry_contains_only_the_two_approved_specs_in_deterministic_order() -> None: families = iter_foundational_families() assert isinstance(families, tuple) assert tuple(family.family_id for family in families) == EXPECTED_FAMILY_IDS assert tuple(family.family_id for family in iter_foundational_families()) == ( EXPECTED_FAMILY_IDS ) def test_public_family_accessors() -> None: quantity = get_foundational_family("binding.quantity_entity") state_change = require_foundational_family("state_change.transition") unary_delta = require_foundational_family("state_change.unary_delta") assert quantity is not None assert quantity.family_id == "binding.quantity_entity" assert state_change.family_id == "state_change.transition" assert unary_delta.family_id == "state_change.unary_delta" assert get_foundational_family("missing.family") is None with pytest.raises(KeyError, match="missing.family"): require_foundational_family("missing.family") def test_lookup_by_primary_relation_type() -> None: quantity = get_foundational_family_by_relation_type("quantity_entity") state_change = get_foundational_family_by_relation_type("state_change") unary_delta = get_foundational_family_by_relation_type("unary_delta") assert quantity is get_foundational_family("binding.quantity_entity") assert state_change is get_foundational_family("state_change.transition") assert unary_delta is get_foundational_family("state_change.unary_delta") assert get_foundational_family_by_relation_type("missing_relation") is None def test_registry_keys_are_unique() -> None: families = iter_foundational_families() family_ids = tuple(family.family_id for family in families) relation_types = tuple(family.primary_relation_type for family in families) assert len(family_ids) == len(set(family_ids)) assert len(relation_types) == len(set(relation_types)) def test_specs_are_frozen_and_only_authorized_slices_are_implemented() -> None: for family in iter_foundational_families(): assert isinstance(family, FoundationalFamilySpec) assert family.serving_allowed is False assert "not serving" in family.serving_status.lower() with pytest.raises(FrozenInstanceError): family.display_name = "mutated" # type: ignore[misc] assert require_foundational_family( "binding.quantity_entity" ).implementation_authorized is True assert require_foundational_family( "state_change.transition" ).implementation_authorized is False assert require_foundational_family( "state_change.unary_delta" ).implementation_authorized is True def test_required_adr_0224_fields_are_populated() -> None: required_fields = ( "family_id", "display_name", "status", "related_adrs", "domains", "summary", "surface_chunk_patterns", "semantic_neighborhood", "construction_signatures", "required_roles", "optional_roles", "hazards_confusers", "frame_representation", "contract_readiness_criteria", "verification_style", "refusal_conditions", "cross_domain_evidence", "current_state", "target_state", "serving_status", "primary_relation_type", "future_adapter", ) for family in iter_foundational_families(): assert all(getattr(family, field) for field in required_fields) assert "ADR-0224" in family.related_adrs assert family.hazards_confusers assert family.refusal_conditions assert family.current_state != family.target_state def test_each_family_has_at_least_two_non_math_evidence_examples() -> None: math_domains = { "arithmetic", "arithmetic_quantitative", "arithmetic_proportional", "mathematics", } for family in iter_foundational_families(): non_math_evidence = tuple( evidence for evidence in family.cross_domain_evidence if evidence.domain not in math_domains ) assert len(non_math_evidence) >= 2 assert all(evidence.example for evidence in non_math_evidence) assert all(evidence.expected_roles for evidence in non_math_evidence) def test_registry_module_has_no_markdown_or_filesystem_loading_surface() -> None: source_path = Path(foundational_families.__file__) tree = ast.parse(source_path.read_text(encoding="utf-8")) imported_modules = { alias.name for node in ast.walk(tree) if isinstance(node, ast.Import) for alias in node.names } imported_from_modules = { node.module for node in ast.walk(tree) if isinstance(node, ast.ImportFrom) and node.module is not None } called_names = { node.func.id for node in ast.walk(tree) if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) } called_attributes = { node.func.attr for node in ast.walk(tree) if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute) } assert "pathlib" not in imported_modules | imported_from_modules assert "markdown" not in imported_modules | imported_from_modules assert "open" not in called_names assert not ({"read_text", "read_bytes"} & called_attributes)