fix(jaimini): 8-karaka order follows BPHS ch. 32 (PiK 5th, DK 8th) (T6, BUG-1204)

KARAKA_8 put Putrakaraka 5th, Darakaraka 7th and Pitrukaraka 8th. BPHS ch. 32
order with Rahu counted is AK, AmK, BK, MK, PiK, PK, GK, DK. Test pins the
table and a public AA chart (Steve Jobs, Raman, mean nodes) plus the reader
report's live 8-karaka rows. jaimini.py is in the frozen rectification identity;
re-freeze follows in a separate commit (rectification does not read karakas).

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:
Jesse_Chen
2026-10-03 11:33:16 +08:00
co-authored by Claude Opus 5.5
parent 60d065a8cf
commit 0cf2249e6b
2 changed files with 78 additions and 2 deletions
+5 -2
View File
@@ -49,10 +49,13 @@ KARAKA_7 = {
7: 'Darakaraka', # DK - 配偶(度数最低)
}
# 8星制(含Rahu,用绝对度数)
# 8星制(含Rahu;Rahu 按 30° 减星座内度数排位)。BPHS 第 32 章次序:
# AK、AmK、BK、MK、PiK、PK、GK、DK,即 PiK 第 5、PK 第 6、GK 第 7、DK 第 8
# (度数最低者为 DK)。旧表把第 5/7/8 位写成 PK/DK/PiK(BUG-1204,上游
# yinduzhanxing 同样写错)。
KARAKA_8 = {
1: 'Atmakaraka', 2: 'Amatyakaraka', 3: 'Bhratrikaraka', 4: 'Matrikaraka',
5: 'Putrakaraka', 6: 'Gnatikaraka', 7: 'Darakaraka', 8: 'Pitrukaraka',
5: 'Pitrukaraka', 6: 'Putrakaraka', 7: 'Gnatikaraka', 8: 'Darakaraka',
}
KARAKA_CN = {
+73
View File
@@ -0,0 +1,73 @@
"""8-karaka Chara Karaka order follows BPHS ch. 32 (BUG-1204).
BPHS ch. 32 (Karakas): with Rahu counted, the eight roles in descending
order of degrees are Atma, Amatya, Bhratru, Matru, Pitru, Putra, Gnati, Dara;
Rahu ranks by 30 minus its degree in sign. The old table put Putra 5th, Dara
7th and Pitru 8th (TASK-astrologer-rulings-batch1-20261003 T6).
Public chart: Steve Jobs, Astro-Databank AA (repository development case
library), Raman ayanamsa, mean nodes.
"""
from __future__ import annotations
import json
from pathlib import Path
from scripts.jaimini import KARAKA_7, KARAKA_8, calc_chara_karaka_8
from scripts.jyotish_engine import compute_chart_data
ROOT = Path(__file__).resolve().parents[1]
BPHS_8 = ["Atmakaraka", "Amatyakaraka", "Bhratrikaraka", "Matrikaraka",
"Pitrukaraka", "Putrakaraka", "Gnatikaraka", "Darakaraka"]
def _jobs_degrees() -> dict[str, float]:
cases = json.loads((ROOT / "references/real_case_calibration/minute_rectification_development_v1.json").read_text(encoding="utf-8"))["cases"]
birth = next(case for case in cases if case["case_id"] == "steve_jobs_1955_development")["birth"]
assert birth["source"]["rodden_rating"] == "AA"
year, month, day = (int(part) for part in birth["date"].split("-"))
hour, minute = (int(part) for part in birth["time"].split(":"))
chart, *_ = compute_chart_data(year, month, day, hour, minute, birth["latitude"], birth["longitude"],
birth["timezone_offset"], ayanamsa_name="raman")
return {name: row["degree_raw"] % 30 for name, row in chart["planets"].items()}
def test_table_is_the_bphs_order() -> None:
assert [KARAKA_8[rank] for rank in range(1, 9)] == BPHS_8
# The 7-karaka scheme (no Pitrukaraka) is unchanged.
assert [KARAKA_7[rank] for rank in range(1, 8)] == [
"Atmakaraka", "Amatyakaraka", "Bhratrikaraka", "Matrikaraka", "Putrakaraka", "Gnatikaraka", "Darakaraka"]
def test_public_chart_roles_follow_bphs_ranking() -> None:
degrees = _jobs_degrees()
effective = {name: (30.0 - value) % 30.0 if name == "Rahu" else value
for name, value in degrees.items() if name != "Ketu"}
expected_order = sorted(effective, key=effective.get, reverse=True)
table = calc_chara_karaka_8(degrees)["karaka_table_8"]
assert {role: row["planet"] for role, row in table.items()} == dict(zip(BPHS_8, expected_order))
assert {role: row["rank"] for role, row in table.items()} == {role: rank for rank, role in enumerate(BPHS_8, 1)}
# Lowest effective degree is Dara; Pitru sits between Matru and Putra.
assert table["Darakaraka"]["planet"] == min(effective, key=effective.get)
assert table["Matrikaraka"]["effective_degree_in_sign"] >= table["Pitrukaraka"]["effective_degree_in_sign"] >= table["Putrakaraka"]["effective_degree_in_sign"]
# This chart's own values (Raman, mean nodes): Rahu at 10.72° ranks by 19.28°.
assert table["Pitrukaraka"]["planet"] == "Rahu"
assert table["Darakaraka"]["planet"] == "Mars"
assert table["Putrakaraka"]["planet"] == "Moon"
def test_reader_report_karaka_table_is_in_bphs_order() -> None:
"""Live render of a fictional chart: the reader's 8-karaka rows run AK..DK."""
import copy
from scripts.jaimini import KARAKA_CN
from scripts.pl9_reader_export import _pl9_export_markdown_for_edition
from tests.test_report_english_edition import CASES, _packet
packet = _packet(CASES["day"])
markdown = _pl9_export_markdown_for_edition(copy.deepcopy(packet), "reader_main")
lines = markdown.splitlines()
start = next(i for i, line in enumerate(lines) if line.startswith("### Jaimini Karaka"))
rows = [line for line in lines[start + 1:start + 14] if line.startswith("| ") and "星" in line.split("|")[1]]
assert [row.split("|")[1].strip() for row in rows] == [KARAKA_CN[role] for role in BPHS_8]