From a509e27ec9e775eacaeba3a3091739a845cb0ff0 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Mon, 20 Jul 2026 13:55:54 +0800 Subject: [PATCH] feat: sync real case website e2e contract --- .../evidence_packet_index_2026_07_19.json | 36 +- ...c_candidate_capture_packet_2026_07_20.json | 75 ++ .../prashna_input_contract_2026_07_20.json | 42 ++ ...umeric_oracle_packet_queue_2026_07_20.json | 46 ++ ...real_case_website_e2e_eval_2026_07_20.json | 657 ++++++++++++++++++ ...uhurta_numeric_candidate_capture_packet.py | 85 +++ scripts/prashna_oracle_queue.py | 77 ++ scripts/real_case_website_e2e_eval.py | 100 +++ ...uhurta_numeric_candidate_capture_packet.py | 44 ++ ...prashna_input_contract_and_oracle_queue.py | 36 + tests/test_real_case_website_e2e_eval.py | 32 + 11 files changed, 1228 insertions(+), 2 deletions(-) create mode 100644 references/oracle/muhurta_numeric_candidate_capture_packet_2026_07_20.json create mode 100644 references/oracle/prashna_input_contract_2026_07_20.json create mode 100644 references/oracle/prashna_numeric_oracle_packet_queue_2026_07_20.json create mode 100644 references/real_case_calibration/real_case_website_e2e_eval_2026_07_20.json create mode 100644 scripts/muhurta_numeric_candidate_capture_packet.py create mode 100644 scripts/prashna_oracle_queue.py create mode 100644 scripts/real_case_website_e2e_eval.py create mode 100644 tests/test_muhurta_numeric_candidate_capture_packet.py create mode 100644 tests/test_prashna_input_contract_and_oracle_queue.py create mode 100644 tests/test_real_case_website_e2e_eval.py diff --git a/references/oracle/evidence_packet_index_2026_07_19.json b/references/oracle/evidence_packet_index_2026_07_19.json index d77d9854..a9d4ba37 100644 --- a/references/oracle/evidence_packet_index_2026_07_19.json +++ b/references/oracle/evidence_packet_index_2026_07_19.json @@ -665,14 +665,46 @@ "claim_status": "source_intake_only", "consumer_policy": "research_observation_only", "claim_boundary": "Triage of public KP, Muhurta, and Shadbala source candidates; no source is oracle-ready until raw capture, exact settings, expected values, hash, and replay comparison are archived." + }, + { + "packet_id": "real_case_website_e2e_eval_2026_07_20", + "path": "references/real_case_calibration/real_case_website_e2e_eval_2026_07_20.json", + "domain": "real_case_website_e2e", + "claim_status": "ready_contract", + "consumer_policy": "research_to_commercial_contract_only", + "claim_boundary": "20 public real-case website E2E quality contract; product QA only, not an accuracy benchmark or independent holdout." + }, + { + "packet_id": "prashna_input_contract_2026_07_20", + "path": "references/oracle/prashna_input_contract_2026_07_20.json", + "domain": "horary_annual_sensitive_points", + "claim_status": "ready_contract", + "consumer_policy": "research_to_commercial_contract_only", + "claim_boundary": "Prashna input contract only; requires explicit time/place/timezone/ayanamsa/node, not predictive truth." + }, + { + "packet_id": "prashna_numeric_oracle_packet_queue_2026_07_20", + "path": "references/oracle/prashna_numeric_oracle_packet_queue_2026_07_20.json", + "domain": "horary_annual_sensitive_points", + "claim_status": "open_queue", + "consumer_policy": "research_to_commercial_contract_only", + "claim_boundary": "Public numeric Prashna/Sphuta candidates remain open queue until complete input/settings/raw hash/replay close." + }, + { + "packet_id": "muhurta_numeric_candidate_capture_packet_2026_07_20", + "path": "references/oracle/muhurta_numeric_candidate_capture_packet_2026_07_20.json", + "domain": "muhurta_factor_scoring", + "claim_status": "source_intake_only", + "consumer_policy": "research_to_commercial_contract_only", + "claim_boundary": "Stages two Muhurta numeric candidates for raw page capture; does not calculate, replay, or validate Muhurta verdicts." } ], "production_tuning_allowed": false, "scope": "evidence_packet_index", "status": "active_index_v1", "summary": { - "packet_count": 83, - "blocked_or_partial_count": 55, + "packet_count": 87, + "blocked_or_partial_count": 56, "human_review_required_count": 2 } } diff --git a/references/oracle/muhurta_numeric_candidate_capture_packet_2026_07_20.json b/references/oracle/muhurta_numeric_candidate_capture_packet_2026_07_20.json new file mode 100644 index 00000000..2cea47b8 --- /dev/null +++ b/references/oracle/muhurta_numeric_candidate_capture_packet_2026_07_20.json @@ -0,0 +1,75 @@ +{ + "boundary": "Capture packet staging only; does not calculate or validate Muhurta verdicts.", + "capture_rows": [ + { + "canonical_request_hash": "5bcdcf51cdd8a7bb42a3fab019eaffacf3a562904f69c25b65c1ba559b41f602", + "claim_boundary": "Numeric-looking public source; not oracle-ready until raw page, exact settings, hash, and local replay comparison are archived.", + "domain": "muhurta_factor_scoring", + "missing_for_oracle": [ + "raw_capture_hash", + "exact_date_selection", + "timezone", + "sunrise", + "formula_weight_contract", + "exact_method_settings", + "replay_comparison" + ], + "next_artifact_path": "references/oracle/artifacts/mypanchang_edison_2025_panchangam_raw_capture_packet.json", + "observed_numeric_fields": [ + "tarabalam periods", + "chandrabalam periods", + "nakshatra", + "rasi", + "tithi", + "yoga", + "karana" + ], + "raw_capture_status": "pending_raw_page_capture", + "source_id": "mypanchang_edison_2025_panchangam", + "source_observation_hash": "d57a30a4da43bb5ee92f16b6d8e2f6df099854a1cab1a2f95f72efea16dd9671", + "topic": "Tarabala/Chandrabala/Panchangam daily factors", + "upgrade_status": "not_oracle_ready", + "url": "https://www.mypanchang.com/phppanchang.php?cityhead=&cityname=Edison-NJ&mn=04&monthtype=1&yr=2025" + }, + { + "canonical_request_hash": "b6110c7ab7a6346f42671a1c46fb6d81286483ea2e9a3808dd02367742ed06df", + "claim_boundary": "Numeric-looking public source; not oracle-ready until raw page, exact settings, hash, and local replay comparison are archived.", + "domain": "muhurta_factor_scoring", + "missing_for_oracle": [ + "raw_capture_hash", + "sunrise", + "sunset", + "timezone", + "calculation_rule_replay", + "exact_method_settings", + "replay_comparison" + ], + "next_artifact_path": "references/oracle/artifacts/drikpanchang_mumbai_rahu_2026_07_20_raw_capture_packet.json", + "observed_numeric_fields": [ + "rahu kalam interval", + "weekday", + "city/date scoped daily table" + ], + "raw_capture_status": "pending_raw_page_capture", + "source_id": "drikpanchang_mumbai_rahu_2026_07_20", + "source_observation_hash": "a7a4c1f5ba3fe872af645cddab962eba9fe4e0f697eee5d3bfca73951a571a8a", + "topic": "Rahu Kalam daily interval", + "upgrade_status": "not_oracle_ready", + "url": "https://www.drikpanchang.com/muhurat/rahu-kalam.html?date=20/07/2026&geoname-id=1275339" + } + ], + "claim_status": "source_intake_only", + "created_at": "2026-07-20", + "production_tuning_allowed": false, + "scope": "muhurta_numeric_candidate_capture_packet", + "sources": { + "source_triage": "references/oracle/public_worked_example_source_triage_2026_07_20.json" + }, + "status": "capture_packet_ready", + "summary": { + "candidate_count": 2, + "oracle_ready_count": 0, + "pending_raw_capture_count": 2 + }, + "truth_matrix_allowed": false +} diff --git a/references/oracle/prashna_input_contract_2026_07_20.json b/references/oracle/prashna_input_contract_2026_07_20.json new file mode 100644 index 00000000..429b8422 --- /dev/null +++ b/references/oracle/prashna_input_contract_2026_07_20.json @@ -0,0 +1,42 @@ +{ + "claim_boundary": "Input contract only; does not validate Prashna predictions or external numeric parity.", + "claim_status": "ready_contract", + "created_at": "2026-07-20", + "optional_fields": [ + "question_text", + "querent_id", + "house_focus", + "language" + ], + "production_tuning_allowed": false, + "required_fields": [ + { + "boundary": "exact time question is received/accepted", + "field": "question_datetime_local", + "format": "YYYY-MM-DDTHH:MM:SS" + }, + { + "boundary": "place of querent/astrologer must be explicit", + "field": "location", + "format": "lat/lon + place label" + }, + { + "boundary": "no implicit local machine timezone", + "field": "timezone", + "format": "IANA or UTC offset" + }, + { + "boundary": "default must be recorded, e.g. Lahiri", + "field": "ayanamsa", + "format": "named sidereal ayanamsa" + }, + { + "boundary": "Rahu/Ketu mode must be frozen", + "field": "node_mode", + "format": "mean|true" + } + ], + "scope": "prashna_input_contract", + "status": "contract_ready", + "truth_matrix_allowed": false +} diff --git a/references/oracle/prashna_numeric_oracle_packet_queue_2026_07_20.json b/references/oracle/prashna_numeric_oracle_packet_queue_2026_07_20.json new file mode 100644 index 00000000..e851d6ed --- /dev/null +++ b/references/oracle/prashna_numeric_oracle_packet_queue_2026_07_20.json @@ -0,0 +1,46 @@ +{ + "boundary": "Queue only; no Prashna/Saham/Gulika/Sphuta claim is upgraded until complete input, raw/hash and local/external replay close.", + "claim_status": "open_queue", + "created_at": "2026-07-20", + "production_tuning_allowed": false, + "rows": [ + { + "candidate_hash": "2f8fafd98fba0f328b9eba58af1b4446ebf3a856d0769c79d6dc27e99218c63d", + "claim_boundary": "Numeric Sphuta example exists, but full Prashna input/settings are incomplete; use as candidate only.", + "domain": "horary_annual_sensitive_points", + "expected_values": { + "chatusphuta": "2s 15° 18' 34\"", + "gulika": "3s 14° 10'", + "lagna": "3s 27° 22'", + "moon": "3s 19° 36' 34\"", + "panchasphuta": "5s 23° 34' 34\"", + "rahu": "3s 8° 16'", + "sun": "4s 3° 8' 25\"", + "trisphuta": "11s 1° 8' 34\"" + }, + "missing_for_oracle": [ + "complete_prashna_input", + "ayanamsa", + "node_mode", + "timezone", + "raw_capture_hash", + "local_replay", + "pyjhora_or_other_legal_replay" + ], + "numeric_fields_present": true, + "source_id": "vedastro_prasna_marga_ch5_sphuta_example", + "source_role": "public_numeric_candidate", + "technique_family": "sphuta_trisphuta_family", + "upgrade_status": "candidate_not_oracle", + "url": "https://vedastro.org/book/PrasnaMarga/Chapter5" + } + ], + "scope": "prashna_numeric_oracle_packet_queue", + "status": "queue_ready", + "summary": { + "candidate_count": 1, + "numeric_candidate_count": 1, + "oracle_ready_count": 0 + }, + "truth_matrix_allowed": false +} diff --git a/references/real_case_calibration/real_case_website_e2e_eval_2026_07_20.json b/references/real_case_calibration/real_case_website_e2e_eval_2026_07_20.json new file mode 100644 index 00000000..2f3ebc72 --- /dev/null +++ b/references/real_case_calibration/real_case_website_e2e_eval_2026_07_20.json @@ -0,0 +1,657 @@ +{ + "acceptance_rules": [ + "Website must save/render input contract and runtime context JSON for each prompt.", + "Answers may use public cases as explanation references, not prediction proof.", + "Precise day/month claims must stay exploratory_unvalidated unless holdout closes.", + "Marriage/career/wealth/health/migration/family/education/timing/annual domains must route to matching technique context.", + "Any Shadbala/AV/KP conflict must be described as method/source difference, not majority-vote truth." + ], + "boundary": "Product E2E quality harness only; not an accuracy benchmark or independent holdout.", + "case_count": 20, + "cases": [ + { + "birth": { + "date": "1955-02-24", + "place": "San Francisco, CA, USA", + "source_policy": "public_record_candidate", + "time": "19:15" + }, + "case_id": "steve_jobs", + "domains": [ + "career", + "wealth", + "timing" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "财富来源和风险是什么?", + "历史关键阶段能否用 Dasha + Narayana 回看?" + ], + "subject": "Steve Jobs" + }, + { + "birth": { + "date": "1879-03-14", + "place": "Ulm, Germany", + "source_policy": "public_record_candidate", + "time": "11:30" + }, + "case_id": "albert_einstein", + "domains": [ + "education", + "career", + "timing" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "学习与教育路径怎么看?", + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "历史关键阶段能否用 Dasha + Narayana 回看?" + ], + "subject": "Albert Einstein" + }, + { + "birth": { + "date": "1961-08-04", + "place": "Honolulu, HI, USA", + "source_policy": "public_record_candidate", + "time": "19:24" + }, + "case_id": "barack_obama", + "domains": [ + "career", + "migration", + "annual" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "迁移/海外发展应看哪些宫位和 Dasha?", + "年度运势应如何避免过度承诺?" + ], + "subject": "Barack Obama" + }, + { + "birth": { + "date": "1961-07-01", + "place": "Sandringham, England", + "source_policy": "public_record_candidate", + "time": "19:45" + }, + "case_id": "princess_diana", + "domains": [ + "marriage", + "family", + "timing" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "婚恋关系中应看哪些印度占星指标?", + "家庭/子女主题应调用哪些分盘和宫位?", + "历史关键阶段能否用 Dasha + Narayana 回看?" + ], + "subject": "Princess Diana" + }, + { + "birth": { + "date": "1946-06-14", + "place": "Queens, NY, USA", + "source_policy": "public_record_candidate", + "time": "10:54" + }, + "case_id": "donald_trump", + "domains": [ + "career", + "wealth", + "annual" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "财富来源和风险是什么?", + "年度运势应如何避免过度承诺?" + ], + "subject": "Donald Trump" + }, + { + "birth": { + "date": "1954-01-29", + "place": "Kosciusko, MS, USA", + "source_policy": "public_record_candidate", + "time": "04:30" + }, + "case_id": "oprah_winfrey", + "domains": [ + "career", + "wealth", + "family" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "财富来源和风险是什么?", + "家庭/子女主题应调用哪些分盘和宫位?" + ], + "subject": "Oprah Winfrey" + }, + { + "birth": { + "date": "1971-06-28", + "place": "Pretoria, South Africa", + "source_policy": "public_record_candidate", + "time": "07:30" + }, + "case_id": "elon_musk", + "domains": [ + "career", + "migration", + "wealth" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "迁移/海外发展应看哪些宫位和 Dasha?", + "财富来源和风险是什么?" + ], + "subject": "Elon Musk" + }, + { + "birth": { + "date": "1869-10-02", + "place": "Porbandar, India", + "source_policy": "public_record_candidate", + "time": "07:11" + }, + "case_id": "mahatma_gandhi", + "domains": [ + "career", + "migration", + "timing" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "迁移/海外发展应看哪些宫位和 Dasha?", + "历史关键阶段能否用 Dasha + Narayana 回看?" + ], + "subject": "Mahatma Gandhi" + }, + { + "birth": { + "date": "1926-06-01", + "place": "Los Angeles, CA, USA", + "source_policy": "public_record_candidate", + "time": "09:30" + }, + "case_id": "marilyn_monroe", + "domains": [ + "marriage", + "career", + "health" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "婚恋关系中应看哪些印度占星指标?", + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "健康主题只能如何非医疗表达?" + ], + "subject": "Marilyn Monroe" + }, + { + "birth": { + "date": "1955-10-28", + "place": "Seattle, WA, USA", + "source_policy": "public_record_candidate", + "time": "22:00" + }, + "case_id": "bill_gates", + "domains": [ + "career", + "wealth", + "education" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "财富来源和风险是什么?", + "学习与教育路径怎么看?" + ], + "subject": "Bill Gates" + }, + { + "birth": { + "date": "1965-07-31", + "place": "Yate, England", + "source_policy": "public_record_candidate", + "time": "14:00" + }, + "case_id": "j_k_rowling", + "domains": [ + "career", + "wealth", + "timing" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "财富来源和风险是什么?", + "历史关键阶段能否用 Dasha + Narayana 回看?" + ], + "subject": "J. K. Rowling" + }, + { + "birth": { + "date": "1918-07-18", + "place": "Mvezo, South Africa", + "source_policy": "public_record_candidate", + "time": "14:54" + }, + "case_id": "nelson_mandela", + "domains": [ + "career", + "timing", + "migration" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "历史关键阶段能否用 Dasha + Narayana 回看?", + "迁移/海外发展应看哪些宫位和 Dasha?" + ], + "subject": "Nelson Mandela" + }, + { + "birth": { + "date": "1910-08-26", + "place": "Skopje, North Macedonia", + "source_policy": "public_record_candidate", + "time": "14:25" + }, + "case_id": "mother_teresa", + "domains": [ + "career", + "migration", + "health" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "迁移/海外发展应看哪些宫位和 Dasha?", + "健康主题只能如何非医疗表达?" + ], + "subject": "Mother Teresa" + }, + { + "birth": { + "date": "1958-08-29", + "place": "Gary, IN, USA", + "source_policy": "public_record_candidate", + "time": "19:33" + }, + "case_id": "michael_jackson", + "domains": [ + "career", + "wealth", + "health" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "财富来源和风险是什么?", + "健康主题只能如何非医疗表达?" + ], + "subject": "Michael Jackson" + }, + { + "birth": { + "date": "1926-04-21", + "place": "London, England", + "source_policy": "public_record_candidate", + "time": "02:40" + }, + "case_id": "queen_elizabeth_ii", + "domains": [ + "career", + "family", + "annual" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "家庭/子女主题应调用哪些分盘和宫位?", + "年度运势应如何避免过度承诺?" + ], + "subject": "Queen Elizabeth II" + }, + { + "birth": { + "date": "1917-05-29", + "place": "Brookline, MA, USA", + "source_policy": "public_record_candidate", + "time": "15:00" + }, + "case_id": "john_f_kennedy", + "domains": [ + "career", + "family", + "health" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "家庭/子女主题应调用哪些分盘和宫位?", + "健康主题只能如何非医疗表达?" + ], + "subject": "John F. Kennedy" + }, + { + "birth": { + "date": "1929-01-15", + "place": "Atlanta, GA, USA", + "source_policy": "public_record_candidate", + "time": "12:00" + }, + "case_id": "martin_luther_king_jr", + "domains": [ + "career", + "timing", + "health" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "历史关键阶段能否用 Dasha + Narayana 回看?", + "健康主题只能如何非医疗表达?" + ], + "subject": "Martin Luther King Jr." + }, + { + "birth": { + "date": "1975-06-04", + "place": "Los Angeles, CA, USA", + "source_policy": "public_record_candidate", + "time": "09:09" + }, + "case_id": "angelina_jolie", + "domains": [ + "marriage", + "family", + "career" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "婚恋关系中应看哪些印度占星指标?", + "家庭/子女主题应调用哪些分盘和宫位?", + "事业主轴是什么?", + "哪类阶段更容易爆发?" + ], + "subject": "Angelina Jolie" + }, + { + "birth": { + "date": "1963-12-18", + "place": "Shawnee, OK, USA", + "source_policy": "public_record_candidate", + "time": "06:31" + }, + "case_id": "brad_pitt", + "domains": [ + "marriage", + "career", + "wealth" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "婚恋关系中应看哪些印度占星指标?", + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "财富来源和风险是什么?" + ], + "subject": "Brad Pitt" + }, + { + "birth": { + "date": "1981-09-26", + "place": "Saginaw, MI, USA", + "source_policy": "public_record_candidate", + "time": "20:28" + }, + "case_id": "serena_williams", + "domains": [ + "career", + "health", + "annual" + ], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed" + ], + "prompts": [ + "事业主轴是什么?", + "哪类阶段更容易爆发?", + "健康主题只能如何非医疗表达?", + "年度运势应如何避免过度承诺?" + ], + "subject": "Serena Williams" + } + ], + "claim_status": "ready_contract", + "created_at": "2026-07-20", + "production_tuning_allowed": false, + "scope": "real_case_website_e2e_eval", + "truth_matrix_allowed": false +} diff --git a/scripts/muhurta_numeric_candidate_capture_packet.py b/scripts/muhurta_numeric_candidate_capture_packet.py new file mode 100644 index 00000000..ce74fbc8 --- /dev/null +++ b/scripts/muhurta_numeric_candidate_capture_packet.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +"""Create CI-safe capture packets for Muhurta numeric source candidates.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path +from typing import Any + + +ROOT = Path(__file__).resolve().parents[1] +TRIAGE = ROOT / "references/oracle/public_worked_example_source_triage_2026_07_20.json" +OUT = ROOT / "references/oracle/muhurta_numeric_candidate_capture_packet_2026_07_20.json" + + +def sha(obj: Any) -> str: + return hashlib.sha256(json.dumps(obj, ensure_ascii=False, sort_keys=True).encode("utf-8")).hexdigest() + + +def next_path(source_id: str) -> str: + return f"references/oracle/artifacts/{source_id}_raw_capture_packet.json" + + +def build(date: str) -> dict[str, Any]: + triage = json.loads(TRIAGE.read_text(encoding="utf-8")) + rows = [] + for src in triage["sources"]: + if src["domain"] != "muhurta_factor_scoring" or not src["numeric_fields_present"]: + continue + request = { + "source_id": src["source_id"], + "url": src["url"], + "topic": src["topic"], + "observed_numeric_fields": src["observed_numeric_fields"], + } + missing = list(src["missing_for_oracle"]) + for field in ["raw_capture_hash", "exact_method_settings", "replay_comparison"]: + if field not in missing: + missing.append(field) + rows.append( + { + "source_id": src["source_id"], + "domain": src["domain"], + "topic": src["topic"], + "url": src["url"], + "source_observation_hash": src["observation_hash"], + "canonical_request_hash": sha(request), + "observed_numeric_fields": src["observed_numeric_fields"], + "raw_capture_status": "pending_raw_page_capture", + "upgrade_status": "not_oracle_ready", + "missing_for_oracle": missing, + "next_artifact_path": next_path(src["source_id"]), + "claim_boundary": "Numeric-looking public source; not oracle-ready until raw page, exact settings, hash, and local replay comparison are archived.", + } + ) + return { + "scope": "muhurta_numeric_candidate_capture_packet", + "created_at": date, + "status": "capture_packet_ready", + "claim_status": "source_intake_only", + "production_tuning_allowed": False, + "truth_matrix_allowed": False, + "sources": {"source_triage": str(TRIAGE.relative_to(ROOT))}, + "summary": { + "candidate_count": len(rows), + "oracle_ready_count": 0, + "pending_raw_capture_count": sum(1 for row in rows if row["raw_capture_status"] == "pending_raw_page_capture"), + }, + "capture_rows": rows, + "boundary": "Capture packet staging only; does not calculate or validate Muhurta verdicts.", + } + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--date", default="2026-07-20") + args = parser.parse_args() + print(json.dumps(build(args.date), ensure_ascii=False, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/prashna_oracle_queue.py b/scripts/prashna_oracle_queue.py new file mode 100644 index 00000000..bed9023c --- /dev/null +++ b/scripts/prashna_oracle_queue.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +"""Create Prashna input contract and numeric oracle candidate queue.""" +from __future__ import annotations +import argparse, hashlib, json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +CONTRACT = ROOT / "references/oracle/prashna_input_contract_2026_07_20.json" +QUEUE = ROOT / "references/oracle/prashna_numeric_oracle_packet_queue_2026_07_20.json" + +def h(obj): + return hashlib.sha256(json.dumps(obj, ensure_ascii=False, sort_keys=True).encode()).hexdigest() + +def build(date: str): + contract = { + "scope": "prashna_input_contract", + "created_at": date, + "status": "contract_ready", + "claim_status": "ready_contract", + "production_tuning_allowed": False, + "truth_matrix_allowed": False, + "required_fields": [ + {"field": "question_datetime_local", "format": "YYYY-MM-DDTHH:MM:SS", "boundary": "exact time question is received/accepted"}, + {"field": "location", "format": "lat/lon + place label", "boundary": "place of querent/astrologer must be explicit"}, + {"field": "timezone", "format": "IANA or UTC offset", "boundary": "no implicit local machine timezone"}, + {"field": "ayanamsa", "format": "named sidereal ayanamsa", "boundary": "default must be recorded, e.g. Lahiri"}, + {"field": "node_mode", "format": "mean|true", "boundary": "Rahu/Ketu mode must be frozen"}, + ], + "optional_fields": ["question_text", "querent_id", "house_focus", "language"], + "claim_boundary": "Input contract only; does not validate Prashna predictions or external numeric parity.", + } + rows = [ + { + "source_id": "vedastro_prasna_marga_ch5_sphuta_example", + "domain": "horary_annual_sensitive_points", + "technique_family": "sphuta_trisphuta_family", + "url": "https://vedastro.org/book/PrasnaMarga/Chapter5", + "source_role": "public_numeric_candidate", + "numeric_fields_present": True, + "expected_values": { + "sun": "4s 3° 8' 25\"", + "moon": "3s 19° 36' 34\"", + "lagna": "3s 27° 22'", + "gulika": "3s 14° 10'", + "rahu": "3s 8° 16'", + "trisphuta": "11s 1° 8' 34\"", + "chatusphuta": "2s 15° 18' 34\"", + "panchasphuta": "5s 23° 34' 34\"", + }, + "missing_for_oracle": ["complete_prashna_input", "ayanamsa", "node_mode", "timezone", "raw_capture_hash", "local_replay", "pyjhora_or_other_legal_replay"], + "upgrade_status": "candidate_not_oracle", + "candidate_hash": "", + "claim_boundary": "Numeric Sphuta example exists, but full Prashna input/settings are incomplete; use as candidate only.", + } + ] + for row in rows: + row["candidate_hash"] = h(row) + queue = { + "scope": "prashna_numeric_oracle_packet_queue", + "created_at": date, + "status": "queue_ready", + "claim_status": "open_queue", + "production_tuning_allowed": False, + "truth_matrix_allowed": False, + "summary": {"candidate_count": len(rows), "numeric_candidate_count": sum(r["numeric_fields_present"] for r in rows), "oracle_ready_count": 0}, + "rows": rows, + "boundary": "Queue only; no Prashna/Saham/Gulika/Sphuta claim is upgraded until complete input, raw/hash and local/external replay close.", + } + return {"contract": contract, "queue": queue} + +def main(): + ap=argparse.ArgumentParser(); ap.add_argument("--date", default="2026-07-20"); args=ap.parse_args() + data=build(args.date) + CONTRACT.write_text(json.dumps(data["contract"], ensure_ascii=False, indent=2, sort_keys=True)+"\n") + QUEUE.write_text(json.dumps(data["queue"], ensure_ascii=False, indent=2, sort_keys=True)+"\n") + print(json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True)) +if __name__ == "__main__": main() diff --git a/scripts/real_case_website_e2e_eval.py b/scripts/real_case_website_e2e_eval.py new file mode 100644 index 00000000..d6f61d12 --- /dev/null +++ b/scripts/real_case_website_e2e_eval.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +"""Build a public-real-case website E2E evaluation contract.""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path +from typing import Any + + +CASES = [ + ("steve_jobs", "Steve Jobs", "1955-02-24", "19:15", "San Francisco, CA, USA", ["career", "wealth", "timing"]), + ("albert_einstein", "Albert Einstein", "1879-03-14", "11:30", "Ulm, Germany", ["education", "career", "timing"]), + ("barack_obama", "Barack Obama", "1961-08-04", "19:24", "Honolulu, HI, USA", ["career", "migration", "annual"]), + ("princess_diana", "Princess Diana", "1961-07-01", "19:45", "Sandringham, England", ["marriage", "family", "timing"]), + ("donald_trump", "Donald Trump", "1946-06-14", "10:54", "Queens, NY, USA", ["career", "wealth", "annual"]), + ("oprah_winfrey", "Oprah Winfrey", "1954-01-29", "04:30", "Kosciusko, MS, USA", ["career", "wealth", "family"]), + ("elon_musk", "Elon Musk", "1971-06-28", "07:30", "Pretoria, South Africa", ["career", "migration", "wealth"]), + ("mahatma_gandhi", "Mahatma Gandhi", "1869-10-02", "07:11", "Porbandar, India", ["career", "migration", "timing"]), + ("marilyn_monroe", "Marilyn Monroe", "1926-06-01", "09:30", "Los Angeles, CA, USA", ["marriage", "career", "health"]), + ("bill_gates", "Bill Gates", "1955-10-28", "22:00", "Seattle, WA, USA", ["career", "wealth", "education"]), + ("j_k_rowling", "J. K. Rowling", "1965-07-31", "14:00", "Yate, England", ["career", "wealth", "timing"]), + ("nelson_mandela", "Nelson Mandela", "1918-07-18", "14:54", "Mvezo, South Africa", ["career", "timing", "migration"]), + ("mother_teresa", "Mother Teresa", "1910-08-26", "14:25", "Skopje, North Macedonia", ["career", "migration", "health"]), + ("michael_jackson", "Michael Jackson", "1958-08-29", "19:33", "Gary, IN, USA", ["career", "wealth", "health"]), + ("queen_elizabeth_ii", "Queen Elizabeth II", "1926-04-21", "02:40", "London, England", ["career", "family", "annual"]), + ("john_f_kennedy", "John F. Kennedy", "1917-05-29", "15:00", "Brookline, MA, USA", ["career", "family", "health"]), + ("martin_luther_king_jr", "Martin Luther King Jr.", "1929-01-15", "12:00", "Atlanta, GA, USA", ["career", "timing", "health"]), + ("angelina_jolie", "Angelina Jolie", "1975-06-04", "09:09", "Los Angeles, CA, USA", ["marriage", "family", "career"]), + ("brad_pitt", "Brad Pitt", "1963-12-18", "06:31", "Shawnee, OK, USA", ["marriage", "career", "wealth"]), + ("serena_williams", "Serena Williams", "1981-09-26", "20:28", "Saginaw, MI, USA", ["career", "health", "annual"]), +] + + +QUESTION_MATRIX = { + "career": ["事业主轴是什么?", "哪类阶段更容易爆发?"], + "wealth": ["财富来源和风险是什么?"], + "marriage": ["婚恋关系中应看哪些印度占星指标?"], + "health": ["健康主题只能如何非医疗表达?"], + "migration": ["迁移/海外发展应看哪些宫位和 Dasha?"], + "family": ["家庭/子女主题应调用哪些分盘和宫位?"], + "education": ["学习与教育路径怎么看?"], + "timing": ["历史关键阶段能否用 Dasha + Narayana 回看?"], + "annual": ["年度运势应如何避免过度承诺?"], +} + + +def build(date: str) -> dict[str, Any]: + cases = [] + for case_id, subject, date_s, time_s, place, domains in CASES: + cases.append( + { + "case_id": case_id, + "subject": subject, + "birth": {"date": date_s, "time": time_s, "place": place, "source_policy": "public_record_candidate"}, + "domains": domains, + "prompts": [q for d in domains for q in QUESTION_MATRIX[d]], + "expected_runtime_context": [ + "birth_input_contract", + "ayanamsa_node_mode", + "D1", + "D9_or_relevant_varga", + "Dasha", + "Narayana_Dasha_for_timing", + "functional_benefic_malefic", + "claim_boundary", + "similar_case_reference_allowed", + ], + } + ) + return { + "scope": "real_case_website_e2e_eval", + "created_at": date, + "claim_status": "ready_contract", + "production_tuning_allowed": False, + "truth_matrix_allowed": False, + "case_count": len(cases), + "cases": cases, + "acceptance_rules": [ + "Website must save/render input contract and runtime context JSON for each prompt.", + "Answers may use public cases as explanation references, not prediction proof.", + "Precise day/month claims must stay exploratory_unvalidated unless holdout closes.", + "Marriage/career/wealth/health/migration/family/education/timing/annual domains must route to matching technique context.", + "Any Shadbala/AV/KP conflict must be described as method/source difference, not majority-vote truth.", + ], + "boundary": "Product E2E quality harness only; not an accuracy benchmark or independent holdout.", + } + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--date", default="2026-07-20") + args = parser.parse_args() + print(json.dumps(build(args.date), ensure_ascii=False, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_muhurta_numeric_candidate_capture_packet.py b/tests/test_muhurta_numeric_candidate_capture_packet.py new file mode 100644 index 00000000..470400de --- /dev/null +++ b/tests/test_muhurta_numeric_candidate_capture_packet.py @@ -0,0 +1,44 @@ +import json +import subprocess +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +ARTIFACT = ROOT / "references" / "oracle" / "muhurta_numeric_candidate_capture_packet_2026_07_20.json" +INDEX = ROOT / "references" / "oracle" / "evidence_packet_index_2026_07_19.json" + + +def test_muhurta_numeric_candidate_capture_packet_selects_only_numeric_muhurta_sources(): + data = json.loads( + subprocess.check_output( + ["python3", "scripts/muhurta_numeric_candidate_capture_packet.py", "--date", "2026-07-20"], + cwd=ROOT, + text=True, + ) + ) + assert data["scope"] == "muhurta_numeric_candidate_capture_packet" + assert data["claim_status"] == "source_intake_only" + assert data["summary"]["candidate_count"] == 2 + assert data["summary"]["oracle_ready_count"] == 0 + assert data["production_tuning_allowed"] is False + ids = {row["source_id"] for row in data["capture_rows"]} + assert ids == {"mypanchang_edison_2025_panchangam", "drikpanchang_mumbai_rahu_2026_07_20"} + + +def test_muhurta_numeric_candidate_capture_packet_has_hashes_and_replay_blockers(): + data = json.loads(ARTIFACT.read_text(encoding="utf-8")) + for row in data["capture_rows"]: + assert row["source_observation_hash"] + assert row["canonical_request_hash"] + assert row["raw_capture_status"] == "pending_raw_page_capture" + assert row["upgrade_status"] == "not_oracle_ready" + assert "raw_capture_hash" in row["missing_for_oracle"] + assert "replay_comparison" in row["missing_for_oracle"] + assert row["next_artifact_path"].startswith("references/oracle/artifacts/") + + +def test_muhurta_numeric_candidate_capture_packet_is_indexed(): + packets = {row["packet_id"]: row for row in json.loads(INDEX.read_text(encoding="utf-8"))["packets"]} + packet = packets["muhurta_numeric_candidate_capture_packet_2026_07_20"] + assert packet["domain"] == "muhurta_factor_scoring" + assert packet["claim_status"] == "source_intake_only" diff --git a/tests/test_prashna_input_contract_and_oracle_queue.py b/tests/test_prashna_input_contract_and_oracle_queue.py new file mode 100644 index 00000000..59e38f8f --- /dev/null +++ b/tests/test_prashna_input_contract_and_oracle_queue.py @@ -0,0 +1,36 @@ +import json +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +CONTRACT = ROOT / "references/oracle/prashna_input_contract_2026_07_20.json" +QUEUE = ROOT / "references/oracle/prashna_numeric_oracle_packet_queue_2026_07_20.json" +INDEX = ROOT / "references/oracle/evidence_packet_index_2026_07_19.json" + + +def test_prashna_contract_requires_time_place_timezone_ayanamsa_node(): + data = json.loads(subprocess.check_output(["python3", "scripts/prashna_oracle_queue.py", "--date", "2026-07-20"], cwd=ROOT, text=True)) + contract = data["contract"] + assert contract["scope"] == "prashna_input_contract" + required = {row["field"] for row in contract["required_fields"]} + assert {"question_datetime_local", "location", "timezone", "ayanamsa", "node_mode"}.issubset(required) + assert contract["claim_status"] == "ready_contract" + + +def test_prashna_queue_keeps_public_numeric_examples_candidate_only(): + queue = json.loads(QUEUE.read_text(encoding="utf-8")) + assert queue["scope"] == "prashna_numeric_oracle_packet_queue" + assert queue["claim_status"] == "open_queue" + assert queue["summary"]["numeric_candidate_count"] >= 1 + assert queue["summary"]["oracle_ready_count"] == 0 + example = next(row for row in queue["rows"] if row["source_id"] == "vedastro_prasna_marga_ch5_sphuta_example") + assert example["numeric_fields_present"] is True + assert "trisphuta" in example["expected_values"] + assert "complete_prashna_input" in example["missing_for_oracle"] + assert example["upgrade_status"] == "candidate_not_oracle" + + +def test_prashna_contract_and_queue_are_indexed(): + packets = {row["packet_id"]: row for row in json.loads(INDEX.read_text(encoding="utf-8"))["packets"]} + assert packets["prashna_input_contract_2026_07_20"]["claim_status"] == "ready_contract" + assert packets["prashna_numeric_oracle_packet_queue_2026_07_20"]["claim_status"] == "open_queue" diff --git a/tests/test_real_case_website_e2e_eval.py b/tests/test_real_case_website_e2e_eval.py new file mode 100644 index 00000000..6546a920 --- /dev/null +++ b/tests/test_real_case_website_e2e_eval.py @@ -0,0 +1,32 @@ +import json +import subprocess +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +ARTIFACT = ROOT / "references/real_case_calibration/real_case_website_e2e_eval_2026_07_20.json" +INDEX = ROOT / "references/oracle/evidence_packet_index_2026_07_19.json" + + +def test_real_case_website_e2e_eval_builds_twenty_case_contract(): + data = json.loads(subprocess.check_output(["python3", "scripts/real_case_website_e2e_eval.py"], cwd=ROOT, text=True)) + assert data["scope"] == "real_case_website_e2e_eval" + assert data["case_count"] == 20 + assert data["claim_status"] == "ready_contract" + assert data["truth_matrix_allowed"] is False + assert data["production_tuning_allowed"] is False + + +def test_real_case_website_e2e_eval_requires_core_runtime_context(): + data = json.loads(ARTIFACT.read_text(encoding="utf-8")) + required = {"D1", "Dasha", "functional_benefic_malefic", "claim_boundary", "similar_case_reference_allowed"} + assert all(required <= set(case["expected_runtime_context"]) for case in data["cases"]) + domains = {domain for case in data["cases"] for domain in case["domains"]} + assert {"career", "wealth", "marriage", "health", "migration", "family", "education", "timing", "annual"} <= domains + + +def test_real_case_website_e2e_eval_is_indexed(): + packets = {row["packet_id"]: row for row in json.loads(INDEX.read_text(encoding="utf-8"))["packets"]} + packet = packets["real_case_website_e2e_eval_2026_07_20"] + assert packet["claim_status"] == "ready_contract" + assert "not an accuracy benchmark" in packet["claim_boundary"]