diff --git a/docs/benchmark/public_real_case_negative_controls_holdout_v2_4controls_20260717.json b/docs/benchmark/public_real_case_negative_controls_holdout_v2_4controls_20260717.json new file mode 100644 index 00000000..67ca69b9 --- /dev/null +++ b/docs/benchmark/public_real_case_negative_controls_holdout_v2_4controls_20260717.json @@ -0,0 +1,3908 @@ +{ + "benchmark_id": "public_real_case_negative_control_pilot_2026_07_11", + "boundary": "Controls are dates without the exact recorded target outcome. They may contain other life events. This pilot measures date ranking and false domain activation, not scientific causal validity.", + "cases": [ + { + "case_id": "albert_ii_accession_2005", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "2005-02-05", + "result_class": "weak_hit", + "score": 6 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2005-03-07", + "result_class": "weak_hit", + "score": 6 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2005-05-06", + "result_class": "weak_hit", + "score": 6 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2005-06-05", + "result_class": "weak_hit", + "score": 6 + } + ], + "domain": "career", + "name": "Albert II, Prince of Monaco", + "positive": { + "actual_label": "domain_activation", + "birth_time_rating": "AA", + "blocked": false, + "case_id": "albert_ii_accession_2005", + "domain": "career", + "event_date": "2005-04-06", + "evidence": { + "arudha_lord": "Venus", + "ascendant": { + "degree": 28.0929, + "degree_in_sign": 28.0929, + "degree_in_sign_raw": 58.0929006900906, + "degree_raw": 58.0929, + "lon": 58.0929, + "lord": "Venus", + "sign": "Taurus", + "sign_cn": "金牛座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "10": { + "level": "极吉", + "sav_score": 31, + "sign": "Aquarius" + }, + "11": { + "level": "吉利", + "sav_score": 29, + "sign": "Pisces" + }, + "6": { + "level": "极吉", + "sav_score": 37, + "sign": "Libra" + }, + "9": { + "level": "吉利", + "sav_score": 29, + "sign": "Capricorn" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 23.9306, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 3, + "sav": 24, + "sign": "Virgo" + }, + "Saturn": { + "bav": 3, + "sav": 22, + "sign": "Gemini" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "quoted BC/BR", + "source_grade": "primary", + "time_accuracy_rating": "AA", + "url": "https://www.astro.com/adbvip/adbvip_03_14.htm" + }, + "domain_varga": { + "birth_info": "1958-03-14 10:50", + "divisional_charts": { + "D10_Dasamsa": { + "Jupiter": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Ketu": { + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "Mars": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "Mercury": { + "sign": "Aquarius", + "sign_cn": "水瓶座" + }, + "Moon": { + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "Rahu": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Saturn": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Sun": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "Venus": { + "sign": "Aquarius", + "sign_cn": "水瓶座" + }, + "ascendant": "Libra" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": { + "CL_10宫(Virgo)": [ + { + "desc": "同宫(10宫)", + "type": "Position" + }, + { + "desc": "合相(4.68°)", + "type": "Conjunction" + } + ] + }, + "saturn": { + "CL_10宫(Virgo)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ] + } + }, + "d1": { + "jupiter": { + "10宫(Aquarius)": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ] + }, + "saturn": { + "Mars(对宫主)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "Venus(LL)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + } + }, + "d9": { + "jupiter": { + "D9_10宫(Gemini)": [ + { + "desc": "同宫(1宫)", + "type": "Position" + }, + { + "desc": "合相(4.68°)", + "type": "Conjunction" + } + ], + "Saturn_D9(Aries)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "Venus_D9(Gemini)": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ] + }, + "saturn": { + "D9_10宫(Gemini)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ], + "Saturn_D9(Aries)": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "Venus_D9(Gemini)": [ + { + "desc": "同宫(10宫)", + "type": "Position" + } + ] + } + }, + "double_transit": [ + { + "jupiter_pac": [ + { + "desc": "同宫(1宫)", + "type": "Position" + }, + { + "desc": "合相(4.68°)", + "type": "Conjunction" + } + ], + "layer": "D9", + "saturn_pac": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ], + "strength": "strong", + "target": "D9_10宫(Gemini)" + }, + { + "jupiter_pac": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "layer": "D9", + "saturn_pac": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "strength": "strong", + "target": "Saturn_D9(Aries)" + }, + { + "jupiter_pac": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ], + "layer": "D9", + "saturn_pac": [ + { + "desc": "同宫(10宫)", + "type": "Position" + } + ], + "strength": "strong", + "target": "Venus_D9(Gemini)" + }, + { + "jupiter_pac": [ + { + "desc": "同宫(10宫)", + "type": "Position" + }, + { + "desc": "合相(4.68°)", + "type": "Conjunction" + } + ], + "layer": "CL", + "saturn_pac": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ], + "strength": "strong", + "target": "CL_10宫(Virgo)" + } + ], + "event_house": 10, + "stats": { + "chandra_lagna": "Sagittarius", + "cl_jupiter_targets": [ + "CL_10宫(Virgo)" + ], + "cl_overlap": [ + "CL_10宫(Virgo)" + ], + "cl_saturn_targets": [ + "CL_10宫(Virgo)" + ], + "d1_jupiter_targets": [ + "10宫(Aquarius)" + ], + "d1_overlap": [], + "d1_saturn_targets": [ + "Mars(对宫主)", + "Venus(LL)" + ], + "d9_ascendant": "Virgo", + "d9_jupiter_targets": [ + "D9_10宫(Gemini)", + "Saturn_D9(Aries)", + "Venus_D9(Gemini)" + ], + "d9_overlap": [ + "D9_10宫(Gemini)", + "Saturn_D9(Aries)", + "Venus_D9(Gemini)" + ], + "d9_saturn_targets": [ + "D9_10宫(Gemini)", + "Saturn_D9(Aries)", + "Venus_D9(Gemini)" + ], + "event_lord_d9_sign": "Aries" + }, + "summary": "✅ Double Transit PAC 确认: D9+CL 多层激活10宫主题", + "transit_date": "2005-04-06" + }, + "event_source": { + "source_grade": "primary", + "url": "https://www.palais.mc/en/princely-family/h-s-h-prince-albert-ii/biography-1-9.html" + }, + "functional_benefic_malefic": { + "ascendant": "Taurus", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_malefics": [ + "Jupiter", + "Mars", + "Moon" + ], + "functional_neutrals": [ + "Sun" + ], + "owned_houses": { + "Jupiter": [ + 8, + 11 + ], + "Mars": [ + 7, + 12 + ], + "Mercury": [ + 2, + 5 + ], + "Moon": [ + 3 + ], + "Saturn": [ + 9, + 10 + ], + "Sun": [ + 4 + ], + "Venus": [ + 1, + 6 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Saturn", + "Venus" + ] + }, + "narayana": { + "ad": { + "end_age": 47.3563, + "lord": "Mercury", + "sign": "Gemini", + "sign_idx": 2, + "start_age": 46.3218, + "years": 1.0345 + }, + "md": { + "end_age": 50.0, + "lord": "Jupiter", + "sign": "Sagittarius", + "sign_idx": 8, + "start_age": 40.0, + "years": 10 + }, + "pd": { + "end_age": 47.0709, + "lord": "Saturn", + "sign": "Aquarius", + "sign_idx": 10, + "start_age": 46.952, + "years": 0.1189 + }, + "remaining_years": 2.94 + }, + "vimshottari": { + "antardasha": "Jupiter", + "mahadasha": "Jupiter" + } + }, + "expected_label": "career_status", + "matched_expected_label": false, + "name": "Albert II, Prince of Monaco", + "outcome": "Began reign as Prince of Monaco", + "result_class": "weak_hit", + "rule_version": "v2_1", + "score": 6, + "signals": [ + "Jupiter_owns_event_houses:[11]", + "Jupiter_occupies_event_house:6", + "narayana_lord_owns_event_house:Jupiter", + "double_transit_pac_strong" + ] + }, + "positive_date": "2005-04-06", + "ranking": { + "candidate_count": 5, + "max_control_score": 6, + "positive_rank": 5, + "positive_score": 6, + "reciprocal_rank": 0.2, + "score_margin": 0, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "boy_george_grammy_1984", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "1983-12-30", + "result_class": "weak_hit", + "score": 6 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1984-01-29", + "result_class": "weak_hit", + "score": 6 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1984-03-29", + "result_class": "weak_hit", + "score": 6 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1984-04-28", + "result_class": "weak_hit", + "score": 6 + } + ], + "domain": "career", + "name": "Boy George", + "positive": { + "actual_label": "domain_activation", + "birth_time_rating": "AA", + "blocked": false, + "case_id": "boy_george_grammy_1984", + "domain": "career", + "event_date": "1984-02-28", + "evidence": { + "arudha_lord": "Venus", + "ascendant": { + "degree": 19.5865, + "degree_in_sign": 19.5865, + "degree_in_sign_raw": 19.58652184346338, + "degree_raw": 19.5865, + "lon": 19.5865, + "lord": "Mars", + "sign": "Aries", + "sign_cn": "白羊座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "10": { + "level": "中等", + "sav_score": 25, + "sign": "Capricorn" + }, + "11": { + "level": "极吉", + "sav_score": 34, + "sign": "Aquarius" + }, + "6": { + "level": "中等", + "sav_score": 25, + "sign": "Virgo" + }, + "9": { + "level": "挑战", + "sav_score": 21, + "sign": "Sagittarius" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 23.6358, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 5, + "sav": 21, + "sign": "Sagittarius" + }, + "Saturn": { + "bav": 0, + "sav": 27, + "sign": "Libra" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "quoted BC/BR", + "source_grade": "primary", + "time_accuracy_rating": "AA", + "url": "https://www.astro.com/adbvip/adbvip_06_14.htm" + }, + "domain_varga": { + "birth_info": "1961-06-14 02:50", + "divisional_charts": { + "D10_Dasamsa": { + "Jupiter": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Ketu": { + "sign": "Aries", + "sign_cn": "白羊座" + }, + "Mars": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Mercury": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "Moon": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Rahu": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "Saturn": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "Sun": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "Venus": { + "sign": "Leo", + "sign_cn": "狮子座" + }, + "ascendant": "Libra" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": {}, + "saturn": { + "CL_Jupiter(宫主)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ] + } + }, + "d1": { + "jupiter": { + "Mars(LL)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + }, + "saturn": { + "10宫(Capricorn)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ], + "Saturn(宫主)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ] + } + }, + "d9": { + "jupiter": { + "D9_10宫(Gemini)": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ] + }, + "saturn": {} + }, + "double_transit": [], + "event_house": 10, + "stats": { + "chandra_lagna": "Gemini", + "cl_jupiter_targets": [], + "cl_overlap": [], + "cl_saturn_targets": [ + "CL_Jupiter(宫主)" + ], + "d1_jupiter_targets": [ + "Mars(LL)" + ], + "d1_overlap": [], + "d1_saturn_targets": [ + "10宫(Capricorn)", + "Saturn(宫主)" + ], + "d9_ascendant": "Virgo", + "d9_jupiter_targets": [ + "D9_10宫(Gemini)" + ], + "d9_overlap": [], + "d9_saturn_targets": [], + "event_lord_d9_sign": "Aquarius" + }, + "summary": "❌ 无 Double Transit PAC 激活", + "transit_date": "1984-02-28" + }, + "event_source": { + "source_grade": "verified_secondary", + "url": "https://en.wikipedia.org/wiki/26th_Annual_Grammy_Awards" + }, + "functional_benefic_malefic": { + "ascendant": "Aries", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Jupiter", + "Mars", + "Sun" + ], + "functional_malefics": [ + "Mercury", + "Saturn" + ], + "functional_neutrals": [ + "Moon", + "Venus" + ], + "owned_houses": { + "Jupiter": [ + 9, + 12 + ], + "Mars": [ + 1, + 8 + ], + "Mercury": [ + 3, + 6 + ], + "Moon": [ + 4 + ], + "Saturn": [ + 10, + 11 + ], + "Sun": [ + 5 + ], + "Venus": [ + 2, + 7 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Mars" + ] + }, + "narayana": { + "ad": { + "end_age": 23.2039, + "lord": "Saturn", + "sign": "Aquarius", + "sign_idx": 10, + "start_age": 21.9223, + "years": 1.2816 + }, + "md": { + "end_age": 26.0, + "lord": "Mercury", + "sign": "Gemini", + "sign_idx": 2, + "start_age": 14.0, + "years": 12 + }, + "pd": { + "end_age": 22.756, + "lord": "Sun", + "sign": "Leo", + "sign_idx": 4, + "start_age": 22.644, + "years": 0.112 + }, + "remaining_years": 3.29 + }, + "vimshottari": { + "antardasha": "Venus", + "mahadasha": "Jupiter" + } + }, + "expected_label": "career_status", + "matched_expected_label": false, + "name": "Boy George", + "outcome": "Culture Club won the Grammy for Best New Artist", + "result_class": "weak_hit", + "rule_version": "v2_1", + "score": 6, + "signals": [ + "Jupiter_owns_event_houses:[9]", + "Jupiter_occupies_event_house:10", + "active_dasha_matches_D10_Lagna_lord:Venus", + "active_dasha_matches_A10_lord:Venus", + "narayana_lord_owns_event_house:Mercury" + ] + }, + "positive_date": "1984-02-28", + "ranking": { + "candidate_count": 5, + "max_control_score": 6, + "positive_rank": 5, + "positive_score": 6, + "reciprocal_rank": 0.2, + "score_margin": 0, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "bergman_oscar_1945", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "1945-01-14", + "result_class": "strong_hit", + "score": 8 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1945-02-13", + "result_class": "strong_hit", + "score": 8 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1945-04-14", + "result_class": "strong_hit", + "score": 8 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1945-05-14", + "result_class": "strong_hit", + "score": 8 + } + ], + "domain": "career", + "name": "Ingrid Bergman", + "positive": { + "actual_label": "career_status", + "birth_time_rating": "AA", + "blocked": false, + "case_id": "bergman_oscar_1945", + "domain": "career", + "event_date": "1945-03-15", + "evidence": { + "arudha_lord": "Saturn", + "ascendant": { + "degree": 0.9464, + "degree_in_sign": 0.9464, + "degree_in_sign_raw": 120.94642922543406, + "degree_raw": 120.9464, + "lon": 120.9464, + "lord": "Sun", + "sign": "Leo", + "sign_cn": "狮子座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "10": { + "level": "中等", + "sav_score": 26, + "sign": "Taurus" + }, + "11": { + "level": "极吉", + "sav_score": 41, + "sign": "Gemini" + }, + "6": { + "level": "极吉", + "sav_score": 37, + "sign": "Capricorn" + }, + "9": { + "level": "极吉", + "sav_score": 31, + "sign": "Aries" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 23.0917, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 5, + "sav": 26, + "sign": "Leo" + }, + "Saturn": { + "bav": 5, + "sav": 41, + "sign": "Gemini" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "BC/BR in hand", + "source_grade": "primary", + "time_accuracy_rating": "AA", + "url": "https://www.astro.com/adbvip/adbvip_08_29.htm" + }, + "domain_varga": { + "birth_info": "1915-08-29 03:30", + "divisional_charts": { + "D10_Dasamsa": { + "Jupiter": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Ketu": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "Mars": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "Mercury": { + "sign": "Aries", + "sign_cn": "白羊座" + }, + "Moon": { + "sign": "Aries", + "sign_cn": "白羊座" + }, + "Rahu": { + "sign": "Aries", + "sign_cn": "白羊座" + }, + "Saturn": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Sun": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "Venus": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "ascendant": "Leo" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": { + "CL_10宫(Capricorn)": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ] + }, + "saturn": { + "CL_10宫(Capricorn)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "CL_Saturn(宫主)": [ + { + "desc": "同宫(3宫)", + "type": "Position" + }, + { + "desc": "合相(9.73°)", + "type": "Conjunction" + } + ] + } + }, + "d1": { + "jupiter": { + "10宫(Taurus)": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ], + "Sun(LL)": [ + { + "desc": "同宫(1宫)", + "type": "Position" + } + ], + "Venus(宫主)": [ + { + "desc": "同宫(1宫)", + "type": "Position" + } + ] + }, + "saturn": { + "Saturn(对宫主)": [ + { + "desc": "同宫(11宫)", + "type": "Position" + }, + { + "desc": "合相(9.73°)", + "type": "Conjunction" + } + ] + } + }, + "d9": { + "jupiter": {}, + "saturn": { + "D9_10宫(Capricorn)": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "D9_Saturn(宫主)": [ + { + "desc": "同宫(3宫)", + "type": "Position" + }, + { + "desc": "合相(9.73°)", + "type": "Conjunction" + } + ], + "Venus_D9(Gemini)": [ + { + "desc": "同宫(3宫)", + "type": "Position" + }, + { + "desc": "合相(4.18°)", + "type": "Conjunction" + } + ] + } + }, + "double_transit": [ + { + "jupiter_pac": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ], + "layer": "CL", + "saturn_pac": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "strength": "strong", + "target": "CL_10宫(Capricorn)" + }, + { + "jupiter_pac": [ + { + "desc": "同宫(1宫)", + "type": "Position" + } + ], + "layer": "D1+D9", + "saturn_pac": [ + { + "desc": "同宫(3宫)", + "type": "Position" + }, + { + "desc": "合相(4.18°)", + "type": "Conjunction" + } + ], + "strength": "moderate", + "target": "Jupiter(D1)Venus(宫主) + Saturn(D9)Venus_D9(Gemini)" + } + ], + "event_house": 10, + "stats": { + "chandra_lagna": "Aries", + "cl_jupiter_targets": [ + "CL_10宫(Capricorn)" + ], + "cl_overlap": [ + "CL_10宫(Capricorn)" + ], + "cl_saturn_targets": [ + "CL_10宫(Capricorn)", + "CL_Saturn(宫主)" + ], + "d1_jupiter_targets": [ + "10宫(Taurus)", + "Sun(LL)", + "Venus(宫主)" + ], + "d1_overlap": [], + "d1_saturn_targets": [ + "Saturn(对宫主)" + ], + "d9_ascendant": "Aries", + "d9_jupiter_targets": [], + "d9_overlap": [], + "d9_saturn_targets": [ + "D9_10宫(Capricorn)", + "D9_Saturn(宫主)", + "Venus_D9(Gemini)" + ], + "event_lord_d9_sign": "Gemini" + }, + "summary": "⚠️ Chandra Lagna 层 Double Transit 激活,D1/D9 未确认", + "transit_date": "1945-03-15" + }, + "event_source": { + "source_grade": "primary", + "url": "https://www.oscars.org/oscars/ceremonies/1945" + }, + "functional_benefic_malefic": { + "ascendant": "Leo", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Jupiter", + "Mars", + "Sun" + ], + "functional_malefics": [ + "Mercury", + "Moon", + "Saturn", + "Venus" + ], + "functional_neutrals": [], + "owned_houses": { + "Jupiter": [ + 5, + 8 + ], + "Mars": [ + 4, + 9 + ], + "Mercury": [ + 2, + 11 + ], + "Moon": [ + 12 + ], + "Saturn": [ + 6, + 7 + ], + "Sun": [ + 1 + ], + "Venus": [ + 3, + 10 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Mars" + ] + }, + "narayana": { + "ad": { + "end_age": 30.125, + "lord": "Moon", + "sign": "Cancer", + "sign_idx": 3, + "start_age": 29.0, + "years": 1.125 + }, + "md": { + "end_age": 33.0, + "lord": "Venus", + "sign": "Libra", + "sign_idx": 6, + "start_age": 23.0, + "years": 10 + }, + "pd": { + "end_age": 29.5906, + "lord": "Venus", + "sign": "Libra", + "sign_idx": 6, + "start_age": 29.45, + "years": 0.1406 + }, + "remaining_years": 3.46 + }, + "vimshottari": { + "antardasha": "Mercury", + "mahadasha": "Sun" + } + }, + "expected_label": "career_status", + "matched_expected_label": true, + "name": "Ingrid Bergman", + "outcome": "Won Best Actress for Gaslight", + "result_class": "strong_hit", + "rule_version": "v2_1", + "score": 8, + "signals": [ + "Sun_domain_karaka", + "Mercury_owns_event_houses:[11]", + "Mercury_domain_karaka", + "active_dasha_matches_D10_Lagna_lord:Sun", + "narayana_lord_owns_event_house:Venus", + "double_transit_pac_strong" + ] + }, + "positive_date": "1945-03-15", + "ranking": { + "candidate_count": 5, + "max_control_score": 8, + "positive_rank": 5, + "positive_score": 8, + "reciprocal_rank": 0.2, + "score_margin": 0, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "morissette_grammy_1996", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "1995-12-30", + "result_class": "weak_hit", + "score": 6 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1996-01-29", + "result_class": "weak_hit", + "score": 6 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1996-03-29", + "result_class": "weak_hit", + "score": 4 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1996-04-28", + "result_class": "weak_hit", + "score": 4 + } + ], + "domain": "career", + "name": "Alanis Morissette", + "positive": { + "actual_label": "domain_activation", + "birth_time_rating": "A", + "blocked": false, + "case_id": "morissette_grammy_1996", + "domain": "career", + "event_date": "1996-02-28", + "evidence": { + "arudha_lord": "Saturn", + "ascendant": { + "degree": 15.1562, + "degree_in_sign": 15.1562, + "degree_in_sign_raw": 105.15618971934725, + "degree_raw": 105.1562, + "lon": 105.1562, + "lord": "Moon", + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "10": { + "level": "极吉", + "sav_score": 32, + "sign": "Aries" + }, + "11": { + "level": "吉利", + "sav_score": 28, + "sign": "Taurus" + }, + "6": { + "level": "极吉", + "sav_score": 34, + "sign": "Sagittarius" + }, + "9": { + "level": "极吉", + "sav_score": 31, + "sign": "Pisces" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 23.8034, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 4, + "sav": 34, + "sign": "Sagittarius" + }, + "Saturn": { + "bav": 4, + "sav": 31, + "sign": "Pisces" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "from memory", + "source_grade": "verified_secondary", + "time_accuracy_rating": "A", + "url": "https://www.astro.com/adbvip/adbvip_06_01.htm" + }, + "domain_varga": { + "birth_info": "1974-06-01 09:51", + "divisional_charts": { + "D10_Dasamsa": { + "Jupiter": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Ketu": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Mars": { + "sign": "Pisces", + "sign_cn": "双鱼座" + }, + "Mercury": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Moon": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Rahu": { + "sign": "Pisces", + "sign_cn": "双鱼座" + }, + "Saturn": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Sun": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "Venus": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "ascendant": "Leo" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": { + "CL_10宫(Cancer)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + }, + "saturn": { + "CL_Moon(宫主)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + } + }, + "d1": { + "jupiter": { + "Mars(宫主)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + }, + "saturn": { + "Moon(LL)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "Saturn(对宫主)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ] + } + }, + "d9": { + "jupiter": { + "D9_Sun(宫主)": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ], + "Mars_D9(Cancer)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "Moon_D9(Sagittarius)": [ + { + "desc": "同宫(2宫)", + "type": "Position" + }, + { + "desc": "合相(2.71°)", + "type": "Conjunction" + } + ] + }, + "saturn": {} + }, + "double_transit": [], + "event_house": 10, + "stats": { + "chandra_lagna": "Libra", + "cl_jupiter_targets": [ + "CL_10宫(Cancer)" + ], + "cl_overlap": [], + "cl_saturn_targets": [ + "CL_Moon(宫主)" + ], + "d1_jupiter_targets": [ + "Mars(宫主)" + ], + "d1_overlap": [], + "d1_saturn_targets": [ + "Moon(LL)", + "Saturn(对宫主)" + ], + "d9_ascendant": "Scorpio", + "d9_jupiter_targets": [ + "D9_Sun(宫主)", + "Mars_D9(Cancer)", + "Moon_D9(Sagittarius)" + ], + "d9_overlap": [], + "d9_saturn_targets": [], + "event_lord_d9_sign": "Cancer" + }, + "summary": "❌ 无 Double Transit PAC 激活", + "transit_date": "1996-02-28" + }, + "event_source": { + "source_grade": "verified_secondary", + "url": "https://en.wikipedia.org/wiki/38th_Annual_Grammy_Awards" + }, + "functional_benefic_malefic": { + "ascendant": "Cancer", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Jupiter", + "Mars", + "Moon" + ], + "functional_malefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_neutrals": [ + "Sun" + ], + "owned_houses": { + "Jupiter": [ + 6, + 9 + ], + "Mars": [ + 5, + 10 + ], + "Mercury": [ + 3, + 12 + ], + "Moon": [ + 1 + ], + "Saturn": [ + 7, + 8 + ], + "Sun": [ + 2 + ], + "Venus": [ + 4, + 11 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Mars" + ] + }, + "narayana": { + "ad": { + "end_age": 22.012, + "lord": "Mars", + "sign": "Scorpio", + "sign_idx": 7, + "start_age": 21.4337, + "years": 0.5783 + }, + "md": { + "end_age": 27.0, + "lord": "Venus", + "sign": "Libra", + "sign_idx": 6, + "start_age": 21.0, + "years": 6 + }, + "pd": { + "end_age": 21.8239, + "lord": "Mercury", + "sign": "Gemini", + "sign_idx": 2, + "start_age": 21.7403, + "years": 0.0836 + }, + "remaining_years": 5.26 + }, + "vimshottari": { + "antardasha": "Mercury", + "mahadasha": "Jupiter" + } + }, + "expected_label": "career_status", + "matched_expected_label": false, + "name": "Alanis Morissette", + "outcome": "Won four Grammy awards", + "result_class": "weak_hit", + "rule_version": "v2_1", + "score": 4, + "signals": [ + "Jupiter_owns_event_houses:[6, 9]", + "Mercury_domain_karaka", + "narayana_lord_owns_event_house:Venus" + ] + }, + "positive_date": "1996-02-28", + "ranking": { + "candidate_count": 5, + "max_control_score": 6, + "positive_rank": 5, + "positive_score": 4, + "reciprocal_rank": 0.2, + "score_margin": -2, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "dion_eurovision_1988", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "1988-03-01", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1988-03-31", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1988-05-30", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1988-06-29", + "result_class": "weak_hit", + "score": 5 + } + ], + "domain": "career", + "name": "Celine Dion", + "positive": { + "actual_label": "domain_activation", + "birth_time_rating": "A", + "blocked": false, + "case_id": "dion_eurovision_1988", + "domain": "career", + "event_date": "1988-04-30", + "evidence": { + "arudha_lord": "Saturn", + "ascendant": { + "degree": 9.1356, + "degree_in_sign": 9.1356, + "degree_in_sign_raw": 99.13557485171225, + "degree_raw": 99.1356, + "lon": 99.1356, + "lord": "Moon", + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "10": { + "level": "中等", + "sav_score": 27, + "sign": "Aries" + }, + "11": { + "level": "极吉", + "sav_score": 31, + "sign": "Taurus" + }, + "6": { + "level": "极吉", + "sav_score": 37, + "sign": "Sagittarius" + }, + "9": { + "level": "挑战", + "sav_score": 19, + "sign": "Pisces" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 23.6941, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 3, + "sav": 27, + "sign": "Aries" + }, + "Saturn": { + "bav": 5, + "sav": 37, + "sign": "Sagittarius" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "from memory", + "source_grade": "verified_secondary", + "time_accuracy_rating": "A", + "url": "https://www.astro.com/adbvip/adbvip_03_30.htm" + }, + "domain_varga": { + "birth_info": "1968-03-30 12:15", + "divisional_charts": { + "D10_Dasamsa": { + "Jupiter": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Ketu": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Mars": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "Mercury": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "Moon": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "Rahu": { + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "Saturn": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "Sun": { + "sign": "Aries", + "sign_cn": "白羊座" + }, + "Venus": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "ascendant": "Gemini" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": { + "CL_10宫(Capricorn)": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ] + }, + "saturn": { + "CL_Saturn(宫主)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ] + } + }, + "d1": { + "jupiter": { + "10宫(Aries)": [ + { + "desc": "同宫(10宫)", + "type": "Position" + }, + { + "desc": "合相(3.45°)", + "type": "Conjunction" + } + ], + "Mars(宫主)": [ + { + "desc": "同宫(10宫)", + "type": "Position" + }, + { + "desc": "合相(9.85°)", + "type": "Conjunction" + } + ], + "Moon(LL)": [ + { + "desc": "同宫(10宫)", + "type": "Position" + } + ] + }, + "saturn": { + "Saturn(对宫主)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ] + } + }, + "d9": { + "jupiter": { + "D9_10宫(Gemini)": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ] + }, + "saturn": {} + }, + "double_transit": [], + "event_house": 10, + "stats": { + "chandra_lagna": "Aries", + "cl_jupiter_targets": [ + "CL_10宫(Capricorn)" + ], + "cl_overlap": [], + "cl_saturn_targets": [ + "CL_Saturn(宫主)" + ], + "d1_jupiter_targets": [ + "10宫(Aries)", + "Mars(宫主)", + "Moon(LL)" + ], + "d1_overlap": [], + "d1_saturn_targets": [ + "Saturn(对宫主)" + ], + "d9_ascendant": "Virgo", + "d9_jupiter_targets": [ + "D9_10宫(Gemini)" + ], + "d9_overlap": [], + "d9_saturn_targets": [], + "event_lord_d9_sign": "Gemini" + }, + "summary": "❌ 无 Double Transit PAC 激活", + "transit_date": "1988-04-30" + }, + "event_source": { + "source_grade": "primary", + "url": "https://eurovision.tv/event/dublin-1988" + }, + "functional_benefic_malefic": { + "ascendant": "Cancer", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Jupiter", + "Mars", + "Moon" + ], + "functional_malefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_neutrals": [ + "Sun" + ], + "owned_houses": { + "Jupiter": [ + 6, + 9 + ], + "Mars": [ + 5, + 10 + ], + "Mercury": [ + 3, + 12 + ], + "Moon": [ + 1 + ], + "Saturn": [ + 7, + 8 + ], + "Sun": [ + 2 + ], + "Venus": [ + 4, + 11 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Mars" + ] + }, + "narayana": { + "ad": { + "end_age": 20.5333, + "lord": "Moon", + "sign": "Cancer", + "sign_idx": 3, + "start_age": 19.9333, + "years": 0.6 + }, + "md": { + "end_age": 21.0, + "lord": "Mercury", + "sign": "Virgo", + "sign_idx": 5, + "start_age": 16.0, + "years": 5 + }, + "pd": { + "end_age": 20.1013, + "lord": "Mercury", + "sign": "Virgo", + "sign_idx": 5, + "start_age": 20.0613, + "years": 0.04 + }, + "remaining_years": 0.91 + }, + "vimshottari": { + "antardasha": "Mercury", + "mahadasha": "Venus" + } + }, + "expected_label": "career_status", + "matched_expected_label": false, + "name": "Celine Dion", + "outcome": "Won the Eurovision Song Contest for Switzerland", + "result_class": "weak_hit", + "rule_version": "v2_1", + "score": 5, + "signals": [ + "Venus_owns_event_houses:[11]", + "Mercury_domain_karaka", + "active_dasha_matches_D10_Lagna_lord:Mercury", + "active_dasha_matches_Amatyakaraka:Mercury" + ] + }, + "positive_date": "1988-04-30", + "ranking": { + "candidate_count": 5, + "max_control_score": 5, + "positive_rank": 5, + "positive_score": 5, + "reciprocal_rank": 0.2, + "score_margin": 0, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "mccartney_marriage_1969", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "1969-01-11", + "result_class": "strong_hit", + "score": 9 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1969-02-10", + "result_class": "strong_hit", + "score": 9 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1969-04-11", + "result_class": "strong_hit", + "score": 7 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1969-05-11", + "result_class": "strong_hit", + "score": 7 + } + ], + "domain": "marriage", + "name": "Paul McCartney", + "positive": { + "actual_label": "legal_marriage", + "birth_time_rating": "A", + "blocked": false, + "case_id": "mccartney_marriage_1969", + "domain": "marriage", + "event_date": "1969-03-12", + "evidence": { + "arudha_lord": "Mars", + "ascendant": { + "degree": 2.2532, + "degree_in_sign": 2.2532, + "degree_in_sign_raw": 152.25316730126025, + "degree_raw": 152.2532, + "lon": 152.2532, + "lord": "Mercury", + "sign": "Virgo", + "sign_cn": "处女座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "11": { + "level": "极吉", + "sav_score": 30, + "sign": "Cancer" + }, + "2": { + "level": "中等", + "sav_score": 26, + "sign": "Libra" + }, + "5": { + "level": "吉利", + "sav_score": 29, + "sign": "Capricorn" + }, + "7": { + "level": "极吉", + "sav_score": 32, + "sign": "Pisces" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 23.4268, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 6, + "sav": 32, + "sign": "Virgo" + }, + "Saturn": { + "bav": 4, + "sav": 31, + "sign": "Aries" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "from memory", + "source_grade": "verified_secondary", + "time_accuracy_rating": "A", + "url": "https://www.astro.com/adbvip/adbvip_06_18.htm" + }, + "domain_varga": { + "birth_info": "1942-06-18 14:00", + "divisional_charts": { + "D9_Navamsa": { + "Jupiter": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Ketu": { + "sign": "Aquarius", + "sign_cn": "水瓶座" + }, + "Mars": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Mercury": { + "sign": "Leo", + "sign_cn": "狮子座" + }, + "Moon": { + "sign": "Aquarius", + "sign_cn": "水瓶座" + }, + "Rahu": { + "sign": "Leo", + "sign_cn": "狮子座" + }, + "Saturn": { + "sign": "Aries", + "sign_cn": "白羊座" + }, + "Sun": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "Venus": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "ascendant": "Capricorn" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": {}, + "saturn": {} + }, + "d1": { + "jupiter": { + "Jupiter(宫主)": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ], + "Jupiter(对宫主)": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ] + }, + "saturn": {} + }, + "d9": { + "jupiter": {}, + "saturn": { + "D9_Moon(宫主)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ] + } + }, + "double_transit": [], + "event_house": 7, + "stats": { + "chandra_lagna": "Cancer", + "cl_jupiter_targets": [], + "cl_overlap": [], + "cl_saturn_targets": [], + "d1_jupiter_targets": [ + "Jupiter(宫主)", + "Jupiter(对宫主)" + ], + "d1_overlap": [], + "d1_saturn_targets": [], + "d9_ascendant": "Capricorn", + "d9_jupiter_targets": [], + "d9_overlap": [], + "d9_saturn_targets": [ + "D9_Moon(宫主)" + ], + "event_lord_d9_sign": "Sagittarius" + }, + "summary": "❌ 无 Double Transit PAC 激活", + "transit_date": "1969-03-12" + }, + "event_source": { + "source_grade": "verified_secondary", + "url": "https://en.wikipedia.org/wiki/Personal_relationships_of_Paul_McCartney" + }, + "functional_benefic_malefic": { + "ascendant": "Virgo", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_malefics": [ + "Mars", + "Moon", + "Sun" + ], + "functional_neutrals": [ + "Jupiter" + ], + "owned_houses": { + "Jupiter": [ + 4, + 7 + ], + "Mars": [ + 3, + 8 + ], + "Mercury": [ + 1, + 10 + ], + "Moon": [ + 11 + ], + "Saturn": [ + 5, + 6 + ], + "Sun": [ + 12 + ], + "Venus": [ + 2, + 9 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Mercury" + ] + }, + "narayana": { + "ad": { + "end_age": 27.0118, + "lord": "Mercury", + "sign": "Virgo", + "sign_idx": 5, + "start_age": 26.4471, + "years": 0.5647 + }, + "md": { + "end_age": 28.0, + "lord": "Jupiter", + "sign": "Sagittarius", + "sign_idx": 8, + "start_age": 22.0, + "years": 6 + }, + "pd": { + "end_age": 26.7926, + "lord": "Venus", + "sign": "Taurus", + "sign_idx": 1, + "start_age": 26.7195, + "years": 0.0731 + }, + "remaining_years": 1.27 + }, + "vimshottari": { + "antardasha": "Jupiter", + "mahadasha": "Venus" + } + }, + "expected_label": "legal_marriage", + "matched_expected_label": true, + "name": "Paul McCartney", + "outcome": "Married Linda Eastman", + "result_class": "strong_hit", + "rule_version": "v2_1", + "score": 7, + "signals": [ + "Venus_owns_event_houses:[2]", + "Venus_domain_karaka", + "Jupiter_owns_event_houses:[7]", + "Jupiter_domain_karaka", + "narayana_lord_owns_event_house:Jupiter" + ] + }, + "positive_date": "1969-03-12", + "ranking": { + "candidate_count": 5, + "max_control_score": 9, + "positive_rank": 5, + "positive_score": 7, + "reciprocal_rank": 0.2, + "score_margin": -2, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "depp_marriage_2015", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "2014-12-05", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2015-01-04", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2015-03-05", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2015-04-04", + "result_class": "weak_hit", + "score": 5 + } + ], + "domain": "marriage", + "name": "Johnny Depp", + "positive": { + "actual_label": "domain_activation", + "birth_time_rating": "AA", + "blocked": false, + "case_id": "depp_marriage_2015", + "domain": "marriage", + "event_date": "2015-02-03", + "evidence": { + "arudha_lord": "Mars", + "ascendant": { + "degree": 6.9997, + "degree_in_sign": 6.9997, + "degree_in_sign_raw": 96.99973733317259, + "degree_raw": 96.9997, + "lon": 96.9997, + "lord": "Moon", + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "11": { + "level": "极吉", + "sav_score": 31, + "sign": "Taurus" + }, + "2": { + "level": "中等", + "sav_score": 26, + "sign": "Leo" + }, + "5": { + "level": "挑战", + "sav_score": 23, + "sign": "Scorpio" + }, + "7": { + "level": "吉利", + "sav_score": 29, + "sign": "Capricorn" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 24.0679, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 2, + "sav": 26, + "sign": "Cancer" + }, + "Saturn": { + "bav": 2, + "sav": 23, + "sign": "Scorpio" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "BC/BR in hand", + "source_grade": "primary", + "time_accuracy_rating": "AA", + "url": "https://www.astro.com/adbvip/adbvip_06_09.htm" + }, + "domain_varga": { + "birth_info": "1963-06-09 08:44", + "divisional_charts": { + "D9_Navamsa": { + "Jupiter": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Ketu": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Mars": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "Mercury": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Moon": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Rahu": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "Saturn": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Sun": { + "sign": "Leo", + "sign_cn": "狮子座" + }, + "Venus": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "ascendant": "Virgo" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": {}, + "saturn": { + "CL_7宫(Gemini)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + } + }, + "d1": { + "jupiter": { + "Moon(LL)": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ] + }, + "saturn": {} + }, + "d9": { + "jupiter": {}, + "saturn": { + "D9_7宫(Pisces)": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "Moon_D9(Virgo)": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "Saturn_D9(Virgo)": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ] + } + }, + "double_transit": [], + "event_house": 7, + "stats": { + "chandra_lagna": "Sagittarius", + "cl_jupiter_targets": [], + "cl_overlap": [], + "cl_saturn_targets": [ + "CL_7宫(Gemini)" + ], + "d1_jupiter_targets": [ + "Moon(LL)" + ], + "d1_overlap": [], + "d1_saturn_targets": [], + "d9_ascendant": "Virgo", + "d9_jupiter_targets": [], + "d9_overlap": [], + "d9_saturn_targets": [ + "D9_7宫(Pisces)", + "Moon_D9(Virgo)", + "Saturn_D9(Virgo)" + ], + "event_lord_d9_sign": "Virgo" + }, + "summary": "❌ 无 Double Transit PAC 激活", + "transit_date": "2015-02-03" + }, + "event_source": { + "source_grade": "verified_secondary", + "url": "https://variety.com/2016/biz/news/johnny-depp-amber-heard-divorce-settlement-1201837685/" + }, + "functional_benefic_malefic": { + "ascendant": "Cancer", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Jupiter", + "Mars", + "Moon" + ], + "functional_malefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_neutrals": [ + "Sun" + ], + "owned_houses": { + "Jupiter": [ + 6, + 9 + ], + "Mars": [ + 5, + 10 + ], + "Mercury": [ + 3, + 12 + ], + "Moon": [ + 1 + ], + "Saturn": [ + 7, + 8 + ], + "Sun": [ + 2 + ], + "Venus": [ + 4, + 11 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Mars" + ] + }, + "narayana": { + "ad": { + "end_age": 52.6505, + "lord": "Mars", + "sign": "Scorpio", + "sign_idx": 7, + "start_age": 51.6019, + "years": 1.0485 + }, + "md": { + "end_age": 53.0, + "lord": "Saturn", + "sign": "Capricorn", + "sign_idx": 9, + "start_age": 41.0, + "years": 12 + }, + "pd": { + "end_age": 51.6935, + "lord": "Mars", + "sign": "Scorpio", + "sign_idx": 7, + "start_age": 51.6019, + "years": 0.0916 + }, + "remaining_years": 1.34 + }, + "vimshottari": { + "antardasha": "Jupiter", + "mahadasha": "Jupiter" + } + }, + "expected_label": "legal_marriage", + "matched_expected_label": false, + "name": "Johnny Depp", + "outcome": "Married Amber Heard in a civil ceremony", + "result_class": "weak_hit", + "rule_version": "v2_1", + "score": 5, + "signals": [ + "Jupiter_domain_karaka", + "active_dasha_matches_D9_7L:Jupiter", + "narayana_activates_primary_event_sign:Capricorn", + "narayana_lord_owns_event_house:Saturn" + ] + }, + "positive_date": "2015-02-03", + "ranking": { + "candidate_count": 5, + "max_control_score": 5, + "positive_rank": 5, + "positive_score": 5, + "reciprocal_rank": 0.2, + "score_margin": 0, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "kidman_marriage_2006", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "2006-04-26", + "result_class": "miss", + "score": 3 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2006-05-26", + "result_class": "miss", + "score": 3 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2006-07-25", + "result_class": "miss", + "score": 3 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2006-08-24", + "result_class": "miss", + "score": 3 + } + ], + "domain": "marriage", + "name": "Nicole Kidman", + "positive": { + "actual_label": null, + "birth_time_rating": "A", + "blocked": false, + "case_id": "kidman_marriage_2006", + "domain": "marriage", + "event_date": "2006-06-25", + "evidence": { + "arudha_lord": "Mercury", + "ascendant": { + "degree": 12.9323, + "degree_in_sign": 12.9323, + "degree_in_sign_raw": 192.9322623333046, + "degree_raw": 192.9323, + "lon": 192.9323, + "lord": "Venus", + "sign": "Libra", + "sign_cn": "天秤座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "11": { + "level": "吉利", + "sav_score": 28, + "sign": "Leo" + }, + "2": { + "level": "吉利", + "sav_score": 28, + "sign": "Scorpio" + }, + "5": { + "level": "挑战", + "sav_score": 23, + "sign": "Aquarius" + }, + "7": { + "level": "极吉", + "sav_score": 33, + "sign": "Aries" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 23.9476, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 4, + "sav": 28, + "sign": "Libra" + }, + "Saturn": { + "bav": 4, + "sav": 28, + "sign": "Cancer" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "from memory", + "source_grade": "verified_secondary", + "time_accuracy_rating": "A", + "url": "https://www.astro.com/adbvip/adbvip_06_20.htm" + }, + "domain_varga": { + "birth_info": "1967-06-20 15:15", + "divisional_charts": { + "D9_Navamsa": { + "Jupiter": { + "sign": "Libra", + "sign_cn": "天秤座" + }, + "Ketu": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Mars": { + "sign": "Leo", + "sign_cn": "狮子座" + }, + "Mercury": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "Moon": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Rahu": { + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "Saturn": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Sun": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "Venus": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "ascendant": "Capricorn" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": { + "CL_7宫(Taurus)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "CL_Venus(宫主)": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ] + }, + "saturn": { + "CL_7宫(Taurus)": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "CL_Venus(宫主)": [ + { + "desc": "同宫(9宫)", + "type": "Position" + }, + { + "desc": "合相(5.32°)", + "type": "Conjunction" + } + ] + } + }, + "d1": { + "jupiter": { + "Venus(LL)": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ] + }, + "saturn": { + "Venus(LL)": [ + { + "desc": "同宫(10宫)", + "type": "Position" + }, + { + "desc": "合相(5.32°)", + "type": "Conjunction" + } + ] + } + }, + "d9": { + "jupiter": {}, + "saturn": {} + }, + "double_transit": [ + { + "jupiter_pac": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ], + "layer": "D1", + "saturn_pac": [ + { + "desc": "同宫(10宫)", + "type": "Position" + }, + { + "desc": "合相(5.32°)", + "type": "Conjunction" + } + ], + "strength": "strong", + "target": "Venus(LL)" + }, + { + "jupiter_pac": [ + { + "desc": "9宫相位", + "offset": 9, + "type": "Aspect" + } + ], + "layer": "CL", + "saturn_pac": [ + { + "desc": "同宫(9宫)", + "type": "Position" + }, + { + "desc": "合相(5.32°)", + "type": "Conjunction" + } + ], + "strength": "strong", + "target": "CL_Venus(宫主)" + }, + { + "jupiter_pac": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "layer": "CL", + "saturn_pac": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "strength": "strong", + "target": "CL_7宫(Taurus)" + } + ], + "event_house": 7, + "stats": { + "chandra_lagna": "Scorpio", + "cl_jupiter_targets": [ + "CL_7宫(Taurus)", + "CL_Venus(宫主)" + ], + "cl_overlap": [ + "CL_7宫(Taurus)", + "CL_Venus(宫主)" + ], + "cl_saturn_targets": [ + "CL_7宫(Taurus)", + "CL_Venus(宫主)" + ], + "d1_jupiter_targets": [ + "Venus(LL)" + ], + "d1_overlap": [ + "Venus(LL)" + ], + "d1_saturn_targets": [ + "Venus(LL)" + ], + "d9_ascendant": "Capricorn", + "d9_jupiter_targets": [], + "d9_overlap": [], + "d9_saturn_targets": [], + "event_lord_d9_sign": "Leo" + }, + "summary": "✅ Double Transit PAC 确认: D1+CL 多层激活7宫主题", + "transit_date": "2006-06-25" + }, + "event_source": { + "source_grade": "verified_secondary", + "url": "https://en.wikipedia.org/wiki/Nicole_Kidman" + }, + "functional_benefic_malefic": { + "ascendant": "Libra", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_malefics": [ + "Jupiter", + "Sun" + ], + "functional_neutrals": [ + "Mars", + "Moon" + ], + "owned_houses": { + "Jupiter": [ + 3, + 6 + ], + "Mars": [ + 2, + 7 + ], + "Mercury": [ + 9, + 12 + ], + "Moon": [ + 10 + ], + "Saturn": [ + 4, + 5 + ], + "Sun": [ + 11 + ], + "Venus": [ + 1, + 8 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Saturn", + "Venus" + ] + }, + "narayana": { + "ad": { + "end_age": 39.2267, + "lord": "Venus", + "sign": "Libra", + "sign_idx": 6, + "start_age": 38.9867, + "years": 0.24 + }, + "md": { + "end_age": 40.0, + "lord": "Venus", + "sign": "Taurus", + "sign_idx": 1, + "start_age": 38.0, + "years": 2 + }, + "pd": { + "end_age": 39.0155, + "lord": "Venus", + "sign": "Libra", + "sign_idx": 6, + "start_age": 38.9867, + "years": 0.0288 + }, + "remaining_years": 0.98 + }, + "vimshottari": { + "antardasha": "Ketu", + "mahadasha": "Venus" + } + }, + "expected_label": "legal_marriage", + "matched_expected_label": false, + "name": "Nicole Kidman", + "outcome": "Married Keith Urban", + "result_class": "miss", + "rule_version": "v2_1", + "score": 3, + "signals": [ + "Venus_domain_karaka", + "double_transit_pac_strong" + ] + }, + "positive_date": "2006-06-25", + "ranking": { + "candidate_count": 5, + "max_control_score": 3, + "positive_rank": 5, + "positive_score": 3, + "reciprocal_rank": 0.2, + "score_margin": 0, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "demi_moore_marriage_1987", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "1987-09-22", + "result_class": "miss", + "score": 0 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1987-10-22", + "result_class": "miss", + "score": 0 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1987-12-21", + "result_class": "miss", + "score": 2 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "1988-01-20", + "result_class": "miss", + "score": 2 + } + ], + "domain": "marriage", + "name": "Demi Moore", + "positive": { + "actual_label": null, + "birth_time_rating": "A", + "blocked": false, + "case_id": "demi_moore_marriage_1987", + "domain": "marriage", + "event_date": "1987-11-21", + "evidence": { + "arudha_lord": "Venus", + "ascendant": { + "degree": 29.0648, + "degree_in_sign": 29.0648, + "degree_in_sign_raw": 329.06483110736514, + "degree_raw": 329.0648, + "lon": 329.0648, + "lord": "Saturn", + "sign": "Aquarius", + "sign_cn": "水瓶座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "11": { + "level": "极吉", + "sav_score": 32, + "sign": "Sagittarius" + }, + "2": { + "level": "中等", + "sav_score": 26, + "sign": "Pisces" + }, + "5": { + "level": "中等", + "sav_score": 27, + "sign": "Gemini" + }, + "7": { + "level": "极吉", + "sav_score": 34, + "sign": "Leo" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 23.6879, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 5, + "sav": 26, + "sign": "Pisces" + }, + "Saturn": { + "bav": 4, + "sav": 27, + "sign": "Scorpio" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "from memory", + "source_grade": "verified_secondary", + "time_accuracy_rating": "A", + "url": "https://www.astro.com/adbvip/adbvip_11_11.htm" + }, + "domain_varga": { + "birth_info": "1962-11-11 14:16", + "divisional_charts": { + "D9_Navamsa": { + "Jupiter": { + "sign": "Sagittarius", + "sign_cn": "射手座" + }, + "Ketu": { + "sign": "Pisces", + "sign_cn": "双鱼座" + }, + "Mars": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Mercury": { + "sign": "Pisces", + "sign_cn": "双鱼座" + }, + "Moon": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "Rahu": { + "sign": "Virgo", + "sign_cn": "处女座" + }, + "Saturn": { + "sign": "Aries", + "sign_cn": "白羊座" + }, + "Sun": { + "sign": "Taurus", + "sign_cn": "金牛座" + }, + "Venus": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "ascendant": "Gemini" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": { + "CL_7宫(Libra)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "CL_Venus(宫主)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + }, + "saturn": {} + }, + "d1": { + "jupiter": { + "7宫(Leo)": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ], + "Sun(宫主)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "Sun(对宫主)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + }, + "saturn": {} + }, + "d9": { + "jupiter": {}, + "saturn": { + "D9_7宫(Sagittarius)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "D9_Jupiter(宫主)": [ + { + "desc": "3宫相位", + "offset": 3, + "type": "Aspect" + } + ] + } + }, + "double_transit": [], + "event_house": 7, + "stats": { + "chandra_lagna": "Aries", + "cl_jupiter_targets": [ + "CL_7宫(Libra)", + "CL_Venus(宫主)" + ], + "cl_overlap": [], + "cl_saturn_targets": [], + "d1_jupiter_targets": [ + "7宫(Leo)", + "Sun(宫主)", + "Sun(对宫主)" + ], + "d1_overlap": [], + "d1_saturn_targets": [], + "d9_ascendant": "Gemini", + "d9_jupiter_targets": [], + "d9_overlap": [], + "d9_saturn_targets": [ + "D9_7宫(Sagittarius)", + "D9_Jupiter(宫主)" + ], + "event_lord_d9_sign": "Taurus" + }, + "summary": "❌ 无 Double Transit PAC 激活", + "transit_date": "1987-11-21" + }, + "event_source": { + "source_grade": "verified_secondary", + "url": "https://en.wikipedia.org/wiki/Demi_Moore" + }, + "functional_benefic_malefic": { + "ascendant": "Aquarius", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_malefics": [ + "Jupiter", + "Mars", + "Moon" + ], + "functional_neutrals": [ + "Sun" + ], + "owned_houses": { + "Jupiter": [ + 2, + 11 + ], + "Mars": [ + 3, + 10 + ], + "Mercury": [ + 5, + 8 + ], + "Moon": [ + 6 + ], + "Saturn": [ + 1, + 12 + ], + "Sun": [ + 7 + ], + "Venus": [ + 4, + 9 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Saturn", + "Venus" + ] + }, + "narayana": { + "ad": { + "end_age": 25.3125, + "lord": "Venus", + "sign": "Taurus", + "sign_idx": 1, + "start_age": 25.0, + "years": 0.3125 + }, + "md": { + "end_age": 30.0, + "lord": "Venus", + "sign": "Taurus", + "sign_idx": 1, + "start_age": 25.0, + "years": 5 + }, + "pd": { + "end_age": 25.0352, + "lord": "Mercury", + "sign": "Gemini", + "sign_idx": 2, + "start_age": 25.0195, + "years": 0.0156 + }, + "remaining_years": 4.97 + }, + "vimshottari": { + "antardasha": "Moon", + "mahadasha": "Mars" + } + }, + "expected_label": "legal_marriage", + "matched_expected_label": false, + "name": "Demi Moore", + "outcome": "Married Bruce Willis", + "result_class": "miss", + "rule_version": "v2_1", + "score": 0, + "signals": [] + }, + "positive_date": "1987-11-21", + "ranking": { + "candidate_count": 5, + "max_control_score": 2, + "positive_rank": 5, + "positive_score": 0, + "reciprocal_rank": 0.2, + "score_margin": -2, + "top_1": false, + "top_3": false + } + }, + { + "case_id": "chelsea_clinton_marriage_2010", + "controls": [ + { + "blocked": false, + "blocked_reason": null, + "date": "2010-06-01", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2010-07-01", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2010-08-30", + "result_class": "weak_hit", + "score": 5 + }, + { + "blocked": false, + "blocked_reason": null, + "date": "2010-09-29", + "result_class": "weak_hit", + "score": 5 + } + ], + "domain": "marriage", + "name": "Chelsea Clinton", + "positive": { + "actual_label": "domain_activation", + "birth_time_rating": "AA", + "blocked": false, + "case_id": "chelsea_clinton_marriage_2010", + "domain": "marriage", + "event_date": "2010-07-31", + "evidence": { + "arudha_lord": "Moon", + "ascendant": { + "degree": 22.7703, + "degree_in_sign": 22.7703, + "degree_in_sign_raw": 202.7702714237087, + "degree_raw": 202.7703, + "lon": 202.7703, + "lord": "Venus", + "sign": "Libra", + "sign_cn": "天秤座" + }, + "ashtakavarga_audit": { + "all_bav_valid": true, + "boundary": "Audit evidence only. SAV/BAV does not change V2.1 event scores until a fresh holdout validates it.", + "event_house_sav": { + "11": { + "level": "中等", + "sav_score": 26, + "sign": "Leo" + }, + "2": { + "level": "极吉", + "sav_score": 30, + "sign": "Scorpio" + }, + "5": { + "level": "挑战", + "sav_score": 22, + "sign": "Aquarius" + }, + "7": { + "level": "挑战", + "sav_score": 24, + "sign": "Aries" + } + }, + "method": "Ashtakavarga八分法(BPHS/PVR书例校准v2.1)", + "sav_total": 337, + "sav_valid": true, + "scoring_effect": 0, + "settings": { + "ayanamsa": 24.0049, + "node_mode": "mean" + }, + "status": "used_non_scoring", + "transit_support": { + "Jupiter": { + "bav": 6, + "sav": 26, + "sign": "Pisces" + }, + "Saturn": { + "bav": 3, + "sav": 25, + "sign": "Virgo" + } + }, + "version": "2.1" + }, + "birth_source": { + "evidence_basis": "BC/BR in hand", + "source_grade": "primary", + "time_accuracy_rating": "AA", + "url": "https://www.astro.com/adbvip/adbvip_02_27.htm" + }, + "domain_varga": { + "birth_info": "1980-02-27 23:24", + "divisional_charts": { + "D9_Navamsa": { + "Jupiter": { + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "Ketu": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "Mars": { + "sign": "Cancer", + "sign_cn": "巨蟹座" + }, + "Mercury": { + "sign": "Gemini", + "sign_cn": "双子座" + }, + "Moon": { + "sign": "Scorpio", + "sign_cn": "天蝎座" + }, + "Rahu": { + "sign": "Taurus", + "sign_cn": "金牛座" + }, + "Saturn": { + "sign": "Capricorn", + "sign_cn": "摩羯座" + }, + "Sun": { + "sign": "Aquarius", + "sign_cn": "水瓶座" + }, + "Venus": { + "sign": "Pisces", + "sign_cn": "双鱼座" + }, + "ascendant": "Aries" + } + } + }, + "double_transit_pac": { + "cl": { + "jupiter": {}, + "saturn": { + "CL_Saturn(宫主)": [ + { + "desc": "同宫(3宫)", + "type": "Position" + }, + { + "desc": "合相(5.63°)", + "type": "Conjunction" + } + ] + } + }, + "d1": { + "jupiter": { + "Mars(宫主)": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ], + "Mars(对宫主)": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ], + "Venus(LL)": [ + { + "desc": "同宫(6宫)", + "type": "Position" + } + ] + }, + "saturn": { + "7宫(Aries)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ] + } + }, + "d9": { + "jupiter": { + "D9_Venus(宫主)": [ + { + "desc": "同宫(12宫)", + "type": "Position" + } + ], + "Venus_D9(Pisces)": [ + { + "desc": "同宫(12宫)", + "type": "Position" + }, + { + "desc": "合相(5.71°)", + "type": "Conjunction" + } + ] + }, + "saturn": { + "D9_7宫(Libra)": [ + { + "desc": "7宫相位", + "offset": 7, + "type": "Aspect" + } + ], + "Mars_D9(Cancer)": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ] + } + }, + "double_transit": [ + { + "jupiter_pac": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ], + "layer": "D1+D9", + "saturn_pac": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "strength": "moderate", + "target": "Jupiter(D1)Mars(宫主) + Saturn(D9)Mars_D9(Cancer)" + }, + { + "jupiter_pac": [ + { + "desc": "5宫相位", + "offset": 5, + "type": "Aspect" + } + ], + "layer": "D1+D9", + "saturn_pac": [ + { + "desc": "10宫相位", + "offset": 10, + "type": "Aspect" + } + ], + "strength": "moderate", + "target": "Jupiter(D1)Mars(对宫主) + Saturn(D9)Mars_D9(Cancer)" + } + ], + "event_house": 7, + "stats": { + "chandra_lagna": "Cancer", + "cl_jupiter_targets": [], + "cl_overlap": [], + "cl_saturn_targets": [ + "CL_Saturn(宫主)" + ], + "d1_jupiter_targets": [ + "Mars(宫主)", + "Mars(对宫主)", + "Venus(LL)" + ], + "d1_overlap": [], + "d1_saturn_targets": [ + "7宫(Aries)" + ], + "d9_ascendant": "Aries", + "d9_jupiter_targets": [ + "D9_Venus(宫主)", + "Venus_D9(Pisces)" + ], + "d9_overlap": [], + "d9_saturn_targets": [ + "D9_7宫(Libra)", + "Mars_D9(Cancer)" + ], + "event_lord_d9_sign": "Cancer" + }, + "summary": "⚠️ 跨层间接 Double Transit (D1+D9),需结合 Dasha 确认", + "transit_date": "2010-07-31" + }, + "event_source": { + "source_grade": "verified_secondary", + "url": "https://en.wikipedia.org/wiki/Chelsea_Clinton" + }, + "functional_benefic_malefic": { + "ascendant": "Libra", + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "functional_benefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_malefics": [ + "Jupiter", + "Sun" + ], + "functional_neutrals": [ + "Mars", + "Moon" + ], + "owned_houses": { + "Jupiter": [ + 3, + 6 + ], + "Mars": [ + 2, + 7 + ], + "Mercury": [ + 9, + 12 + ], + "Moon": [ + 10 + ], + "Saturn": [ + 4, + 5 + ], + "Sun": [ + 11 + ], + "Venus": [ + 1, + 8 + ] + }, + "source": "strict_functional_benefic_malefic_v1", + "status": "used", + "yogakarakas": [ + "Saturn", + "Venus" + ] + }, + "narayana": { + "ad": { + "end_age": 30.5632, + "lord": "Saturn", + "sign": "Aquarius", + "sign_idx": 10, + "start_age": 30.0, + "years": 0.5632 + }, + "md": { + "end_age": 37.0, + "lord": "Saturn", + "sign": "Aquarius", + "sign_idx": 10, + "start_age": 30.0, + "years": 7 + }, + "pd": { + "end_age": 30.4596, + "lord": "Mars", + "sign": "Scorpio", + "sign_idx": 7, + "start_age": 30.4014, + "years": 0.0583 + }, + "remaining_years": 6.58 + }, + "vimshottari": { + "antardasha": "Moon", + "mahadasha": "Venus" + } + }, + "expected_label": "legal_marriage", + "matched_expected_label": false, + "name": "Chelsea Clinton", + "outcome": "Married Marc Mezvinsky", + "result_class": "weak_hit", + "rule_version": "v2_1", + "score": 5, + "signals": [ + "Venus_domain_karaka", + "active_dasha_matches_D9_7L:Venus", + "active_dasha_matches_UL_lord:Moon", + "narayana_lord_owns_event_house:Saturn", + "double_transit_pac_present" + ] + }, + "positive_date": "2010-07-31", + "ranking": { + "candidate_count": 5, + "max_control_score": 5, + "positive_rank": 5, + "positive_score": 5, + "reciprocal_rank": 0.2, + "score_margin": 0, + "top_1": false, + "top_3": false + } + } + ], + "control_offsets_days": [ + -60, + -30, + 30, + 60 + ], + "rule_version": "v2_1", + "summary": { + "balanced_accuracy": null, + "balanced_accuracy_blocked_reason": "controls_are_non_target_dates_not_independently_adjudicated_all-domain_non_events", + "case_count": 10, + "control_activation_rate": 0.8, + "control_date_count": 40, + "control_strong_activation_rate": 0.2, + "mean_reciprocal_rank": 0.2, + "mean_score_margin": -0.6, + "positive_top_1_rate": 0.0, + "positive_top_3_rate": 0.0, + "ranked_case_count": 10, + "specificity_proxy": 0.19999999999999996, + "strong_specificity_proxy": 0.8, + "timing_precision_gate": { + "positive_top_3_minimum": 0.6, + "reason": "positive_dates_do_not_rank_above_controls_with_required_specificity", + "specificity_proxy_minimum": 0.6, + "status": "blocked" + } + } +} diff --git a/references/evidence_manifests/commercial_external_validation_release.v1.json b/references/evidence_manifests/commercial_external_validation_release.v1.json index 53b4e37b..3310abb2 100644 --- a/references/evidence_manifests/commercial_external_validation_release.v1.json +++ b/references/evidence_manifests/commercial_external_validation_release.v1.json @@ -97,7 +97,7 @@ { "id": "high_rigor_local_raw", "path": "references/oracle/artifacts/local_steve_jobs_high_rigor_raw.json", - "sha256": "8361cac2831404a005e6be5c927b9cd610cfc0787ca17a547e81ae9a4d601746", + "sha256": "87a0f176629403d2bc47e08fef28f7ce8118efa4786e11604bc7141af6724b38", "scope": "public same-chart local high-rigor raw output" }, { @@ -109,7 +109,7 @@ { "id": "high_rigor_jyotishganit_raw", "path": "references/oracle/artifacts/jyotishganit_steve_jobs_high_rigor_raw.json", - "sha256": "5cbb85f6cd9210558d496c350b45aa1dc2785ab3f49a800a884b45c76c49e6a1", + "sha256": "b3a13f446ceacb2b57905692e7d2de629d9d3326929c73912a110e99deeca28e", "scope": "public same-chart jyotishganit high-rigor raw output" }, { diff --git a/references/oracle/artifacts/jyotishganit_steve_jobs_high_rigor_raw.json b/references/oracle/artifacts/jyotishganit_steve_jobs_high_rigor_raw.json index 1c10dc9e..c97b0b0c 100644 --- a/references/oracle/artifacts/jyotishganit_steve_jobs_high_rigor_raw.json +++ b/references/oracle/artifacts/jyotishganit_steve_jobs_high_rigor_raw.json @@ -198,6 +198,14 @@ "@type": "PlanetPosition", "aspects": { "gives": [ + { + "aspect_type": "3", + "to_planet": "Rahu" + }, + { + "aspect_type": "7", + "to_house": 9 + }, { "aspect_type": "7", "to_planet": "Mars" @@ -206,24 +214,20 @@ "aspect_type": "10", "to_house": 12 }, - { - "aspect_type": "7", - "to_house": 9 - }, { "aspect_type": "3", "to_house": 5 }, - { - "aspect_type": "3", - "to_planet": "Rahu" - }, { "aspect_type": "3", "to_planet": "Venus" } ], "receives": [ + { + "aspect_type": "7", + "from_planet": "Mars" + }, { "aspect_type": "5", "from_planet": "Ketu" @@ -231,10 +235,6 @@ { "aspect_type": "5", "from_planet": "Jupiter" - }, - { - "aspect_type": "7", - "from_planet": "Mars" } ] }, @@ -344,7 +344,7 @@ "gives": [ { "aspect_type": "7", - "to_planet": "Jupiter" + "to_house": 11 }, { "aspect_type": "7", @@ -352,17 +352,17 @@ }, { "aspect_type": "7", - "to_house": 11 + "to_planet": "Jupiter" } ], "receives": [ - { - "aspect_type": "7", - "from_planet": "Jupiter" - }, { "aspect_type": "3", "from_planet": "Saturn" + }, + { + "aspect_type": "7", + "from_planet": "Jupiter" } ] }, @@ -427,6 +427,10 @@ "@type": "PlanetPosition", "aspects": { "gives": [ + { + "aspect_type": "5", + "to_planet": "Mars" + }, { "aspect_type": "9", "to_house": 1 @@ -434,20 +438,16 @@ { "aspect_type": "5", "to_house": 9 - }, - { - "aspect_type": "5", - "to_planet": "Mars" } ], "receives": [ - { - "aspect_type": "7", - "from_planet": "Jupiter" - }, { "aspect_type": "3", "from_planet": "Saturn" + }, + { + "aspect_type": "7", + "from_planet": "Jupiter" } ] }, @@ -605,11 +605,11 @@ "receives": [ { "aspect_type": "9", - "from_planet": "Jupiter" + "from_planet": "Ketu" }, { "aspect_type": "9", - "from_planet": "Ketu" + "from_planet": "Jupiter" } ] }, @@ -781,6 +781,10 @@ "aspect_type": "7", "to_house": 3 }, + { + "aspect_type": "7", + "to_planet": "Saturn" + }, { "aspect_type": "8", "to_house": 4 @@ -788,10 +792,6 @@ { "aspect_type": "4", "to_house": 12 - }, - { - "aspect_type": "7", - "to_planet": "Saturn" } ], "receives": [ @@ -904,29 +904,29 @@ "aspect_type": "7", "to_planet": "Rahu" }, - { - "aspect_type": "7", - "to_planet": "Venus" - }, { "aspect_type": "5", "to_house": 3 }, + { + "aspect_type": "9", + "to_house": 7 + }, { "aspect_type": "5", "to_planet": "Saturn" }, { "aspect_type": "9", - "to_house": 7 + "to_planet": "Sun" }, { "aspect_type": "7", "to_house": 5 }, { - "aspect_type": "9", - "to_planet": "Sun" + "aspect_type": "7", + "to_planet": "Venus" } ], "receives": [ @@ -1001,8 +1001,8 @@ "aspects": { "gives": [ { - "aspect_type": "5", - "to_house": 3 + "aspect_type": "9", + "to_house": 7 }, { "aspect_type": "9", @@ -1010,11 +1010,11 @@ }, { "aspect_type": "5", - "to_planet": "Saturn" + "to_house": 3 }, { - "aspect_type": "9", - "to_house": 7 + "aspect_type": "5", + "to_planet": "Saturn" } ], "receives": [ diff --git a/references/oracle/artifacts/local_steve_jobs_high_rigor_raw.json b/references/oracle/artifacts/local_steve_jobs_high_rigor_raw.json index 48a440ab..5dd86d16 100644 --- a/references/oracle/artifacts/local_steve_jobs_high_rigor_raw.json +++ b/references/oracle/artifacts/local_steve_jobs_high_rigor_raw.json @@ -257,7 +257,7 @@ "label": "Steve Jobs public AA", "module_health": { "empty_modules": [], - "module_count": 55, + "module_count": 56, "validation": { "checked": 11, "failed": 0, @@ -418,70 +418,70 @@ "privacy": "public", "sample_id": "steve_jobs_public_aa", "shadbala": { - "Jupiter": null, - "Mars": null, - "Mercury": null, - "Moon": null, - "Saturn": null, - "Sun": null, - "Venus": null + "Jupiter": 569.4, + "Mars": 456.19, + "Mercury": 365.28, + "Moon": 584.26, + "Saturn": 430.05, + "Sun": 480.62, + "Venus": 406.93 }, "shadbala_components": { "Jupiter": { - "chesta": null, - "dig": null, - "drik": null, - "kala": null, - "naisargika": null, - "sthana": null + "chesta": 46.49, + "dig": 80.59, + "drik": 6.9, + "kala": 199.32, + "naisargika": 34.29, + "sthana": 201.81 }, "Mars": { - "chesta": null, - "dig": null, - "drik": null, - "kala": null, - "naisargika": null, - "sthana": null + "chesta": 21.6, + "dig": 77.41, + "drik": 13.49, + "kala": 127.92, + "naisargika": 17.14, + "sthana": 198.63 }, "Mercury": { - "chesta": null, - "dig": null, - "drik": null, - "kala": null, - "naisargika": null, - "sthana": null + "chesta": 47.8, + "dig": 12.64, + "drik": -10.62, + "kala": 121.79, + "naisargika": 25.71, + "sthana": 167.96 }, "Moon": { - "chesta": null, - "dig": null, - "drik": null, - "kala": null, - "naisargika": null, - "sthana": null + "chesta": 21.34, + "dig": 95.48, + "drik": 20.06, + "kala": 149.61, + "naisargika": 51.43, + "sthana": 246.34 }, "Saturn": { - "chesta": null, - "dig": null, - "drik": null, - "kala": null, - "naisargika": null, - "sthana": null + "chesta": 36.99, + "dig": 19.63, + "drik": 9.49, + "kala": 136.76, + "naisargika": 8.57, + "sthana": 218.61 }, "Sun": { - "chesta": null, - "dig": null, - "drik": null, - "kala": null, - "naisargika": null, - "sthana": null + "chesta": 36.0, + "dig": 24.81, + "drik": 1.74, + "kala": 140.98, + "naisargika": 60.0, + "sthana": 217.09 }, "Venus": { - "chesta": null, - "dig": null, - "drik": null, - "kala": null, - "naisargika": null, - "sthana": null + "chesta": 29.36, + "dig": 69.95, + "drik": -2.75, + "kala": 113.45, + "naisargika": 42.86, + "sthana": 154.06 } }, "shadbala_method_variants": { diff --git a/references/oracle/three_engine_parity_replay_manifest.json b/references/oracle/three_engine_parity_replay_manifest.json index 0b46a3e3..080cce97 100644 --- a/references/oracle/three_engine_parity_replay_manifest.json +++ b/references/oracle/three_engine_parity_replay_manifest.json @@ -894,7 +894,7 @@ }, { "field": "Sun", - "local_value": null, + "local_value": 480.62, "oracle_values": { "PyJHora_JHora": 444.63, "VedAstro": 395.06, @@ -905,7 +905,7 @@ }, { "field": "Sun.sthana", - "local_value": null, + "local_value": 217.09, "oracle_values": { "PyJHora_JHora": 217.09, "VedAstro": 202.0874074074074, @@ -916,7 +916,7 @@ }, { "field": "Sun.kala", - "local_value": null, + "local_value": 140.98, "oracle_values": { "PyJHora_JHora": 140.99, "VedAstro": 128.0507461419753, @@ -927,7 +927,7 @@ }, { "field": "Sun.dig", - "local_value": null, + "local_value": 24.81, "oracle_values": { "PyJHora_JHora": 24.81, "VedAstro": 24.810925925925925, @@ -938,7 +938,7 @@ }, { "field": "Sun.chesta", - "local_value": null, + "local_value": 36.0, "method_conflict": "PyJHora unbounded; VedAstro/jyotishganit bounded; Sun/Moon treatment differs across engines.", "oracle_values": { "PyJHora_JHora": 0.0, @@ -950,18 +950,18 @@ }, { "field": "Sun.naisargika", - "local_value": null, + "local_value": 60.0, "oracle_values": { "PyJHora_JHora": 60.0, "VedAstro": 60.0, "jyotishganit": 60.0 }, "section": "shadbala_components", - "status": "mismatch" + "status": "match" }, { "field": "Sun.drik", - "local_value": null, + "local_value": 1.74, "oracle_values": { "PyJHora_JHora": 1.74, "VedAstro": -19.891041666666666, @@ -972,7 +972,7 @@ }, { "field": "Moon", - "local_value": null, + "local_value": 584.26, "oracle_values": { "PyJHora_JHora": 562.89, "VedAstro": 421.8, @@ -983,7 +983,7 @@ }, { "field": "Moon.sthana", - "local_value": null, + "local_value": 246.34, "oracle_values": { "PyJHora_JHora": 246.34, "VedAstro": 236.69703703703703, @@ -994,7 +994,7 @@ }, { "field": "Moon.kala", - "local_value": null, + "local_value": 149.61, "oracle_values": { "PyJHora_JHora": 149.58, "VedAstro": 159.53537962962963, @@ -1005,7 +1005,7 @@ }, { "field": "Moon.dig", - "local_value": null, + "local_value": 95.48, "oracle_values": { "PyJHora_JHora": 95.48, "VedAstro": 52.26824074074074, @@ -1016,7 +1016,7 @@ }, { "field": "Moon.chesta", - "local_value": null, + "local_value": 21.34, "method_conflict": "PyJHora unbounded; VedAstro/jyotishganit bounded; Sun/Moon treatment differs across engines.", "oracle_values": { "PyJHora_JHora": 0.0, @@ -1028,18 +1028,18 @@ }, { "field": "Moon.naisargika", - "local_value": null, + "local_value": 51.43, "oracle_values": { "PyJHora_JHora": 51.43, "VedAstro": 51.43, "jyotishganit": 51.43 }, "section": "shadbala_components", - "status": "mismatch" + "status": "match" }, { "field": "Moon.drik", - "local_value": null, + "local_value": 20.06, "oracle_values": { "PyJHora_JHora": 20.06, "VedAstro": -18.131319444444447, @@ -1050,7 +1050,7 @@ }, { "field": "Mars", - "local_value": null, + "local_value": 456.19, "oracle_values": { "PyJHora_JHora": 533.18, "VedAstro": 397.89, @@ -1061,7 +1061,7 @@ }, { "field": "Mars.sthana", - "local_value": null, + "local_value": 198.63, "oracle_values": { "PyJHora_JHora": 198.63, "VedAstro": 221.28777777777776, @@ -1072,7 +1072,7 @@ }, { "field": "Mars.kala", - "local_value": null, + "local_value": 127.92, "oracle_values": { "PyJHora_JHora": 127.93, "VedAstro": 148.2544363425926, @@ -1083,7 +1083,7 @@ }, { "field": "Mars.dig", - "local_value": null, + "local_value": 77.41, "oracle_values": { "PyJHora_JHora": 77.41, "VedAstro": 2.3666666666666667, @@ -1094,7 +1094,7 @@ }, { "field": "Mars.chesta", - "local_value": null, + "local_value": 21.6, "method_conflict": "PyJHora unbounded; VedAstro/jyotishganit bounded; Sun/Moon treatment differs across engines.", "oracle_values": { "PyJHora_JHora": 98.58, @@ -1106,18 +1106,18 @@ }, { "field": "Mars.naisargika", - "local_value": null, + "local_value": 17.14, "oracle_values": { "PyJHora_JHora": 17.14, "VedAstro": 17.14, "jyotishganit": 17.14 }, "section": "shadbala_components", - "status": "mismatch" + "status": "match" }, { "field": "Mars.drik", - "local_value": null, + "local_value": 13.49, "oracle_values": { "PyJHora_JHora": 13.49, "VedAstro": -12.978854166666672, @@ -1128,7 +1128,7 @@ }, { "field": "Mercury", - "local_value": null, + "local_value": 365.28, "oracle_values": { "PyJHora_JHora": 363.24, "VedAstro": 376.04, @@ -1139,7 +1139,7 @@ }, { "field": "Mercury.sthana", - "local_value": null, + "local_value": 167.96, "oracle_values": { "PyJHora_JHora": 167.96, "VedAstro": 182.95805555555555, @@ -1150,7 +1150,7 @@ }, { "field": "Mercury.kala", - "local_value": null, + "local_value": 121.79, "oracle_values": { "PyJHora_JHora": 121.78, "VedAstro": 126.59104166666665, @@ -1161,7 +1161,7 @@ }, { "field": "Mercury.dig", - "local_value": null, + "local_value": 12.64, "oracle_values": { "PyJHora_JHora": 12.64, "VedAstro": 12.643148148148148, @@ -1172,7 +1172,7 @@ }, { "field": "Mercury.chesta", - "local_value": null, + "local_value": 47.8, "method_conflict": "PyJHora unbounded; VedAstro/jyotishganit bounded; Sun/Moon treatment differs across engines.", "oracle_values": { "PyJHora_JHora": 45.78, @@ -1184,18 +1184,18 @@ }, { "field": "Mercury.naisargika", - "local_value": null, + "local_value": 25.71, "oracle_values": { "PyJHora_JHora": 25.71, "VedAstro": 25.7, "jyotishganit": 25.71 }, "section": "shadbala_components", - "status": "mismatch" + "status": "match" }, { "field": "Mercury.drik", - "local_value": null, + "local_value": -10.62, "oracle_values": { "PyJHora_JHora": -10.63, "VedAstro": -19.363888888888884, @@ -1206,7 +1206,7 @@ }, { "field": "Jupiter", - "local_value": null, + "local_value": 569.4, "oracle_values": { "PyJHora_JHora": 596.89, "VedAstro": 427.22, @@ -1217,7 +1217,7 @@ }, { "field": "Jupiter.sthana", - "local_value": null, + "local_value": 201.81, "oracle_values": { "PyJHora_JHora": 201.8, "VedAstro": 213.06314814814814, @@ -1228,7 +1228,7 @@ }, { "field": "Jupiter.kala", - "local_value": null, + "local_value": 199.32, "oracle_values": { "PyJHora_JHora": 199.31, "VedAstro": 141.64764506172838, @@ -1239,7 +1239,7 @@ }, { "field": "Jupiter.dig", - "local_value": null, + "local_value": 80.59, "oracle_values": { "PyJHora_JHora": 80.6, "VedAstro": 6.773333333333333, @@ -1250,7 +1250,7 @@ }, { "field": "Jupiter.chesta", - "local_value": null, + "local_value": 46.49, "method_conflict": "PyJHora unbounded; VedAstro/jyotishganit bounded; Sun/Moon treatment differs across engines.", "oracle_values": { "PyJHora_JHora": 74.0, @@ -1262,18 +1262,18 @@ }, { "field": "Jupiter.naisargika", - "local_value": null, + "local_value": 34.29, "oracle_values": { "PyJHora_JHora": 34.29, "VedAstro": 34.28, "jyotishganit": 34.29 }, "section": "shadbala_components", - "status": "mismatch" + "status": "match" }, { "field": "Jupiter.drik", - "local_value": null, + "local_value": 6.9, "oracle_values": { "PyJHora_JHora": 6.89, "VedAstro": -14.818125000000006, @@ -1284,7 +1284,7 @@ }, { "field": "Venus", - "local_value": null, + "local_value": 406.93, "oracle_values": { "PyJHora_JHora": 408.64, "VedAstro": 402.56, @@ -1295,7 +1295,7 @@ }, { "field": "Venus.sthana", - "local_value": null, + "local_value": 154.06, "oracle_values": { "PyJHora_JHora": 154.06, "VedAstro": 210.05953703703705, @@ -1306,7 +1306,7 @@ }, { "field": "Venus.kala", - "local_value": null, + "local_value": 113.45, "oracle_values": { "PyJHora_JHora": 113.44, "VedAstro": 97.43954166666667, @@ -1317,7 +1317,7 @@ }, { "field": "Venus.dig", - "local_value": null, + "local_value": 69.95, "oracle_values": { "PyJHora_JHora": 69.95, "VedAstro": 29.630740740740737, @@ -1328,7 +1328,7 @@ }, { "field": "Venus.chesta", - "local_value": null, + "local_value": 29.36, "method_conflict": "PyJHora unbounded; VedAstro/jyotishganit bounded; Sun/Moon treatment differs across engines.", "oracle_values": { "PyJHora_JHora": 31.08, @@ -1340,18 +1340,18 @@ }, { "field": "Venus.naisargika", - "local_value": null, + "local_value": 42.86, "oracle_values": { "PyJHora_JHora": 42.86, "VedAstro": 42.85, "jyotishganit": 42.86 }, "section": "shadbala_components", - "status": "mismatch" + "status": "match" }, { "field": "Venus.drik", - "local_value": null, + "local_value": -2.75, "oracle_values": { "PyJHora_JHora": -2.75, "VedAstro": -8.51038194444445, @@ -1362,7 +1362,7 @@ }, { "field": "Saturn", - "local_value": null, + "local_value": 430.05, "oracle_values": { "PyJHora_JHora": 429.42, "VedAstro": 448.58, @@ -1373,7 +1373,7 @@ }, { "field": "Saturn.sthana", - "local_value": null, + "local_value": 218.61, "oracle_values": { "PyJHora_JHora": 218.61, "VedAstro": 239.23268518518518, @@ -1384,7 +1384,7 @@ }, { "field": "Saturn.kala", - "local_value": null, + "local_value": 136.76, "oracle_values": { "PyJHora_JHora": 136.77, "VedAstro": 140.7160763888889, @@ -1395,7 +1395,7 @@ }, { "field": "Saturn.dig", - "local_value": null, + "local_value": 19.63, "oracle_values": { "PyJHora_JHora": 19.62, "VedAstro": 19.623796296296295, @@ -1406,7 +1406,7 @@ }, { "field": "Saturn.chesta", - "local_value": null, + "local_value": 36.99, "method_conflict": "PyJHora unbounded; VedAstro/jyotishganit bounded; Sun/Moon treatment differs across engines.", "oracle_values": { "PyJHora_JHora": 36.36, @@ -1418,18 +1418,18 @@ }, { "field": "Saturn.naisargika", - "local_value": null, + "local_value": 8.57, "oracle_values": { "PyJHora_JHora": 8.57, "VedAstro": 8.57, "jyotishganit": 8.57 }, "section": "shadbala_components", - "status": "mismatch" + "status": "match" }, { "field": "Saturn.drik", - "local_value": null, + "local_value": 9.49, "oracle_values": { "PyJHora_JHora": 9.49, "VedAstro": 0.9979513888888878, @@ -1482,7 +1482,7 @@ "status": "official_verified" }, "jyotishganit": { - "artifact_hash": "5cbb85f6cd9210558d496c350b45aa1dc2785ab3f49a800a884b45c76c49e6a1", + "artifact_hash": "b3a13f446ceacb2b57905692e7d2de629d9d3326929c73912a110e99deeca28e", "raw_output_path": "artifacts/jyotishganit_steve_jobs_high_rigor_raw.json", "settings": { "ayanamsa": { diff --git a/references/oracle/vedastro_official_source_contract_2026_07_17.json b/references/oracle/vedastro_official_source_contract_2026_07_17.json new file mode 100644 index 00000000..a1fcf9f0 --- /dev/null +++ b/references/oracle/vedastro_official_source_contract_2026_07_17.json @@ -0,0 +1,29 @@ +{ + "checks": { + "all_planet_longitude_is_nirayana": true, + "mit_license": true, + "offset_parse_exact": true, + "time_keeps_offset": true, + "zero_offset_auto_lookup": true + }, + "deployment_identity_reason": "Remote responses expose neither library version nor source commit.", + "deployment_identity_status": "blocked", + "files": { + "Library/Data/Time.cs": "6cd9bbe98afd072b665ad85ad71bdd7be89baf45f9767cae4907b09377037da3", + "Library/Library.csproj": "d74bc184a225c77247c29ee74542f3ba4daf67912d32b587da7a30a3aa78a2b2", + "Library/Logic/Calculate/Core.cs": "105ee6d0caeb0cb02057193cf68d74cef756e4d111dfdfd82c62db5a0c76b187", + "Library/Logic/Tools.cs": "65fb680facaf3281b07ad73b523f10c347378d4a333be81fb2399a333100d668" + }, + "library_version": "1.2.0", + "longitude_contract": { + "AllPlanetLongitude": "nirayana" + }, + "source": "https://github.com/VedAstro/VedAstro", + "source_commit": "1f3a46482ab98eb414ab03fa44496a37d35a3a96", + "source_contract_status": "verified", + "timezone_contract": { + "conclusion": "+00:00 and the location's real offset may intentionally produce identical results.", + "negative_offset": "literal_offset", + "zero_offset": "auto_lookup_sentinel" + } +} diff --git a/scripts/jyotish_api_server.py b/scripts/jyotish_api_server.py index 36acd00a..4ecb3d30 100644 --- a/scripts/jyotish_api_server.py +++ b/scripts/jyotish_api_server.py @@ -6291,7 +6291,7 @@ class JyotishAPIHandler(BaseHTTPRequestHandler): lon = self._get_float(body, 'lon', 0, -180, 180) tz = self._parse_timezone(body, lat, lon, year, month, day, birth_hour, birth_minute, birth_second) jd = swe.julday(year, month, day, birth_hour_decimal - tz) - context = shadbala_module.build_shadbala_context(jd, lat, lon, body.get('ayanamsa', 'lahiri')) + context = shadbala_module.build_shadbala_context(jd, lat, lon, body.get('ayanamsa', 'lahiri'), tz) result = shadbala_module.calc_shadbala( planets, SIGNS[asc_sign_idx], diff --git a/scripts/jyotish_engine.py b/scripts/jyotish_engine.py index 1f32b987..088fbb76 100644 --- a/scripts/jyotish_engine.py +++ b/scripts/jyotish_engine.py @@ -3364,7 +3364,7 @@ def cmd_shadbala(args): birth_hour = _birth_hour_decimal(args.hour, args.minute, _arg_second(args)) sun_lon = planets.get("Sun", {}).get("degree", 0) moon_lon = planets.get("Moon", {}).get("degree", 0) - context = build_shadbala_context(jd, args.lat, args.lon, _current_ayanamsa_name(args)) + context = build_shadbala_context(jd, args.lat, args.lon, _current_ayanamsa_name(args), args.tz) return calc_shadbala(planets, asc_sign, birth_hour, sun_lon, moon_lon, context=context) @@ -3757,7 +3757,7 @@ def cmd_audit(args): birth_hour = _birth_hour_decimal(args.hour, args.minute, _arg_second(args)) sun_lon = planets.get('Sun', {}).get('degree', 0) moon_lon = planets.get('Moon', {}).get('degree', 0) - context = build_shadbala_context(jd, args.lat, args.lon, _current_ayanamsa_name(args)) + context = build_shadbala_context(jd, args.lat, args.lon, _current_ayanamsa_name(args), args.tz) shadbala = calc_shadbala(planets, asc_sign, birth_hour, sun_lon, moon_lon, context=context) report['audit']['P9_shadbala'] = { 'summary': shadbala.get('summary', {}), @@ -5522,10 +5522,11 @@ def cmd_full_reading(args): # ── Step 10: Shadbala六重力量 ── try: - from shadbala import calc_shadbala + from shadbala import build_shadbala_context, calc_shadbala birth_hour = _birth_hour_decimal(args.hour, args.minute, _arg_second(args)) sun_lon = planet_lons.get('Sun', 0) moon_lon = planet_lons.get('Moon', 0) + context = build_shadbala_context(jd, args.lat, args.lon, _current_ayanamsa_name(args), args.tz) shadbala_result = calc_shadbala(planets, asc_sign, birth_hour, sun_lon, moon_lon, context=context) # 添加顶层汇总 if isinstance(shadbala_result, dict): diff --git a/scripts/public_real_case_negative_controls.py b/scripts/public_real_case_negative_controls.py index dd1e0b00..6474b8e1 100644 --- a/scripts/public_real_case_negative_controls.py +++ b/scripts/public_real_case_negative_controls.py @@ -17,6 +17,10 @@ ROOT = Path(__file__).resolve().parents[1] DEFAULT_OFFSETS = (-120, -90, -60, -30, 30, 60, 90, 120) +def parse_offsets(raw: str) -> tuple[int, ...]: + return tuple(dict.fromkeys(value for value in (int(item.strip()) for item in raw.split(",")) if value != 0)) + + def generate_control_dates(event_date: str, offsets: Iterable[int] = DEFAULT_OFFSETS) -> list[str]: target = date.fromisoformat(event_date) return [(target + timedelta(days=int(offset))).isoformat() for offset in offsets if int(offset) != 0] @@ -41,16 +45,36 @@ def summarize_negative_control_rows(rows: list[dict[str, Any]]) -> dict[str, Any controls = [control for row in rows for control in row.get("controls") or [] if not control.get("blocked")] rankings = [row["ranking"] for row in rows if row.get("ranking")] margins = [item["score_margin"] for item in rankings if item["score_margin"] is not None] + control_activation_rate = sum((control.get("score") or 0) >= 4 for control in controls) / len(controls) if controls else None + control_strong_activation_rate = sum((control.get("score") or 0) >= 7 for control in controls) / len(controls) if controls else None + positive_top_1_rate = sum(item["top_1"] for item in rankings) / len(rankings) if rankings else None + positive_top_3_rate = sum(item["top_3"] for item in rankings) / len(rankings) if rankings else None + specificity_proxy = 1 - control_activation_rate if control_activation_rate is not None else None + strong_specificity_proxy = 1 - control_strong_activation_rate if control_strong_activation_rate is not None else None + timing_precision_pass = ( + positive_top_3_rate is not None + and specificity_proxy is not None + and positive_top_3_rate >= 0.6 + and specificity_proxy >= 0.6 + ) return { "case_count": len(rows), "ranked_case_count": len(rankings), "control_date_count": len(controls), - "control_activation_rate": sum((control.get("score") or 0) >= 4 for control in controls) / len(controls) if controls else None, - "control_strong_activation_rate": sum((control.get("score") or 0) >= 7 for control in controls) / len(controls) if controls else None, - "positive_top_1_rate": sum(item["top_1"] for item in rankings) / len(rankings) if rankings else None, - "positive_top_3_rate": sum(item["top_3"] for item in rankings) / len(rankings) if rankings else None, + "control_activation_rate": control_activation_rate, + "control_strong_activation_rate": control_strong_activation_rate, + "specificity_proxy": specificity_proxy, + "strong_specificity_proxy": strong_specificity_proxy, + "positive_top_1_rate": positive_top_1_rate, + "positive_top_3_rate": positive_top_3_rate, "mean_reciprocal_rank": statistics.mean(item["reciprocal_rank"] for item in rankings) if rankings else None, "mean_score_margin": statistics.mean(margins) if margins else None, + "timing_precision_gate": { + "status": "pass" if timing_precision_pass else "blocked", + "positive_top_3_minimum": 0.6, + "specificity_proxy_minimum": 0.6, + "reason": None if timing_precision_pass else "positive_dates_do_not_rank_above_controls_with_required_specificity", + }, "balanced_accuracy": None, "balanced_accuracy_blocked_reason": "controls_are_non_target_dates_not_independently_adjudicated_all-domain_non_events", } @@ -106,9 +130,10 @@ def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--manifest", default="references/real_case_calibration/replay_manifest_probe3_v2.json") parser.add_argument("--output") + parser.add_argument("--offsets", default=",".join(str(value) for value in DEFAULT_OFFSETS)) args = parser.parse_args() manifest = json.loads((ROOT / args.manifest).read_text(encoding="utf-8")) - report = build_report(manifest) + report = build_report(manifest, parse_offsets(args.offsets)) payload = json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n" if args.output: output_path = ROOT / args.output diff --git a/scripts/shadbala.py b/scripts/shadbala.py index 835eef5d..1b1e9043 100644 --- a/scripts/shadbala.py +++ b/scripts/shadbala.py @@ -125,9 +125,36 @@ _MOOLATRIKONA = { "Mercury": (5, 16.0, 20.0), "Jupiter": (8, 0.0, 10.0), "Venus": (6, 0.0, 15.0), "Saturn": (10, 0.0, 20.0), } +_PLANET_INDEX = {name: index for index, name in enumerate(("Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn"))} +_INDEX_PLANET = {index: name for name, index in _PLANET_INDEX.items()} +_ABDA_WEEKDAY_PLANETS = ("Mars", "Mercury", "Jupiter", "Venus", "Saturn", "Sun", "Moon") +_HORA_ORDER = ("Saturn", "Jupiter", "Mars", "Sun", "Venus", "Mercury", "Moon") +_SURYA_CIVIL_DAYS = 1_577_917_828 +_SURYA_REVOLUTIONS = { + "Sun": 4_320_000, "Mars": 2_296_832, "Mercury": 17_937_060, + "Jupiter": 364_220, "Venus": 7_022_376, "Saturn": 146_568, +} +_UJJAIN_LONGITUDE = 75.7885 -def build_shadbala_context(jd_ut: float, lat: float, lon: float, ayanamsa: str = "lahiri") -> Dict: +def _solar_event_local_hour(jd_ut: float, lat: float, lon: float, timezone: float, event: int) -> float: + local_jd = jd_ut + timezone / 24.0 + year, month, day, _ = swe.revjul(local_jd, swe.GREG_CAL) + local_midnight = swe.julday(year, month, day, 0.0, swe.GREG_CAL) + utc_midnight = local_midnight - timezone / 24.0 + _, times = swe.rise_trans( + utc_midnight, + swe.SUN, + event | swe.BIT_HINDU_RISING, + (float(lon), float(lat), 0.0), + 0.0, + 0.0, + swe.FLG_SWIEPH | swe.FLG_SIDEREAL | swe.FLG_NONUT, + ) + return (times[0] + timezone / 24.0 - local_midnight) * 24.0 + + +def build_shadbala_context(jd_ut: float, lat: float, lon: float, ayanamsa: str = "lahiri", timezone: float = 0.0) -> Dict: """Build precise sidereal house context from standard birth inputs.""" sid_mode = swe.SIDM_LAHIRI if str(ayanamsa).lower() in {"raman"}: @@ -136,7 +163,19 @@ def build_shadbala_context(jd_ut: float, lat: float, lon: float, ayanamsa: str = sid_mode = swe.SIDM_KRISHNAMURTI swe.set_sid_mode(sid_mode) cusps, _ = swe.houses_ex(float(jd_ut), float(lat), float(lon), b"P", swe.FLG_SIDEREAL) - return {"jd_ut": float(jd_ut), "lat": float(lat), "lon": float(lon), "ayanamsa": str(ayanamsa), "house_midpoints": [float(value) % 360 for value in cusps]} + local_jd = float(jd_ut) + float(timezone) / 24.0 + year, month, day, local_hour = swe.revjul(local_jd, swe.GREG_CAL) + sunrise = _solar_event_local_hour(jd_ut, lat, lon, timezone, swe.CALC_RISE) + sunset = _solar_event_local_hour(jd_ut, lat, lon, timezone, swe.CALC_SET) + previous_sunset = _solar_event_local_hour(jd_ut - 1.0, lat, lon, timezone, swe.CALC_SET) + return { + "jd_ut": float(jd_ut), "jd_local": local_jd, + "lat": float(lat), "lon": float(lon), "timezone": float(timezone), + "year": int(year), "month": int(month), "day": int(day), "local_hour": float(local_hour), + "ayanamsa": str(ayanamsa), "ayanamsa_degrees": float(swe.get_ayanamsa_ut(float(jd_ut))), + "sunrise_hour": sunrise, "sunset_hour": sunset, "previous_sunset_hour": previous_sunset, + "house_midpoints": [float(value) % 360 for value in cusps], + } def calc_dig_bala_precise(pname: str, planet_lon: float, house_midpoints: list[float]) -> float: @@ -299,6 +338,155 @@ def calc_sthana_bala_precise(pname: str, all_planets: Dict, house: int) -> Dict: } +def _lagrange_interpolate(xs: tuple[float, ...], ys: tuple[float, ...], value: float) -> float: + total = 0.0 + for i, x_i in enumerate(xs): + term = ys[i] + for j, x_j in enumerate(xs): + if i != j: + term *= (value - x_j) / (x_i - x_j) + total += term + return total + + +def _ayana_bala(pname: str, longitude: float, ayanamsa: float) -> tuple[float, float]: + raw_tropical = longitude + ayanamsa + tropical = raw_tropical % 360.0 + north = raw_tropical < 180.0 + folded = tropical + if 90.0 < tropical < 180.0: + folded = 180.0 - tropical + elif 180.0 < tropical < 270.0: + folded = tropical - 180.0 + elif tropical > 270.0: + folded = 360.0 - tropical + sign = 1.0 + if north and pname in {"Moon", "Saturn"}: + sign = -1.0 + elif not north and pname in {"Sun", "Mars", "Jupiter", "Venus"}: + sign = -1.0 + if pname == "Mercury": + sign = 1.0 + declination = sign * _lagrange_interpolate( + (0.0, 15.0, 30.0, 45.0, 60.0, 75.0, 90.0), + (0.0, 362 / 60.0, 703 / 60.0, 1002 / 60.0, 1238 / 60.0, 1388 / 60.0, 24.0), + round(folded, 2), + ) + bala = round((24.0 + declination) * 1.25, 2) + if pname == "Sun": + bala = round(bala * 2.0, 2) + return bala, round(declination, 4) + + +def _days_elapsed_since_base(year: int, base_year: int = 1951, base_days: int = 174) -> int: + years = year - base_year + leap_years = sum(1 for value in range(base_year + 1, year + 1) if value % 4 == 0 and (value % 100 != 0 or value % 400 == 0)) + return base_days + leap_years * 366 + (years - leap_years) * 365 + + +def _calendar_lords(context: Dict) -> Dict[str, str]: + year, month, day = context["year"], context["month"], context["day"] + local_jd = context["jd_local"] + year_start = swe.julday(year, 1, 1, 0.0, swe.GREG_CAL) + elapsed = int(local_jd - year_start + 1.0) + ahargana = _days_elapsed_since_base(year - 1) + elapsed + abda = _ABDA_WEEKDAY_PLANETS[(int(ahargana // 360) * 3 + 1) % 7] + masa = _ABDA_WEEKDAY_PLANETS[(int(ahargana // 30) * 2 + 1) % 7] + + vaara_ahargana = _days_elapsed_since_base(year - 1, 1827, 244) + elapsed + if context["local_hour"] < context["sunrise_hour"]: + vaara_ahargana -= 1 + vaara = _ABDA_WEEKDAY_PLANETS[int(vaara_ahargana) % 7] + + civil_weekday = int(math.ceil(local_jd + 1.0) % 7) + local_hour = context["local_hour"] + if local_hour < context["sunrise_hour"]: + civil_weekday = (civil_weekday - 1) % 7 + local_hour += 24.0 + hora_index = (int(local_hour - context["sunrise_hour"]) + civil_weekday + 1) % 7 + return {"abda": abda, "masa": masa, "vaara": vaara, "hora": _HORA_ORDER[hora_index]} + + +def calc_kala_bala_precise(pname: str, all_planets: Dict, context: Dict) -> Dict: + """Classical temporal strength from local solar events and calendar lords.""" + local_hour = context["local_hour"] + midnight = (context["sunrise_hour"] + context["previous_sunset_hour"]) / 2.0 + midnight = 12.0 - midnight if midnight < 12.0 else midnight - 12.0 + unnata = (local_hour - midnight) * 5.0 if local_hour < 12.0 else (24.0 + midnight - local_hour) * 5.0 + if pname == "Mercury": + nathonnata = 60.0 + elif pname in {"Sun", "Jupiter", "Venus"}: + nathonnata = round(unnata, 2) + else: + nathonnata = round(60.0 - unnata, 2) + + benefics, malefics = classify_drik_planets(all_planets) + phase = round(abs(_planet_longitude("Sun", all_planets) - _planet_longitude("Moon", all_planets)) / 3.0, 2) + paksha = phase if pname in benefics else round(60.0 - phase, 2) if pname in malefics else 0.0 + if pname == "Moon": + paksha = round(paksha * 2.0, 2) + + sunrise, sunset = context["sunrise_hour"], context["sunset_hour"] + day_length = sunset - sunrise + night_length = 24.0 - day_length + tribhaga_lord = None + if sunrise <= local_hour < sunset: + tribhaga_lord = ("Mercury", "Sun", "Saturn")[min(2, int((local_hour - sunrise) / (day_length / 3.0)))] + else: + since_sunset = (local_hour - sunset) % 24.0 + tribhaga_lord = ("Moon", "Venus", "Mars")[min(2, int(since_sunset / (night_length / 3.0)))] + tribhaga = 60.0 if pname in {"Jupiter", tribhaga_lord} else 0.0 + + lords = _calendar_lords(context) + calendar = (15.0 if pname == lords["abda"] else 0.0) + (30.0 if pname == lords["masa"] else 0.0) + (45.0 if pname == lords["vaara"] else 0.0) + (60.0 if pname == lords["hora"] else 0.0) + ayana, declination = _ayana_bala(pname, _planet_longitude(pname, all_planets), context["ayanamsa_degrees"]) + total = round(nathonnata + paksha + tribhaga + calendar + ayana, 2) + return { + "nathonnata": nathonnata, "paksha": paksha, "tribhaga": tribhaga, + "abda": 15.0 if pname == lords["abda"] else 0.0, + "masa": 30.0 if pname == lords["masa"] else 0.0, + "vaara": 45.0 if pname == lords["vaara"] else 0.0, + "hora": 60.0 if pname == lords["hora"] else 0.0, + "ayana": ayana, "declination": declination, "yuddha": 0.0, + "total": total, + } + + +def _surya_mean_longitude(pname: str, context: Dict) -> float: + """Surya Siddhanta mean motion with desantara correction from Ujjain.""" + local_jd = context["jd_local"] + kali_days = int(local_jd - 588_465.0) + weekday = int(math.ceil(local_jd + 1.0) % 7) + kali_days += weekday - 5 - kali_days % 7 + daily_motion = round(_SURYA_REVOLUTIONS[pname] / _SURYA_CIVIL_DAYS * 360.0, 7) + mean_longitude = (kali_days * daily_motion) % 360.0 + desantara = (_UJJAIN_LONGITUDE - context["lon"]) / 360.0 * daily_motion + return (mean_longitude + desantara) % 360.0 + + +def calc_chesta_bala_precise(pname: str, all_planets: Dict, kala: Dict, context: Dict) -> float: + """BPHS bounded Chesta Bala using mean motion and Seeghrochcha. + + Mean-motion/Seeghrochcha structure and constants are adapted from the MIT + jyotishganit reference retained under references/open_source_sources. + """ + if pname == "Sun": + return round(float(kala["ayana"]), 2) + if pname == "Moon": + return round(float(kala["paksha"]), 2) + sun_mean = _surya_mean_longitude("Sun", context) + planet_mean = _surya_mean_longitude(pname, context) + if pname in {"Mercury", "Venus"}: + seeghrochcha, mean_longitude = planet_mean, sun_mean + else: + seeghrochcha, mean_longitude = sun_mean, planet_mean + average_longitude = (_planet_longitude(pname, all_planets) + mean_longitude) / 2.0 + chesta_kendra = abs(seeghrochcha - average_longitude) + if chesta_kendra > 180.0: + chesta_kendra = 360.0 - chesta_kendra + return round(max(0.0, chesta_kendra) / 3.0, 2) + + def calc_shadbala(planets: Dict, asc_sign: str, birth_hour: float, sun_lon: float, moon_lon: float, birth_minute: float = 0.0, context: Dict | None = None) -> Dict: @@ -333,8 +521,8 @@ def calc_shadbala(planets: Dict, asc_sign: str, birth_hour: float, sthana = calc_sthana_bala_precise(pname, planets, house) dig = calc_dig_bala_precise(pname, lon, context["house_midpoints"]) if context and context.get("house_midpoints") else calc_dig_bala(pname, house) - kala = calc_kala_bala(pname, is_night, sun_northern, sun_lon, moon_lon, birth_hour, birth_minute) - chesta = calc_chesta_bala(pname, retro, speed, sun_lon, moon_lon) + kala = calc_kala_bala_precise(pname, planets, context) if context else calc_kala_bala(pname, is_night, sun_northern, sun_lon, moon_lon, birth_hour, birth_minute) + chesta = calc_chesta_bala_precise(pname, planets, kala, context) if context else calc_chesta_bala(pname, retro, speed, sun_lon, moon_lon) naisargika = NAISARGIKA_BALA.get(pname, 30.0) drik = calc_drik_bala(pname, sign, house, planets) @@ -357,8 +545,8 @@ def calc_shadbala(planets: Dict, asc_sign: str, birth_hour: float, sthana = calc_sthana_bala_precise(pname, planets, house) dig = calc_dig_bala_precise(pname, lon, context["house_midpoints"]) if context and context.get("house_midpoints") else calc_dig_bala(pname, house) - kala = calc_kala_bala(pname, is_night, sun_northern, sun_lon, moon_lon, birth_hour, birth_minute) - chesta = calc_chesta_bala(pname, retro, speed, sun_lon, moon_lon) + kala = calc_kala_bala_precise(pname, planets, context) if context else calc_kala_bala(pname, is_night, sun_northern, sun_lon, moon_lon, birth_hour, birth_minute) + chesta = calc_chesta_bala_precise(pname, planets, kala, context) if context else calc_chesta_bala(pname, retro, speed, sun_lon, moon_lon) naisargika = NAISARGIKA_BALA.get(pname, 30.0) drik = calc_drik_bala(pname, sign, house, planets) @@ -408,7 +596,12 @@ def calc_shadbala(planets: Dict, asc_sign: str, birth_hour: float, bhava_bala = calc_bhava_bala(planets, asc_sign) return { - 'method': 'Shadbala六重力量(v6.9.15: absolute Rupas, Kendra三档+Bhava Bala+Hora Lord+Seeghrochcha Sun)', + 'method': 'Shadbala六重力量(absolute Virupas; precise Sthana/Dig/Kala/Drik; bounded BPHS Chesta)', + 'method_variants': { + 'kala': 'bphs_local_solar_events_ahargana_declination' if context else 'legacy_approximation', + 'chesta': 'bphs_bounded_surya_mean_motion_seeghrochcha' if context else 'legacy_speed_bands', + }, + 'external_parity_boundary': 'Chesta remains cross-engine method-conflicted; totals inherit that boundary.', 'is_night_birth': is_night, 'sun_uttarayana': sun_northern, 'planets': results, diff --git a/scripts/vedastro_official_source_contract.py b/scripts/vedastro_official_source_contract.py new file mode 100644 index 00000000..7008b925 --- /dev/null +++ b/scripts/vedastro_official_source_contract.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +"""Audit VedAstro's official MIT source contract without invoking the service.""" +from __future__ import annotations + +import argparse +import hashlib +import json +import re +import subprocess +from pathlib import Path + + +def _read(root: Path, relative: str) -> str: + return (root / relative).read_text(encoding="utf-8-sig") + + +def audit_source(root: Path) -> dict: + project = _read(root, "Library/Library.csproj") + time_source = _read(root, "Library/Data/Time.cs") + tools_source = _read(root, "Library/Logic/Tools.cs") + core_source = _read(root, "Library/Logic/Calculate/Core.cs") + version_match = re.search(r"([^<]+)", project) + checks = { + "mit_license": "MIT" in project, + "offset_parse_exact": 'DateTimeOffset.ParseExact(timezoneRaw, "zzz"' in tools_source, + "zero_offset_auto_lookup": "parsedTimezone == null || parsedTimezone == TimeSpan.Zero" in tools_source and "GeoLocationToTimezone" in tools_source, + "time_keeps_offset": "DateTimeOffset.ParseExact(stdDateTimeText, Time.DateTimeFormat" in time_source and "HH:mm dd/MM/yyyy zzz" in time_source, + "all_planet_longitude_is_nirayana": "AllPlanetLongitude(Time time)" in core_source and "PlanetNirayanaLongitude" in core_source, + } + commit = None + try: + commit = subprocess.run(["git", "-C", str(root), "rev-parse", "HEAD"], check=True, capture_output=True, text=True).stdout.strip() + except (OSError, subprocess.CalledProcessError): + pass + files = {} + for relative in ("Library/Library.csproj", "Library/Data/Time.cs", "Library/Logic/Tools.cs", "Library/Logic/Calculate/Core.cs"): + files[relative] = hashlib.sha256((root / relative).read_bytes()).hexdigest() + return { + "source": "https://github.com/VedAstro/VedAstro", + "source_commit": commit, + "library_version": version_match.group(1) if version_match else None, + "source_contract_status": "verified" if all(checks.values()) else "blocked", + "checks": checks, + "timezone_contract": { + "zero_offset": "auto_lookup_sentinel" if checks["zero_offset_auto_lookup"] else "blocked", + "negative_offset": "literal_offset" if checks["offset_parse_exact"] else "blocked", + "conclusion": "+00:00 and the location's real offset may intentionally produce identical results.", + }, + "longitude_contract": {"AllPlanetLongitude": "nirayana" if checks["all_planet_longitude_is_nirayana"] else "blocked"}, + "deployment_identity_status": "blocked", + "deployment_identity_reason": "Remote responses expose neither library version nor source commit.", + "files": files, + } + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("source_root", type=Path) + parser.add_argument("--output", type=Path) + args = parser.parse_args() + report = audit_source(args.source_root) + text = json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n" + if args.output: + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(text, encoding="utf-8") + print(text, end="") + return 0 if report["source_contract_status"] == "verified" else 2 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_real_case_negative_controls.py b/tests/test_real_case_negative_controls.py index 2eb8183d..d64e3c3d 100644 --- a/tests/test_real_case_negative_controls.py +++ b/tests/test_real_case_negative_controls.py @@ -2,11 +2,16 @@ from __future__ import annotations from scripts.public_real_case_negative_controls import ( generate_control_dates, + parse_offsets, rank_positive_against_controls, summarize_negative_control_rows, ) +def test_parse_offsets_rejects_zero_and_deduplicates() -> None: + assert parse_offsets("-60,-30,0,30,60,-30") == (-60, -30, 30, 60) + + def test_generate_control_dates_uses_fixed_offsets_without_positive_date() -> None: dates = generate_control_dates("2018-05-19", offsets=(-60, -30, 30, 60)) @@ -47,7 +52,10 @@ def test_negative_control_summary_reports_false_activations() -> None: assert summary["control_date_count"] == 4 assert summary["control_activation_rate"] == 0.5 assert summary["control_strong_activation_rate"] == 0.25 + assert summary["specificity_proxy"] == 0.5 + assert summary["strong_specificity_proxy"] == 0.75 assert summary["positive_top_1_rate"] == 0.5 assert summary["positive_top_3_rate"] == 1.0 assert summary["mean_reciprocal_rank"] == 0.75 assert summary["mean_score_margin"] == 0.5 + assert summary["timing_precision_gate"]["status"] == "blocked" diff --git a/tests/test_shadbala_precise_context.py b/tests/test_shadbala_precise_context.py index 978392c8..5bd47c3d 100644 --- a/tests/test_shadbala_precise_context.py +++ b/tests/test_shadbala_precise_context.py @@ -2,6 +2,8 @@ from scripts.shadbala import ( build_shadbala_context, calc_dig_bala_precise, calc_drik_bala_precise, + calc_kala_bala_precise, + calc_chesta_bala_precise, calc_sthana_bala_precise, classify_drik_planets, ) @@ -19,6 +21,7 @@ PLANET_LONGITUDES = { PYJHORA_DIG = {"Sun": 24.81, "Moon": 95.48, "Mars": 77.41, "Mercury": 12.64, "Jupiter": 80.60, "Venus": 69.95, "Saturn": 19.62} PYJHORA_DRIK = {"Sun": 1.74, "Moon": 20.06, "Mars": 13.49, "Mercury": -10.63, "Jupiter": 6.89, "Venus": -2.75, "Saturn": 9.49} PYJHORA_STHANA = {"Sun": 217.09, "Moon": 246.34, "Mars": 198.63, "Mercury": 167.96, "Jupiter": 201.80, "Venus": 154.06, "Saturn": 218.61} +PYJHORA_KALA = {"Sun": 140.99, "Moon": 149.58, "Mars": 127.93, "Mercury": 121.78, "Jupiter": 199.31, "Venus": 113.44, "Saturn": 136.77} def _planets() -> dict: @@ -32,7 +35,7 @@ def _planets() -> dict: def test_precise_dig_bala_matches_pyjhora_same_chart() -> None: - context = build_shadbala_context(2435163.6354166665, 37.7749, -122.4194, "lahiri") + context = build_shadbala_context(2435163.6354166665, 37.7749, -122.4194, "lahiri", -8.0) for planet, longitude in PLANET_LONGITUDES.items(): assert calc_dig_bala_precise(planet, longitude, context["house_midpoints"]) == PYJHORA_DIG[planet] @@ -54,3 +57,27 @@ def test_precise_sthana_bala_matches_pyjhora_same_chart() -> None: houses = {"Sun": 7, "Moon": 8, "Mars": 9, "Mercury": 6, "Jupiter": 11, "Venus": 5, "Saturn": 3} for planet, expected in PYJHORA_STHANA.items(): assert calc_sthana_bala_precise(planet, planets, houses[planet])["total"] == expected + + +def test_precise_kala_bala_matches_pyjhora_same_chart() -> None: + planets = _planets() + context = build_shadbala_context(2435163.6354166665, 37.7749, -122.4194, "lahiri", -8.0) + assert abs(context["sunrise_hour"] - 6.886306) < 0.00001 + assert abs(context["sunset_hour"] - 17.890427) < 0.00001 + for planet, expected in PYJHORA_KALA.items(): + assert calc_kala_bala_precise(planet, planets, context)["total"] == expected + + +def test_precise_chesta_uses_classical_bounded_variant() -> None: + planets = _planets() + context = build_shadbala_context(2435163.6354166665, 37.7749, -122.4194, "lahiri", -8.0) + kala = {planet: calc_kala_bala_precise(planet, planets, context) for planet in planets} + result = {planet: calc_chesta_bala_precise(planet, planets, kala[planet], context) for planet in planets} + assert result["Sun"] == kala["Sun"]["ayana"] + assert result["Moon"] == kala["Moon"]["paksha"] + for planet in ("Mars", "Mercury", "Jupiter", "Venus", "Saturn"): + assert 0.0 <= result[planet] <= 60.0 + vedastro = {"Mars": 21.7377, "Mercury": 47.5107, "Jupiter": 46.0549, "Venus": 30.8469, "Saturn": 39.4390} + tolerances = {"Mars": 1.0, "Mercury": 2.0, "Jupiter": 1.0, "Venus": 2.0, "Saturn": 3.5} + for planet, expected in vedastro.items(): + assert abs(result[planet] - expected) <= tolerances[planet] diff --git a/tests/test_vedastro_official_source_contract.py b/tests/test_vedastro_official_source_contract.py new file mode 100644 index 00000000..e1f98bef --- /dev/null +++ b/tests/test_vedastro_official_source_contract.py @@ -0,0 +1,21 @@ +from pathlib import Path + +from scripts.vedastro_official_source_contract import audit_source + + +def test_official_source_contract_resolves_zero_offset_semantics(tmp_path: Path) -> None: + (tmp_path / "Library/Data").mkdir(parents=True) + (tmp_path / "Library/Logic/Calculate").mkdir(parents=True) + (tmp_path / "Library/Logic").mkdir(parents=True, exist_ok=True) + (tmp_path / "Library/Library.csproj").write_text("1.2.0MIT") + (tmp_path / "Library/Data/Time.cs").write_text('DateTimeOffset.ParseExact(stdDateTimeText, Time.DateTimeFormat, null); public const string DateTimeFormat = "HH:mm dd/MM/yyyy zzz";') + (tmp_path / "Library/Logic/Tools.cs").write_text('var parsedTimezone = Tools.StringToTimezone(offsetStr); if (parsedTimezone == null || parsedTimezone == TimeSpan.Zero) offsetStr = await Calculate.GeoLocationToTimezone(geoLocation, parsedInputTime); DateTimeOffset.ParseExact(timezoneRaw, "zzz", CultureInfo.InvariantCulture).Offset;') + (tmp_path / "Library/Logic/Calculate/Core.cs").write_text("public static List AllPlanetLongitude(Time time) { return PlanetNirayanaLongitude(Sun, time); }") + + report = audit_source(tmp_path) + + assert report["source_contract_status"] == "verified" + assert report["timezone_contract"]["zero_offset"] == "auto_lookup_sentinel" + assert report["timezone_contract"]["negative_offset"] == "literal_offset" + assert report["longitude_contract"]["AllPlanetLongitude"] == "nirayana" + assert report["deployment_identity_status"] == "blocked"