Files
Jyotisha/tests/test_year_lord_basis_label.py
T
Jesse_ChenandClaude Opus 5.5 0afcc2d9a3 feat(tajika): year lord by the Panchadhikari rule, ported from upstream c7117f92 (BUG-1214)
Round-4 astrologer ruling Q3. tajika.calc_panchadhikari_year_lord and its
missing pieces (Tri-Rasi tables, planet index maps, ayanamsa-aware PyJHora
lookups) plus references/tajika_panchavargiya_rules.json (blob e8c15ac3) are
ported verbatim from yinduzhanxing c7117f92, with one keyword added
(muntha_sign_idx): upstream builds the Muntha-lord candidate from the annual
Lagna + years; ours stays natal Lagna + completed years (BUG-1212).

Both annual producers (solar_return_full_report, cmd_tajika) call the new
tajika_year_lord.select_annual_year_lord, so the pack conflict gate compares
the same rule. Output carries candidates / candidate_list with Panchavargiya
score and engine, aspect flags, selection_basis and a one-sentence basis
(zh/en). The product path always uses the native proxy (PyJHora is AGPL, absent
from the API image and CI); JYOTISH_YEAR_LORD_PYJHORA_REFERENCE=1 restores the
upstream PyJHora lookup for research. Card varshesha_basis and the report
'Selection basis' rows show the sentence; the BUG-1212 stand-in label is gone.
Mudda Dasha and Tri-Pataka follow the selected year lord.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
2026-10-03 16:30:28 +08:00

99 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Year lord shows its selection basis on every surface (BUG-1212 → BUG-1214).
Astrologer rulings 2026-10-03 甲11 and round-4 Q3: Muntha = natal Lagna +
completed years (kept); the year lord is chosen by the Panchadhikari rule
(`tajika_year_lord`), and the card and both report editions carry its
one-sentence basis instead of the BUG-1212 "Muntha lord for now" label.
Fictional chart.
"""
from __future__ import annotations
import copy
import re
from datetime import datetime
from pathlib import Path
import pytest
from scripts.consultation_native_layers import build_annual_tajika
from scripts.pl9_reader_export import _pl9_export_markdown_for_edition
from scripts.solar_return import SIGNS, solar_return_full_report
from tests.test_report_english_edition import CASES, _packet
ROOT = Path(__file__).resolve().parents[1]
@pytest.fixture(autouse=True)
def _native_panchavargiya(monkeypatch):
# Product path: native-proxy Panchavargiya unless the research opt-in is set.
monkeypatch.delenv("JYOTISH_YEAR_LORD_PYJHORA_REFERENCE", raising=False)
def test_report_shows_the_basis_in_both_editions() -> None:
# 原值:两版都断言「暂用 Muntha 主星;占星师口径为 Panchavargiya,待接入」
# 新值:断言 Panchadhikari 选法依据一句话(中文版含「年盘上升」与「本地近似计算」,
# 英文版是同一句的英文、不含中文)
# 原因:BUG-1214 接入 Panchadhikari 年主选法,去掉 BUG-1212 的暂用标注(任务书 T2)
packet = _packet(CASES["day"])
zh = _pl9_export_markdown_for_edition(copy.deepcopy(packet), "reader_main")
english = copy.deepcopy(packet)
english["report_language"] = "en"
en = _pl9_export_markdown_for_edition(english, "reader_main")
zh_rows = [line for line in zh.splitlines() if line.startswith("| Selection basis |")]
en_rows = [line for line in en.splitlines() if line.startswith("| Selection basis |")]
assert zh_rows and all("年盘上升" in row and "Panchavargiya 为本地近似计算" in row for row in zh_rows)
assert en_rows and all("annual Lagna" in row and "local approximation" in row for row in en_rows)
assert not re.search(r"[\u4e00-\u9fff]", "\n".join(en_rows))
assert "暂用 Muntha 主星" not in zh
assert zh.count("| Varshesha |") == zh.count("| Selection basis |")
def test_consultation_annual_card_carries_the_basis() -> None:
case = CASES["day"]
payload = {key: case[key] for key in ("year", "month", "day", "hour", "minute", "second", "lat", "lon", "tz", "ayanamsa", "node_mode")}
from scripts.jyotish_engine import compute_chart_data
chart, *_ = compute_chart_data(case["year"], case["month"], case["day"], case["hour"], case["minute"],
case["lat"], case["lon"], case["tz"], ayanamsa_name=case["ayanamsa"])
annual = build_annual_tajika(payload, chart, reference=datetime(2026, 10, 3))
assert annual["status"] == "parameter_sensitive"
# 原值:varshesha_basis == YEAR_LORD_BASIS(「暂用 Muntha 主星…待接入」)
# 新值:varshesha_basis 是年主选法依据一句话(tajika_year_lord.selection_basis_text)
# 原因:BUG-1214(任务书 T2)
assert "年盘上升" in annual["varshesha_basis"] and "暂用" not in annual["varshesha_basis"]
assert annual["varshesha_basis"].endswith("(Panchavargiya 为本地近似计算)")
card = (ROOT / "frontend/src/lib/consultation-evidence-card.ts").read_text(encoding="utf-8")
assert '"varshesha", "varshesha_basis"' in card
workflow = (ROOT / "frontend/src/mastra/consultation-workflow.ts").read_text(encoding="utf-8")
assert '"varsheshabasis"' in workflow
def test_main_path_muntha_is_natal_lagna_plus_completed_years() -> None:
from scripts.jyotish_engine import compute_chart_data
case = CASES["day"]
report = solar_return_full_report(case["year"], case["month"], case["day"], case["hour"], case["minute"],
case["lat"], case["lon"], case["tz"], 2026, ayanamsa_name="raman")
_chart, natal_asc, *_ = compute_chart_data(case["year"], case["month"], case["day"], case["hour"], case["minute"],
case["lat"], case["lon"], case["tz"], ayanamsa_name="raman")
muntha = report["muntha"]
completed = 2026 - case["year"]
assert (muntha["natal_asc_sign_idx"], muntha["age"]) == (natal_asc, completed)
assert muntha["muntha_sign_idx"] == (natal_asc + completed) % 12
assert muntha["muntha_sign"] == SIGNS[muntha["muntha_sign_idx"]]
# 原值:年主 == Muntha 主星
# 新值:年主由 Panchadhikari 选出;Muntha 主星一定在候选里(来源 muntha_lord),
# 候选 Muntha 用的是「本命上升 + 已满年数」
# 原因:BUG-1214(第四轮问 3)
year_lord = report["year_lord"]
assert year_lord["muntha_basis"] == "natal_ascendant_plus_completed_years"
assert year_lord["muntha_sign_idx"] == muntha["muntha_sign_idx"]
planets = {row["planet"] for row in year_lord["candidates"]}
assert muntha["muntha_lord"] in planets and year_lord["year_lord"] in planets
def test_sun_sign_muntha_variant_is_off_the_main_path() -> None:
pattern = re.compile(r"^\s*(from\s+(scripts\.)?muntha\s+import|import\s+(scripts\.)?muntha\b)|_load_local_module\(['\"]muntha['\"]\)", re.MULTILINE)
offenders = [path.name for path in (ROOT / "scripts").glob("*.py") if path.name != "muntha.py" and pattern.search(path.read_text(encoding="utf-8"))]
assert offenders == []