"""Goal contract (parity row 2): absolute target, hard/soft, fail-fast §10. Hard goal reached -> a STRUCTURED stop signal (typed event, never silent); soft goal reached -> a flag without stopping. The percent-goal baseline is D-E-gated: attempting to construct one is an explicit ``NotImplementedError`` refusal, never silent semantics. """ from __future__ import annotations import math import pytest from pydantic import ValidationError from portfolio_optimiser_claude.goals import GoalContract, GoalReached class TestFailFastConstruction: """§10: a malformed goal never constructs.""" @pytest.mark.parametrize("target", [0.0, -100000.0, math.inf, math.nan]) def test_non_positive_or_non_finite_target_is_refused(self, target: float) -> None: with pytest.raises(ValidationError): GoalContract(target_nok=target, mode="hard") def test_unknown_mode_is_refused(self) -> None: with pytest.raises(ValidationError): GoalContract(target_nok=100000.0, mode="maybe") # type: ignore[arg-type] def test_percent_goal_is_an_explicit_gated_refusal(self) -> None: # D-E-gated: the field is reserved, the semantics are NOT implemented — # construction refuses loudly instead of guessing a baseline. with pytest.raises(NotImplementedError, match="D-E"): GoalContract(target_nok=100000.0, mode="hard", target_percent=10.0) class TestHardGoal: """Hard goal reached -> typed stop event carrying target + observed.""" def test_reaching_the_target_raises_a_structured_stop(self) -> None: contract = GoalContract(target_nok=100000.0, mode="hard") with pytest.raises(GoalReached) as excinfo: contract.check(125000.0) assert excinfo.value.target_nok == 100000.0 assert excinfo.value.observed_nok == 125000.0 def test_exactly_at_the_target_counts_as_reached(self) -> None: with pytest.raises(GoalReached): GoalContract(target_nok=100000.0, mode="hard").check(100000.0) def test_under_the_target_returns_false_without_raising(self) -> None: assert GoalContract(target_nok=100000.0, mode="hard").check(99999.0) is False class TestSoftGoal: """Soft goal reached -> a flag, never a stop.""" def test_reaching_the_target_flags_without_stopping(self) -> None: assert GoalContract(target_nok=100000.0, mode="soft").check(125000.0) is True def test_under_the_target_returns_false(self) -> None: assert GoalContract(target_nok=100000.0, mode="soft").check(50000.0) is False