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"