From c9ce5cbc14572abe740134d1e036ceb6542b50c2 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Sat, 18 Jul 2026 03:11:50 +0800 Subject: [PATCH] fix: preserve theme lords in API case matching --- scripts/reference_transparency_contract.py | 13 ++++++++++--- tests/test_reference_transparency_contract.py | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/scripts/reference_transparency_contract.py b/scripts/reference_transparency_contract.py index c4b8d24b..5d5e0960 100644 --- a/scripts/reference_transparency_contract.py +++ b/scripts/reference_transparency_contract.py @@ -16,11 +16,11 @@ if str(SCRIPT_DIR) not in sys.path: try: from scripts.domain_calculation_service import compute_chart from scripts.timing_precision_contract import build_timing_precision_contract - from scripts.varga import calc_varga + from scripts.varga import SIGN_LORDS, calc_varga except ModuleNotFoundError: # pragma: no cover - direct script execution from domain_calculation_service import compute_chart from timing_precision_contract import build_timing_precision_contract - from varga import calc_varga + from varga import SIGN_LORDS, calc_varga ROOT = Path(__file__).resolve().parents[1] @@ -54,8 +54,15 @@ def _sign(chart: dict[str, Any], planet: str) -> str | None: def _domain_lord_sign(chart: dict[str, Any], domain: str) -> str | None: house = DOMAIN_HOUSES.get(domain) houses = chart.get("houses") if isinstance(chart, dict) else None - house_value = houses.get(house) if house and isinstance(houses, dict) else None + house_index = int(house.split("_", 1)[1]) if house else None + house_value = None + if isinstance(houses, dict) and house: + house_value = houses.get(house) + if house_value is None and house_index is not None: + house_value = houses.get(house_index) or houses.get(str(house_index)) lord = house_value.get("lord") if isinstance(house_value, dict) else None + if not isinstance(lord, str) and isinstance(house_value, dict): + lord = SIGN_LORDS.get(house_value.get("sign") or house_value.get("cusp_sign")) return _sign(chart, lord) if isinstance(lord, str) else None diff --git a/tests/test_reference_transparency_contract.py b/tests/test_reference_transparency_contract.py index b26a3096..ef0c01e0 100644 --- a/tests/test_reference_transparency_contract.py +++ b/tests/test_reference_transparency_contract.py @@ -166,6 +166,24 @@ def test_marriage_similarity_adds_d9_only_when_both_charts_have_longitudes() -> assert "D9" not in similarity["uncompared_layers"] +def test_api_house_shape_keeps_theme_lord_in_similarity() -> None: + chart = _varga_chart() + chart["houses"] = {10: {"sign": "Taurus", "sign_idx": 1}} + cases = [{ + "case_id": "api_house_shape", "subject": {"name": "Public Example"}, "chart": chart, + "source": {"url": "https://example.com/birth", "source_grade": "primary"}, + "event_outcomes": [{ + "domain": "career", "event_type": "career_breakthrough", "event_date": "2007-01-09", + "outcome": "Public career event", "source": {"url": "https://example.com/event", "source_grade": "primary"}, + }], + "replay": {"outcome_replay_status": "replayed", "do_not_use_for_prediction": False}, + }] + + selected = select_similar_public_cases(chart, ["career"], cases=cases) + + assert "domain_lord_sign" in selected["cases"][0]["similarity"]["matching_factors"] + + def test_default_manifest_exposes_kahlo_health_as_context_only() -> None: from scripts.domain_calculation_service import compute_chart