fix(report): keep the chat annual card's Tajika list, finish KP headings, say the dasha caveat once (BUG-1282)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b8eef75871
commit
a13f5c2683
@@ -62,6 +62,7 @@ def build_annual_tajika_pack(
|
||||
"muntha": muntha,
|
||||
"year_lord": year_lord,
|
||||
"tajika_yogas": tajika_yogas,
|
||||
"tajika_named_yogas": _tajika_named_yogas_field(solar_report),
|
||||
"tajika_strength": _tajika_strength_field(solar_report if isinstance(solar_report, dict) else {}),
|
||||
"sahams": sahams,
|
||||
"mudda_dasha": mudda_dasha,
|
||||
@@ -209,6 +210,19 @@ def _annual_chart_from_solar_report(report: dict[str, Any]) -> dict[str, Any]:
|
||||
return field
|
||||
|
||||
|
||||
def _tajika_named_yogas_field(solar_report: Any) -> dict[str, Any]:
|
||||
"""The named-yoga authority surface, for the full-data report only.
|
||||
|
||||
`tajika_yogas` keeps the cmd_tajika candidate list that the chat annual card
|
||||
reads (consultation_native_layers). The report reads this field instead.
|
||||
"""
|
||||
|
||||
chart = solar_report.get("sr_chart") if isinstance(solar_report, dict) else None
|
||||
if not isinstance(chart, dict) or solar_report.get("error"):
|
||||
return {"status": "not_applicable", "producer": "Tajika Named Yoga Authority", "reason": "annual_chart_planets_missing"}
|
||||
return _tajika_yogas_field({**solar_report, "chart": chart})
|
||||
|
||||
|
||||
def _tajika_strength_field(report: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Copy numeric strength scores. Internal status words stay off this surface."""
|
||||
|
||||
|
||||
@@ -223,8 +223,8 @@ def _sanitize_pl9_ai_density_markdown(markdown: str, title: str = "印度占星
|
||||
text = text.replace("Natural friends", "天然友星")
|
||||
text = text.replace("Natural enemies", "天然敌星")
|
||||
text = text.replace("Temporary relation", "临时关系")
|
||||
text = text.replace("Natal / KP Ruling Planets", "本命 / KP 征象星")
|
||||
text = text.replace("Ruling Planets", "征象星")
|
||||
text = text.replace("Natal / KP Ruling Planets", "本命 / KP 主宰星")
|
||||
text = text.replace("Ruling Planets", "主宰星")
|
||||
text = text.replace("Sub-Planets", "副行星")
|
||||
text = text.replace("Planetary", "行星")
|
||||
text = text.replace("Planets", "行星")
|
||||
@@ -437,6 +437,13 @@ def _sanitize_pl9_ai_density_markdown(markdown: str, title: str = "印度占星
|
||||
"Bhinnashtakavarga": "Bhinnashtakavarga 单星八分表",
|
||||
"KP 行星 星座ificators": "KP 行星征象星",
|
||||
"KP 宫位 Cusps and 星座ificators": "KP 宫头与征象星",
|
||||
# Since the term pass stopped rewriting inside words (BUG-1274),
|
||||
# "Significators" arrives intact; these keys match that spelling.
|
||||
"KP 宫位 Cusps and Significators": "KP 宫头与征象星",
|
||||
"KP 行星 Significators": "KP 行星征象星",
|
||||
"KP Significators / 行星 宫主": "KP 征象星 / 行星主星",
|
||||
"KP Chart / Cusps": "KP 星盘 / 宫头",
|
||||
"Annual Tajika瑜伽 Rows": "年度 Tajika 瑜伽行",
|
||||
"KP 星座ificators / 行星 Lords": "KP 征象星 / 行星主星",
|
||||
"Upagraha / Sub-行星s 点位": "Upagraha / 副行星点位",
|
||||
"大运 Tables": "Dasha 表格",
|
||||
@@ -467,6 +474,8 @@ def _sanitize_pl9_ai_density_markdown(markdown: str, title: str = "印度占星
|
||||
text = replace_natural_language_term(text, "house condition", "宫位条件")
|
||||
for raw, public in zh_heading_repairs.items():
|
||||
text = text.replace(raw, public)
|
||||
# Heading lines only: a Latin yoga name keeps a space before 瑜伽 ("Dhana 瑜伽").
|
||||
text = re.sub(r"(?m)^(#{1,6} .*?[A-Za-z])瑜伽", r"\1 瑜伽", text)
|
||||
text = replace_natural_language_term(text, " condition", "宫条件")
|
||||
zh_public_key_repairs = {
|
||||
"mangal_dosha": "火星婚姻煞",
|
||||
|
||||
@@ -339,7 +339,11 @@ def _lord_facts(packet: dict) -> dict[str, dict[str, Any]]:
|
||||
|
||||
|
||||
def _period_beats(lord: str, language: str) -> str:
|
||||
"""Four traditional beats. Wording stays possible, not certain."""
|
||||
"""Four traditional beats. Wording stays possible, not certain.
|
||||
|
||||
The "possible, not certain" caveat is said once at the top of the Dasha
|
||||
chapter (DASHA_CHAPTER_NOTE), not repeated in every period (product 2026-10-08).
|
||||
"""
|
||||
|
||||
bank = _PHALA.get(lord) or _PHALA["Saturn"]
|
||||
topic, good, pressure = bank["en" if language == "en" else "zh"]
|
||||
@@ -347,26 +351,26 @@ def _period_beats(lord: str, language: str) -> str:
|
||||
if language == "zh":
|
||||
return (
|
||||
f"这段时间可能突出的主题:传统阅读里,{name}容易把{topic}推到眼前。"
|
||||
"这只是可能被注意到的主题,不是已经发生的事。"
|
||||
f"条件好时可能:若落宫、尊贵和当前大运同向,可能出现{good}。"
|
||||
"仍要与宫主、分盘和星宿合看,不能单凭这一层下结论。"
|
||||
f"受压时可能表现为:若该星受压或与当前节奏不一致,可能感到{pressure}。"
|
||||
"这是压力下的可能表现,不是确定会发生的事。"
|
||||
f"怎么细读:先核对{name}的落宫、守护宫、尊贵、星宿和功能吉凶,"
|
||||
"再看它是否出现在主运、子运或次子运。只把它当成阶段线索。"
|
||||
"再看它是否出现在主运、子运或次子运。"
|
||||
)
|
||||
return (
|
||||
f"Topics this period may bring forward: in the traditional reading, {name} may bring {topic} forward. "
|
||||
"These are topics that may be noticed, not events that have already happened. "
|
||||
f"When conditions are supportive, it may show {good}. "
|
||||
"House lords, divisional charts, and the nakshatra still have to be read with it. "
|
||||
f"Under pressure, it may show as {pressure}. "
|
||||
"That is a possible expression under pressure, not a certain event. "
|
||||
f"How to read it more closely: check the house, ownership, dignity, nakshatra, and functional nature of {name}, "
|
||||
"then whether it is the Maha, Antar, or Pratyantar lord. Treat it as a period clue."
|
||||
"then whether it is the Maha, Antar, or Pratyantar lord."
|
||||
)
|
||||
|
||||
|
||||
DASHA_CHAPTER_NOTE = {
|
||||
"zh": "以下每段大运、子运、次子运都只写这段时间可能突出的主题与条件,既不是事实陈述,也不是预言;每一段都要和宫主、分盘、星宿以及当前大运层级合看,不能单凭一段下结论。",
|
||||
"en": "Every Maha, Antar and Pratyantar section below describes topics and conditions that may come forward in that period, not events that have happened or must happen. Read each with the house lords, divisional charts, nakshatra and the running period level; no single section is a conclusion on its own.",
|
||||
}
|
||||
|
||||
|
||||
def _ruled_houses_clause(lord: str, owned: list, language: str) -> str:
|
||||
"""Rahu and Ketu rule no houses. Other empty lists stay an explicit gap."""
|
||||
|
||||
@@ -476,6 +480,7 @@ def build_dasha_interpretation_pack(dasha_master_pack: dict[str, Any], profile:
|
||||
"status": status,
|
||||
"language": language,
|
||||
"page_series": pages,
|
||||
"chapter_note": dict(DASHA_CHAPTER_NOTE),
|
||||
"domain_paragraphs": _domain_paragraphs(items, language),
|
||||
"summary": {"page_series_count": len(pages), "narrative_item_count": len(items)},
|
||||
"audit": {"status": status, "source_dasha_master_status": source_status},
|
||||
@@ -634,7 +639,6 @@ def _sub_paragraph(parent: str, lord: str, row: dict, facts: dict, language: str
|
||||
f"{_planet(parent, language)} / {_planet(lord, language)}({level}):{start} 至 {end}。"
|
||||
f"这段时间可能突出{_planet(lord, language)}的第{house_text}宫、{ruled}、"
|
||||
f"尊贵{_dignity(facts.get('dignity'), language)}与星宿{facts.get('nakshatra') or '未列出'}。"
|
||||
"这是阶段线索,不是确定会发生的事。"
|
||||
+ _period_beats(lord, language)
|
||||
)
|
||||
house_text = str(house) if house is not None else "not listed"
|
||||
@@ -645,7 +649,6 @@ def _sub_paragraph(parent: str, lord: str, row: dict, facts: dict, language: str
|
||||
f"{parent} / {lord} ({level}): {start} to {end}. "
|
||||
f"This period may bring forward {lord}'s house {house_text}, {ruled}, "
|
||||
f"dignity {_dignity(facts.get('dignity'), language)}, and nakshatra {nakshatra}. "
|
||||
"This is a period clue, not a certain event. "
|
||||
+ _period_beats(lord, language)
|
||||
)
|
||||
|
||||
|
||||
@@ -2949,6 +2949,9 @@ def render_pl9_parity_markdown(packet: dict) -> str:
|
||||
dasha_pages = dasha.get('page_series') if isinstance(dasha.get('page_series'), list) else []
|
||||
if dasha_pages:
|
||||
lines.extend(['## Dasha Interpretation' if _lang == 'en' else '## 大运解释', ''])
|
||||
_note = dasha.get('chapter_note') if isinstance(dasha.get('chapter_note'), dict) else {}
|
||||
if _note.get(_lang):
|
||||
lines.extend([str(_note[_lang]), ''])
|
||||
for page in dasha_pages:
|
||||
if not isinstance(page, dict):
|
||||
continue
|
||||
|
||||
@@ -104,6 +104,23 @@ def _normalize_languages(value: Any) -> list[str]:
|
||||
return selected
|
||||
|
||||
|
||||
def _with_report_tajika_view(packet: dict) -> dict:
|
||||
"""Read Tajika named yogas from their own field in the full-data report.
|
||||
|
||||
The shared annual pack keeps `tajika_yogas` as the candidate list the chat
|
||||
annual card uses; only this report copy swaps in `tajika_named_yogas`.
|
||||
"""
|
||||
worksheets = packet.get("worksheets")
|
||||
timing = worksheets.get("timing_and_predictive_systems") if isinstance(worksheets, dict) else None
|
||||
annual = timing.get("annual_tajika_pack") if isinstance(timing, dict) else None
|
||||
named = annual.get("tajika_named_yogas") if isinstance(annual, dict) else None
|
||||
if not isinstance(named, dict) or named.get("status") == "not_applicable":
|
||||
return packet
|
||||
packet["worksheets"] = {**worksheets, "timing_and_predictive_systems": {
|
||||
**timing, "annual_tajika_pack": {**annual, "tajika_yogas": named}}}
|
||||
return packet
|
||||
|
||||
|
||||
def _english_edition(packet: dict, include_fact_tables: bool) -> dict[str, Any]:
|
||||
"""Render the English reader from a deep copy of the same packet.
|
||||
|
||||
@@ -194,7 +211,7 @@ def build_professional_report_reference(handler, body: dict[str, Any], *, engine
|
||||
raise ProfessionalReportReferenceInputError(str(exc)) from exc
|
||||
|
||||
if edition == FULL_DATA_EDITION and isinstance(packet, dict):
|
||||
packet = dict(packet)
|
||||
packet = _with_report_tajika_view(dict(packet))
|
||||
packet["report_version"] = REPORT_VERSION_FULL
|
||||
if output_format == "markdown":
|
||||
if edition == FULL_DATA_EDITION:
|
||||
|
||||
@@ -670,8 +670,11 @@ def solar_return_full_report(
|
||||
|
||||
# 9. 综合总结
|
||||
result['summary'] = _make_sr_summary(result)
|
||||
# Keep the longitudes and chart already calculated above so the report
|
||||
# pack can print them. This does not recompute the return.
|
||||
# Keep the longitudes already calculated above so the report pack can print
|
||||
# them. This does not recompute the return. Do not attach `chart` here: a
|
||||
# `chart` key switches annual_tajika_pack._tajika_yogas_field onto the named-
|
||||
# yoga authority surface and empties the chat annual card's Tajika aspects.
|
||||
# The report reads that surface from `tajika_named_yogas` instead.
|
||||
if not degraded:
|
||||
result['planet_lons'] = {
|
||||
name: float(value)
|
||||
@@ -680,7 +683,7 @@ def solar_return_full_report(
|
||||
}
|
||||
chart = sr.get('chart') if isinstance(sr, dict) else None
|
||||
if isinstance(chart, dict):
|
||||
result['chart'] = chart
|
||||
result['sr_chart'] = chart
|
||||
|
||||
return result
|
||||
|
||||
|
||||
Reference in New Issue
Block a user