"""Rule composition tests.""" from datetime import date from coastwise.data import get_rule_card from coastwise.rules import default_context, compose_safety_result from coastwise.schemas import CoastalRegion, HarvestStatus, RuleCard, UserIntent def test_rule_card_result_includes_status_sources_freshness_and_next_action(): result = compose_safety_result( get_rule_card("lingcod"), default_context(today=date(2026, 6, 13)), ) assert result.status is HarvestStatus.RULES_APPLY assert result.display_name == "Lingcod" assert result.source_links assert result.cache_dates assert "verify" in result.next_safe_action.lower() def test_unknown_result_is_observe_only_without_source_requirement(): result = compose_safety_result( get_rule_card("unknown"), default_context(today=date(2026, 6, 13)), ) assert result.status is HarvestStatus.OBSERVE_ONLY assert result.source_links == () assert "observe" in result.next_safe_action.lower() def test_stricter_exception_cards_do_not_fall_through_to_rules_apply(): for key in ("yelloweye_rockfish", "green_sturgeon", "ocean_salmon", "red_abalone"): result = compose_safety_result( get_rule_card(key), default_context( intent=UserIntent.THINKING_OF_HARVEST, region=CoastalRegion.POINT_ARENA_TO_PIGEON_POINT, today=date(2026, 6, 13), ), ) assert result.status is HarvestStatus.DO_NOT_HARVEST def test_mussel_harvest_during_quarantine_returns_do_not_harvest_warning(): result = compose_safety_result( get_rule_card("mussels"), default_context( intent=UserIntent.THINKING_OF_HARVEST, region=CoastalRegion.POINT_ARENA_TO_PIGEON_POINT, today=date(2026, 6, 13), ), ) assert result.status is HarvestStatus.DO_NOT_HARVEST assert any("cooking" in warning.lower() for warning in result.advisory_warnings) def test_stale_rules_apply_card_is_capped_at_verify_before_harvest(): card = RuleCard( key="demo_fish", display_name="Demo fish", category="fish", aliases=("demo fish",), covered_species=(), region_keys=("sf_coast_point_arena_to_pigeon_point",), photo_supported=False, default_status=HarvestStatus.RULES_APPLY, short_answer="Rules apply.", rule_notes=("Demo note.",), safety_warnings=(), source_names=("CDFW",), source_urls=("https://wildlife.ca.gov/Fishing/Ocean/Regulations",), cache_date=date(2026, 1, 1), ) result = compose_safety_result( card, default_context(today=date(2026, 6, 13)), ) assert result.stale assert result.status is HarvestStatus.VERIFY_BEFORE_HARVEST def test_san_francisco_bay_context_for_sf_coast_card_requires_verification(): result = compose_safety_result( get_rule_card("lingcod"), default_context( intent=UserIntent.THINKING_OF_HARVEST, region=CoastalRegion.SAN_FRANCISCO_BAY, today=date(2026, 6, 13), ), ) assert result.status is HarvestStatus.VERIFY_BEFORE_HARVEST assert any("bay" in warning.lower() for warning in result.advisory_warnings)