feat(tajika): label the year lord as a Muntha-lord stand-in for Panchavargiya (T9, BUG-1212)
Astrologer ruling 甲11. Muntha stays natal Lagna + completed years (test pins it on the main path; muntha.calc_muntha_from_sun_sign is imported nowhere). Panchavargiya is not implemented (native producer blocked). Consultation annual layer gains varshesha_basis '暂用 Muntha 主星;占星师口径为 Panchavargiya,待接入' (card keys and the workflow allowlist carry it); reader report 'Selection basis' row says the same in both annual sections (zh/en). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b0329ef03e
commit
eb00b0f70f
@@ -490,7 +490,7 @@ const DOUBLE_TRANSIT_ROW_KEYS = ["layer", "target", "strength", "jupiter_pac", "
|
||||
const DOUBLE_TRANSIT_ALL_KEYS = ["house", "layer", "target", "strength"] as const;
|
||||
const KARAKA_TARGET_KEYS = ["target", "jupiter_pac", "saturn_pac", "double_transit"] as const;
|
||||
const ANNUAL_KEYS = [
|
||||
"status", "varsha_year", "annual_lagna", "varshesha", "muntha", "mudda_dasha", "tajika_aspects", "boundary",
|
||||
"status", "varsha_year", "annual_lagna", "varshesha", "varshesha_basis", "muntha", "mudda_dasha", "tajika_aspects", "boundary",
|
||||
] as const;
|
||||
|
||||
function nonEmpty(value: JsonRecord) {
|
||||
|
||||
@@ -548,6 +548,8 @@ const nativeDoubleTransitKeys = new Set([
|
||||
]);
|
||||
const nativeAnnualKeys = new Set([
|
||||
"status", "reason", "source", "targetyear", "age", "varshayear", "start", "end", "annuallagna", "varshesha",
|
||||
// BUG-1212: how the year lord was chosen (Muntha lord for now; Panchavargiya pending).
|
||||
"varsheshabasis",
|
||||
"muntha", "sign", "lord", "houseinannualchart", "houseinnatalchart", "muddadasha", "months",
|
||||
"tajikaaspects", "name", "planets", "aspect", "motion", "tajikaaspectsstatus", "producers",
|
||||
"solarreturn", "annualchart", "yearlord", "tajikayogas", "boundary",
|
||||
|
||||
@@ -71,6 +71,12 @@ YOGA_PACKET_DOMAINS = {
|
||||
"raman_bvr_relationship_mother_batch_closure_packet_2026_08_20.json": "parents",
|
||||
"raman_bvr_relationship_sibling_core_batch_closure_packet_2026_08_20.json": "siblings",
|
||||
}
|
||||
# BUG-1212 (ruling 甲11): the year lord shown is the Muntha sign lord; the
|
||||
# astrologer's rule is Panchavargiya (strongest of five office-bearers), whose
|
||||
# native producer is still blocked. Shown wherever the year lord is shown.
|
||||
YEAR_LORD_BASIS = "暂用 Muntha 主星;占星师口径为 Panchavargiya,待接入"
|
||||
YEAR_LORD_BASIS_EN = "Muntha sign lord for now; the astrologer's rule is Panchavargiya, not yet wired"
|
||||
|
||||
TAJIKA_BOUNDARY = (
|
||||
"parameter_sensitive: Tajika / Varshaphala is verified on the first target set only, "
|
||||
"not a global closure; annual structure, not an event verdict"
|
||||
@@ -944,6 +950,7 @@ def build_annual_tajika(birth_payload: dict, chart: dict, *, reference: datetime
|
||||
"varsha_year": {"start": start.strftime("%Y-%m-%d"), "end": end.strftime("%Y-%m-%d")},
|
||||
"annual_lagna": annual_chart.get("asc_sign"),
|
||||
"varshesha": year_lord,
|
||||
"varshesha_basis": YEAR_LORD_BASIS,
|
||||
"muntha": {
|
||||
"sign": muntha.get("muntha_sign"),
|
||||
"lord": muntha.get("muntha_lord"),
|
||||
|
||||
@@ -147,6 +147,7 @@ _PHRASES: dict[str, str] = {
|
||||
"| 要素总数 |": "| Total elements |",
|
||||
# ── annual labels and values ──
|
||||
"Muntha 所在星座的守护星(当前本地口径)": "Ruler of the Muntha sign (current local method)",
|
||||
"暂用 Muntha 主星;占星师口径为 Panchavargiya,待接入": "Muntha sign lord for now; the astrologer's rule is Panchavargiya, not yet wired",
|
||||
"两种计算口径给出的年主不同,暂不合并": "The two methods give different year lords; not merged",
|
||||
"(两者不同)": " (they differ)",
|
||||
"太阳返照": "Solar return",
|
||||
|
||||
@@ -580,7 +580,8 @@ def render_pl9_parity_markdown(packet: dict) -> str:
|
||||
if data.get('selection_basis'):
|
||||
return _cell(data['selection_basis'])
|
||||
if data.get('year_lord') and data['year_lord'] == muntha_data.get('muntha_lord'):
|
||||
return 'Muntha 所在星座的守护星(当前本地口径)'
|
||||
# BUG-1212 (甲11): say plainly that this is a stand-in for Panchavargiya.
|
||||
return '暂用 Muntha 主星;占星师口径为 Panchavargiya,待接入'
|
||||
return '-'
|
||||
|
||||
def _degree(value) -> str:
|
||||
@@ -2297,6 +2298,7 @@ def render_pl9_parity_markdown(packet: dict) -> str:
|
||||
if year_lord_data:
|
||||
lines.extend([
|
||||
f"| Varshesha | {_cell(_annual_field_text(year_lord, 'year_lord', 'lord'))} |",
|
||||
f"| Selection basis | {_cell(_annual_selection_basis(year_lord, annual_pack.get('muntha')))} |",
|
||||
f"| Muntha sign | {_cell(_annual_field_text(annual_pack.get('muntha'), 'muntha_sign'))} |",
|
||||
])
|
||||
lines.append('')
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
"""Year lord is labelled as a Muntha-lord stand-in for Panchavargiya (BUG-1212).
|
||||
|
||||
Astrologer rulings 2026-10-03 甲11: Muntha = natal Lagna + completed years
|
||||
(kept); year lord by Panchavargiya is not implemented (native producer blocked),
|
||||
so every surface that shows the year lord says so. Fictional chart.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import re
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from scripts.consultation_native_layers import YEAR_LORD_BASIS, 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]
|
||||
|
||||
|
||||
def test_report_shows_the_basis_in_both_editions() -> None:
|
||||
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")
|
||||
assert zh.count("| Selection basis | 暂用 Muntha 主星;占星师口径为 Panchavargiya,待接入 |") >= 1
|
||||
assert "| Selection basis | Muntha sign lord for now; the astrologer's rule is Panchavargiya, not yet wired |" in en
|
||||
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"
|
||||
assert annual["varshesha_basis"] == YEAR_LORD_BASIS
|
||||
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"]]
|
||||
assert report["year_lord"]["year_lord"] == muntha["muntha_lord"]
|
||||
|
||||
|
||||
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 == []
|
||||
Reference in New Issue
Block a user