merge: upstream sync 10 into the data audit branch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y # Conflicts: # docs/BUG_HISTORY.md
This commit is contained in:
@@ -13,8 +13,8 @@ def cmd_narayana_dasha(args, chart_data):
|
||||
narayana-dasha 子命令:计算并报告 Narayana Dasha(Rishi Dasha)。
|
||||
|
||||
用法:
|
||||
python jyotish_engine.py narayana-dasha --year REDACTED_YEAR --month 4 --day 17 \\
|
||||
--hour 14 --minute 45 --lat 36.47 --lon 114.2 --tz 8 --age 33
|
||||
python jyotish_engine.py narayana-dasha --year 1935 --month 6 --day 21 \\
|
||||
--hour 11 --minute 0 --lat 44.486 --lon 1.842 --tz 1 --age 33
|
||||
"""
|
||||
if chart_data is None:
|
||||
return "\n".join([
|
||||
|
||||
@@ -5,8 +5,8 @@ cmd_solar_return: Solar Return (Varshaphala) CLI 子命令
|
||||
Jyotish Vedic Astrology Skill — v6.0.18
|
||||
|
||||
用法:
|
||||
python3 jyotish_engine.py solar-return --year REDACTED_YEAR --month 4 --day 17 \
|
||||
--hour 14 --minute 45 --lat 36.4667 --lon 114.2 --tz 8 --target-year 2026
|
||||
python3 jyotish_engine.py solar-return --year 1935 --month 6 --day 21 \
|
||||
--hour 11 --minute 0 --lat 44.486 --lon 1.842 --tz 1 --target-year 2026
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
+39
-13
@@ -587,7 +587,7 @@ def calc_dispositor_chain(planet_name, planets_data, max_depth=12):
|
||||
return chain
|
||||
|
||||
|
||||
def calc_inter_chart_linkage(planet_name, d1_data, d9_data, d10_data, d12_data=None, d1_asc_idx=None, d9_asc_idx=None, d10_asc_idx=None):
|
||||
def calc_inter_chart_linkage(planet_name, d1_data, d9_data, d10_data, d12_data=None, d1_asc_idx=None, d9_asc_idx=None, d10_asc_idx=None, d12_asc_idx=None):
|
||||
"""
|
||||
计算行星在 D1/D9/D10 分盘之间的飞星落宫。
|
||||
返回 {chart_type: {sign, house_in_chart, lord_of_sign_in_chart}}
|
||||
@@ -599,7 +599,8 @@ def calc_inter_chart_linkage(planet_name, d1_data, d9_data, d10_data, d12_data=N
|
||||
('D10', d10_data, d10_asc_idx),
|
||||
]
|
||||
if d12_data:
|
||||
charts.append(('D12', d12_data, None))
|
||||
# D12 houses count from the D12 ascendant (upstream cf6c316d / f60568a0).
|
||||
charts.append(('D12', d12_data, d12_asc_idx))
|
||||
|
||||
for chart_name, chart_data, asc_idx in charts:
|
||||
if not isinstance(chart_data, dict):
|
||||
@@ -608,9 +609,14 @@ def calc_inter_chart_linkage(planet_name, d1_data, d9_data, d10_data, d12_data=N
|
||||
if not isinstance(pdata, dict) or 'sign' not in pdata:
|
||||
continue
|
||||
sign = pdata['sign']
|
||||
sign_idx = SIGNS.index(sign) if sign in SIGNS else 0
|
||||
if sign not in SIGNS:
|
||||
# An unknown sign used to become Aries silently.
|
||||
raise ValueError(f'Unknown sign in {chart_name}: {sign!r}')
|
||||
sign_idx = SIGNS.index(sign)
|
||||
house = None
|
||||
if asc_idx is not None:
|
||||
if isinstance(asc_idx, bool) or not isinstance(asc_idx, int) or not 0 <= asc_idx < 12:
|
||||
raise ValueError(f'Invalid ascendant sign index in {chart_name}: {asc_idx!r}')
|
||||
house = ((sign_idx - asc_idx) % 12) + 1
|
||||
lord = SIGN_LORDS.get(sign, '')
|
||||
result[chart_name] = {
|
||||
@@ -655,7 +661,7 @@ def calc_all_dispositor_chains(planets_data):
|
||||
return result
|
||||
|
||||
|
||||
def calc_all_inter_chart_linkages(d1_data, d9_data, d10_data, d12_data=None, d1_asc_idx=None, d9_asc_idx=None, d10_asc_idx=None):
|
||||
def calc_all_inter_chart_linkages(d1_data, d9_data, d10_data, d12_data=None, d1_asc_idx=None, d9_asc_idx=None, d10_asc_idx=None, d12_asc_idx=None):
|
||||
"""
|
||||
为所有行星计算 D1/D9/D10 分盘间飞星。
|
||||
需要各分盘的 asc_idx 来正确计算落宫。
|
||||
@@ -664,7 +670,7 @@ def calc_all_inter_chart_linkages(d1_data, d9_data, d10_data, d12_data=None, d1_
|
||||
for pname in ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn', 'Rahu', 'Ketu']:
|
||||
result[pname] = calc_inter_chart_linkage(
|
||||
pname, d1_data, d9_data, d10_data, d12_data,
|
||||
d1_asc_idx, d9_asc_idx, d10_asc_idx
|
||||
d1_asc_idx, d9_asc_idx, d10_asc_idx, d12_asc_idx
|
||||
)
|
||||
return result
|
||||
|
||||
@@ -13765,6 +13771,12 @@ def cmd_kp(args):
|
||||
_apply_ayanamsa(requested_report_ayanamsa)
|
||||
return {"error": "swisseph未安装"}
|
||||
|
||||
# The chart's julian_day is rounded for display. KP cusp and sub-lord
|
||||
# boundaries use the civil instant itself, seconds included (upstream
|
||||
# 26d5a52d, BUG-1543). Same formula as compute_chart_data.
|
||||
jd = swe.julday(args.year, args.month, args.day,
|
||||
_birth_hour_decimal(args.hour, args.minute, _arg_second(args)) - args.tz)
|
||||
|
||||
asc_sign = chart.get("ascendant", {}).get("sign", "Aries")
|
||||
planets = chart.get("planets", {})
|
||||
planet_lons = {
|
||||
@@ -13778,7 +13790,8 @@ def cmd_kp(args):
|
||||
from bhava_chalit import BhavaChalitCalculator
|
||||
kp_house_calculator = BhavaChalitCalculator()
|
||||
asc_lon = chart.get('ascendant', {}).get('degree_raw', chart.get('ascendant', {}).get('degree', 0.0))
|
||||
boundaries = kp_house_calculator.calculate_bhava_boundaries(
|
||||
# Unrounded cusps; calculate_bhava_boundaries rounds them to 4 decimals.
|
||||
raw_cusps = kp_house_calculator.calculate_cusps(
|
||||
float(asc_lon), 0.0, 'placidus', jd, args.lat, args.lon,
|
||||
)
|
||||
bhava_chart = kp_house_calculator.get_bhava_chalit_chart(
|
||||
@@ -13792,16 +13805,19 @@ def cmd_kp(args):
|
||||
for pname, pdata in planets.items():
|
||||
if isinstance(pdata, dict) and 'sign' in pdata:
|
||||
bhava_row = bhava_planets.get(pname) if isinstance(bhava_planets.get(pname), dict) else {}
|
||||
raw_lon = planet_lons.get(pname)
|
||||
planet_positions[pname] = {
|
||||
'sign': pdata['sign'],
|
||||
'degree': pdata.get('degree_in_sign', pdata.get('degree', 0) % 30),
|
||||
# degree_in_sign is rounded to 4 decimals for display.
|
||||
'degree': (float(raw_lon) % 30 if raw_lon is not None
|
||||
else pdata.get('degree_in_sign', pdata.get('degree', 0) % 30)),
|
||||
'house': bhava_row.get('bhava_house', pdata.get('house', 1)),
|
||||
}
|
||||
|
||||
result = calc_kp_analysis(
|
||||
planet_positions,
|
||||
asc_sign,
|
||||
house_cusps=boundaries.get('cusps'),
|
||||
house_cusps=raw_cusps,
|
||||
house_occupancy_basis='cusp_to_cusp',
|
||||
)
|
||||
moon_lon = planets.get('Moon', {}).get('degree_raw', planets.get('Moon', {}).get('degree', 0.0)) if isinstance(planets.get('Moon'), dict) else 0.0
|
||||
@@ -15856,7 +15872,7 @@ def cmd_full_reading(args):
|
||||
|
||||
ic_result = calc_all_inter_chart_linkages(
|
||||
d1_for_dc, d9_for_ic, d10_for_ic, d12_for_ic,
|
||||
asc_idx, d9_asc_idx, d10_asc_idx
|
||||
asc_idx, d9_asc_idx, d10_asc_idx, d12_asc_idx
|
||||
)
|
||||
report['modules']['inter_chart_linkage'] = ic_result
|
||||
|
||||
@@ -16124,7 +16140,10 @@ def cmd_full_reading(args):
|
||||
from narayana_dasha import attach_narayana_method_comparison, narayana_dasha_full_report
|
||||
# 计算当前年龄(从出生到 today)
|
||||
birth_dt = _birth_datetime_from_args(args)
|
||||
today_dt = datetime.strptime(args.today, '%Y-%m-%d') if hasattr(args, 'today') and args.today else datetime.now()
|
||||
# One observation date for the whole report (upstream 933f254e, BUG-1542).
|
||||
today_dt = datetime.strptime(
|
||||
getattr(args, 'transit_date', None) or getattr(args, 'today', None)
|
||||
or datetime.now().strftime('%Y-%m-%d'), '%Y-%m-%d')
|
||||
current_age = (today_dt - birth_dt).days / 365.25
|
||||
narayana_result = narayana_dasha_full_report(
|
||||
lagna_sign_idx=asc_idx,
|
||||
@@ -16451,7 +16470,9 @@ def cmd_full_reading(args):
|
||||
if nak_age is None:
|
||||
try:
|
||||
birth_date = datetime(args.year, args.month, args.day)
|
||||
nak_age = (datetime.now() - birth_date).days / 365.25
|
||||
nak_reference = getattr(args, 'transit_date', None) or getattr(args, 'today', None)
|
||||
observation = datetime.strptime(nak_reference, '%Y-%m-%d') if nak_reference else datetime.now()
|
||||
nak_age = (observation - birth_date).days / 365.25
|
||||
except:
|
||||
nak_age = None
|
||||
|
||||
@@ -16490,8 +16511,13 @@ def cmd_full_reading(args):
|
||||
if age is None:
|
||||
# 自动计算年龄
|
||||
try:
|
||||
birth_date = datetime(args.year, args.month, args.day)
|
||||
age = (datetime.now() - birth_date).days // 365
|
||||
# Calendar-birthday age on the report's observation date; days // 365
|
||||
# drifted about one day early every four years (upstream 933f254e).
|
||||
ref_today = datetime.strptime(
|
||||
getattr(args, 'transit_date', None) or getattr(args, 'today', None)
|
||||
or datetime.now().strftime('%Y-%m-%d'), '%Y-%m-%d')
|
||||
age = ref_today.year - int(args.year) - (
|
||||
(ref_today.month, ref_today.day) < (int(args.month), int(args.day)))
|
||||
report['warnings'].append(f"未提供年龄,自动计算为 {age} 岁")
|
||||
except:
|
||||
age = None
|
||||
|
||||
@@ -131,6 +131,7 @@ CORE_PYTEST_TARGETS = [
|
||||
# Summary lines by default; failure keeps the last 200 lines and a full log (BUG-1230).
|
||||
"tests/test_run_quality_gate_output.py",
|
||||
"tests/test_upstream_git_import_b9a0ef8f.py",
|
||||
"tests/test_upstream_git_import_5fb8379c.py",
|
||||
"tests/test_interpretation_template_registry.py",
|
||||
"tests/test_vedastro_external_technique_evidence.py",
|
||||
# Self-hosted heading font slices: 6500-character coverage, no overlap, 120 KB cap.
|
||||
|
||||
Reference in New Issue
Block a user