新六章有 12 节读错公开包字段,整节只剩未判定,而且六章绕过了口径替换。按资料包改读路径,先拼六章再统一替换措辞,并把中文附录实际丢掉的组合句数出来。

Co-Authored-By: Grok (agent loop)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jesse-ux
2026-10-22 18:51:54 +08:00
co-authored by Grok (agent loop) Cursor
parent 365b1e647e
commit 92b4e220f2
8 changed files with 647 additions and 135 deletions
+74 -2
View File
@@ -368,6 +368,63 @@ FIELD_ZH = {
"months": "月数",
}
# Names that already had a Chinese header before the #91 fix.
# The annual-table filter used to drop every other column. Counts use this set
# so a later Chinese name still shows up as a column the old filter removed.
ANNUAL_COLUMN_NAMES_BEFORE_FIX = frozenset(FIELD_ZH)
_APPENDIX_DROPS: dict[str, dict[str, int]] = {
"annual_columns": {},
"annual_tables": {},
"effects": {},
"combinations_undetermined": {},
"combinations_replaced": {},
}
def reset_appendix_drop_log() -> None:
"""Clear the per-render drop counts. One Chinese render, then snapshot."""
for bucket in _APPENDIX_DROPS.values():
bucket.clear()
def snapshot_appendix_drop_log() -> dict[str, dict[str, int]]:
return {name: dict(bucket) for name, bucket in _APPENDIX_DROPS.items()}
def note_dropped_annual_column(field: str) -> None:
key = str(field)
bucket = _APPENDIX_DROPS["annual_columns"]
bucket[key] = bucket.get(key, 0) + 1
def note_annual_table() -> None:
bucket = _APPENDIX_DROPS["annual_tables"]
bucket["seen"] = bucket.get("seen", 0) + 1
def _drop_identity(item: dict, text: str) -> str:
parts = [
str(item.get("rule_id") or ""),
str(item.get("source") or ""),
str(item.get("bvr_id") or ""),
str(item.get("name") or ""),
" ".join(str(text).split()),
]
return " | ".join(parts)[:240]
def _note_effect(item: dict, text: str) -> None:
key = _drop_identity(item, text)
bucket = _APPENDIX_DROPS["effects"]
bucket[key] = bucket.get(key, 0) + 1
def _note_combination(item: dict, text: str, kind: str) -> None:
key = _drop_identity(item, text)
bucket = _APPENDIX_DROPS[kind]
bucket[key] = bucket.get(key, 0) + 1
def column_header(field: str, language: str) -> str:
if language != "zh":
@@ -591,12 +648,19 @@ def chinese_yoga_label(item: dict) -> str:
def chinese_combination(item: dict) -> str:
"""Use the Chinese combination sentence. An English sentence is not translated word by word."""
combination = str(item.get("combination") or "").strip()
if combination and re.search(r"[\u4e00-\u9fff]", combination) and not _HAN_FUNCTION_RE.search(combination) and not SIGN_EN_RE.search(combination):
han = bool(re.search(r"[\u4e00-\u9fff]", combination))
function = bool(_HAN_FUNCTION_RE.search(combination)) if combination else False
sign = bool(SIGN_EN_RE.search(combination)) if combination else False
if combination and han and not function and not sign:
return combination
planets = item.get("planets") if isinstance(item.get("planets"), list) else []
names = [planet_name(planet, "zh") for planet in planets if planet]
if names:
if combination:
_note_combination(item, combination, "combinations_replaced")
return "与".join(names)
if combination:
_note_combination(item, combination, "combinations_undetermined")
return "未判定"
@@ -610,7 +674,15 @@ def yoga_cells(item: dict, language: str) -> list[Any]:
category_text = "未判定"
strength = item.get("strength") or "-"
effects = item.get("effects") if isinstance(item.get("effects"), list) else []
kept = [str(effect) for effect in effects if str(effect).strip() and not _has_prose_glue(str(effect))]
kept = []
for effect in effects:
text = str(effect).strip()
if not text:
continue
if _has_prose_glue(text):
_note_effect(item, text)
continue
kept.append(text)
effects_text = ";".join(kept) or "-"
return [chinese_yoga_label(item), category_text, strength, chinese_combination(item), effects_text]
+258 -125
View File
@@ -470,6 +470,84 @@ def _rows_from(items: list[Any], language: str, columns: list[tuple[str, str]])
return _md_table(headers, rows)
_PLANETS = ("Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn", "Rahu", "Ketu")
_MISSING_MODULE = {
"zh": "公开报告资料包未带此模块",
"en": "This module is not in the public report packet",
}
def _missing_module(language: str, columns: list[str]) -> str:
"""The public worksheet does not carry this module. Keep the undetermined row."""
return _MISSING_MODULE[language] + "\n\n" + _blank(language, columns)
def _is_planet(value: Any) -> bool:
return isinstance(value, str) and value.strip() in _PLANETS
def _dignity_token(value: Any, language: str) -> Any:
if not isinstance(value, str):
return value
key = " ".join(value.strip().split()).lower()
if key == "neutral":
return "中性" if language == "zh" else "Neutral"
return {
"exalted": "exalted",
"debilitated": "debilitated",
"own sign": "own",
"own": "own",
"moolatrikona": "mooltrikona",
}.get(key, value)
def _named_planets(chart: Any) -> list[tuple[str, dict]]:
if not isinstance(chart, dict):
return []
nested = chart.get("planets")
source = nested if isinstance(nested, dict) else chart
rows = []
for name in _PLANETS:
item = source.get(name)
if isinstance(item, dict):
rows.append((name, item))
return rows
def _varga_chart(packet: dict, *keys: str) -> dict:
varga = _first(packet, ("divisional_and_special_charts", "varga_full")) or {}
if not isinstance(varga, dict):
return {}
for key in keys:
chart = varga.get(key)
if isinstance(chart, dict):
return chart
return {}
def _varga_label(name: str, chart: dict) -> str:
meta = chart.get("_meta") if isinstance(chart.get("_meta"), dict) else {}
div = meta.get("div")
title = str(meta.get("name") or "")
if div and title and "_" not in title and not re.search(r"[\u4e00-\u9fff]", title):
return f"D{div} {title}".strip()
return " ".join(str(name).replace("_", " ").split())
def _cycle_label(value: str, language: str) -> str | None:
body = value.split(":", 1)[1]
parts = [part.strip(" .") for part in body.replace("->", "|").replace("→", "|").split("|")]
names = []
for part in parts:
if not _is_planet(part):
return None
names.append(planet_name(part, language))
if len(names) < 2:
return None
prefix = "循环" if language == "zh" else "Cycle"
return prefix + " " + " → ".join(names)
def _months(start: Any, end: Any) -> str | None:
if not isinstance(start, str) or not isinstance(end, str):
return None
@@ -560,25 +638,8 @@ def _tribhagi_periods(packet: dict, language: str) -> str:
def _navamsha(packet: dict, language: str) -> str:
module = _first(packet, ("timing_and_predictive_systems", "navamsha_dasha"))
periods = []
if isinstance(module, dict):
majors = module.get("periods") or module.get("native_result", {}).get("periods") if isinstance(module.get("native_result"), dict) else module.get("periods")
if isinstance(module.get("native_result"), dict):
majors = module["native_result"].get("periods") or majors
for major in majors or []:
if not isinstance(major, dict):
continue
for child in major.get("antardasha") or []:
if not isinstance(child, dict):
continue
copied = dict(child)
copied["months"] = child.get("duration_months") or _months(child.get("start"), child.get("end"))
periods.append(copied)
if not periods:
note = "公开报告包没有带上 Navamsha 小运行。" if language == "zh" else "The public packet does not carry the Navamsha sub-period rows."
return note + "\n\n" + _blank(language, ["sign", "start", "end", "months"])
return _rows_from(periods, language, [("sign", "sign"), ("start", "text"), ("end", "text"), ("months", "text")])
del packet
return _missing_module(language, ["sign", "start", "end", "months"])
def _nakshatra_context(packet: dict, language: str) -> str:
@@ -675,31 +736,8 @@ def _sandhi(packet: dict, language: str) -> str:
def _convergence(packet: dict, language: str) -> str:
timing = _first(packet, ("ai_and_audit", "ai_prompt_pack", "evidence_snapshot", "timing")) or {}
pairs = timing.get("convergence_top_domains") if isinstance(timing, dict) else None
module = _first(packet, ("timing_and_predictive_systems", "dasa_convergence"))
activations = module.get("domain_activations") if isinstance(module, dict) else None
rows = []
if isinstance(activations, dict) and activations:
for domain, info in activations.items():
if not isinstance(info, dict):
continue
rows.append({
"domain": domain,
"house": info.get("house"),
"level": info.get("convergence_level"),
"counted": info.get("system_count"),
})
elif isinstance(pairs, list):
for item in pairs:
if isinstance(item, (list, tuple)) and len(item) >= 2:
rows.append({"domain": item[0], "level": item[1]})
elif isinstance(item, dict):
rows.append({"domain": item.get("domain") or item.get("name"), "level": item.get("level") or item.get("convergence_level")})
if not rows:
note = "公开报告包没有带上逐领域激活行。" if language == "zh" else "The public packet does not carry the per-domain activation rows."
return note + "\n\n" + _blank(language, ["domain", "level"])
return _rows_from(rows, language, [("domain", "text"), ("house", "text"), ("level", "text"), ("counted", "text")])
del packet
return _missing_module(language, ["domain", "level"])
def _chara(packet: dict, language: str) -> str:
@@ -890,12 +928,30 @@ def _bhava(packet: dict, language: str) -> str:
def _vimsopaka(packet: dict, language: str) -> str:
module = _first(packet, ("strengths_and_scores", "vimsopaka")) or {}
nested = module.get("planets") if isinstance(module, dict) else None
planets = nested if isinstance(nested, dict) else module
bands = {
"High": ("High", "高"),
"Moderate": ("Moderate", "中"),
"Limited": ("Limited", "有限"),
"Low": ("Low", "低"),
}
rows = []
planets = module.get("planets") if isinstance(module, dict) else module
if isinstance(planets, dict):
for planet, item in planets.items():
if isinstance(item, dict) and ("total_score" in item or "category" in item):
rows.append({"planet": planet, "score": item.get("total_score"), "category": item.get("category")})
if not isinstance(item, dict) or ("total_score" not in item and "category" not in item):
continue
if planet not in _PLANETS and item.get("planet") not in _PLANETS:
continue
category = item.get("category")
pair = bands.get(str(category))
if pair:
category = pair[1] if language == "zh" else pair[0]
rows.append({
"planet": planet if planet in _PLANETS else item.get("planet"),
"score": item.get("total_score"),
"category": category,
})
elif isinstance(planets, list):
rows = [item for item in planets if isinstance(item, dict)]
return _rows_from(rows, language, [("planet", "planet"), ("score", "text"), ("category", "text")])
@@ -958,33 +1014,61 @@ def _prastara(packet: dict, language: str) -> str:
return _rows_from(rows, language, [("planet", "planet"), ("total", "text")])
def _avastha_state(item: dict) -> Any:
states = item.get("avasthas") if isinstance(item.get("avasthas"), dict) else {}
for key in ("Jagrat", "Deeptadi"):
entry = states.get(key)
if isinstance(entry, dict) and entry.get("state"):
return entry.get("state")
return item.get("jagradadi") or item.get("state") or item.get("avastha")
def _avastha(packet: dict, language: str) -> str:
module = _first(packet, ("advanced_systems", "avasthas")) or {}
nested = module.get("planets") if isinstance(module, dict) else None
planets = nested if isinstance(nested, dict) else module if isinstance(module, dict) else {}
rows = []
planets = module.get("planets") if isinstance(module, dict) else module
if isinstance(planets, dict):
for planet, item in planets.items():
if isinstance(item, dict):
rows.append({"planet": planet, "status": item.get("jagradadi") or item.get("state") or item.get("avastha"), "degree": item.get("degree") or item.get("degree_in_sign")})
elif isinstance(planets, list):
rows = [item for item in planets if isinstance(item, dict)]
return _rows_from(rows, language, [("planet", "planet"), ("status", "text"), ("degree", "text")])
for planet, item in planets.items():
if planet not in _PLANETS or not isinstance(item, dict):
continue
degree = item.get("degree")
if degree is None:
degree = item.get("degree_in_sign")
rows.append({
"planet": planet,
"sign": item.get("sign"),
"status": _avastha_state(item),
"degree": degree,
})
return _rows_from(rows, language, [("planet", "planet"), ("sign", "sign"), ("status", "text"), ("degree", "text")])
def _d30(packet: dict, language: str, source: bool) -> str:
module = _first(packet, ("advanced_systems", "trimshamsa_d30")) or _first(packet, ("divisional_and_special_charts", "varga_full", "D30"))
rows = []
planets = module.get("planets") if isinstance(module, dict) else None
if isinstance(planets, dict):
for planet, item in planets.items():
if not isinstance(item, dict):
if source:
rows = []
for planet, item in _shadbala_planets(packet).items():
if planet not in _PLANETS or not isinstance(item, dict):
continue
if source:
rows.append({"planet": planet, "degree": item.get("degree_in_sign") or item.get("degree"), "sign": item.get("sign")})
else:
rows.append({"planet": planet, "sign": item.get("sign"), "status": item.get("dignity") or item.get("status")})
columns = [("planet", "planet"), ("degree", "text"), ("sign", "sign")] if source else [("planet", "planet"), ("sign", "sign"), ("status", "text")]
return _rows_from(rows, language, columns)
sthana = item.get("sthana_bala") if isinstance(item.get("sthana_bala"), dict) else {}
score = sthana.get("sapta_d30")
if isinstance(score, bool) or not isinstance(score, (int, float)):
continue
rows.append({"planet": planet, "score": score})
return _rows_from(rows, language, [("planet", "planet"), ("score", "text")])
chart = _varga_chart(packet, "D30_Trimsamsa", "D30", "Trimsamsa")
if not chart:
legacy = _first(packet, ("advanced_systems", "trimshamsa_d30"))
chart = legacy if isinstance(legacy, dict) else {}
dignity = chart.get("_dignity") if isinstance(chart.get("_dignity"), dict) else {}
rows = []
for planet, item in _named_planets(chart):
status = dignity.get(planet) or item.get("dignity") or item.get("status")
rows.append({
"planet": planet,
"sign": item.get("sign"),
"status": _dignity_token(status, language),
})
return _rows_from(rows, language, [("planet", "planet"), ("sign", "sign"), ("status", "text")])
def _pushkara(packet: dict, language: str) -> str:
@@ -1112,8 +1196,26 @@ def _chain_rows(module: Any, terminal: bool) -> list[dict]:
def _dispositor(packet: dict, language: str, terminal: bool) -> str:
module = _first(packet, ("advanced_systems", "final_dispositors" if terminal else "dispositor_chains"))
return _rows_from(_chain_rows(module, terminal), language, [("planet", "planet"), ("sign", "sign"), ("lord", "planet")])
if not terminal:
module = _first(packet, ("advanced_systems", "dispositor_chains"))
return _rows_from(_chain_rows(module, False), language, [("planet", "planet"), ("sign", "sign"), ("lord", "planet")])
module = _first(packet, ("advanced_systems", "final_dispositors")) or {}
rows = []
if isinstance(module, dict):
for planet, value in module.items():
if planet not in _PLANETS:
continue
if _is_planet(value):
rows.append({"planet": planet, "lord": value})
elif isinstance(value, str) and value.startswith("Cycle:"):
label = _cycle_label(value, language)
if label:
rows.append({"planet": planet, "value": label})
elif isinstance(value, (dict, list)):
rows.extend(_chain_rows({planet: value}, True))
if not rows:
rows = _chain_rows(module, True)
return _rows_from(rows, language, [("planet", "planet"), ("sign", "sign"), ("lord", "planet"), ("value", "text")])
def _aspects(packet: dict, language: str) -> str:
@@ -1290,14 +1392,18 @@ def _saham_basis(packet: dict, language: str) -> str:
for name, item in module.items():
if not isinstance(item, dict):
continue
if "formula_status" not in item and "formula_variant" not in item and "formula_operands" not in item:
if item.get("sign") in (None, "") and not isinstance(item.get("longitude"), (int, float)):
continue
label = item.get("name")
if not isinstance(label, str) or "_" in label or not label.strip():
label = " ".join(str(name).replace("_", " ").split())
rows.append({
"name": name,
"status": item.get("formula_status") or item.get("formula_variant"),
"value": item.get("base_longitude_before_exception") or item.get("longitude"),
"name": label,
"sign": item.get("sign"),
"degree": item.get("degree_in_sign"),
"longitude": item.get("longitude"),
})
return _rows_from(rows, language, [("name", "text"), ("status", "text"), ("value", "text")])
return _rows_from(rows, language, [("name", "text"), ("sign", "sign"), ("degree", "text"), ("longitude", "text")])
def _special_points(packet: dict, language: str) -> str:
@@ -1361,31 +1467,30 @@ def _one_point(packet: dict, language: str, key: str) -> str:
item = jaimini.get(key) if isinstance(jaimini, dict) else None
if isinstance(item, str):
return _rows_from([{"planet": item}], language, [("planet", "planet")])
if isinstance(item, dict):
return _rows_from([item], language, [("planet", "planet"), ("sign", "sign"), ("house", "text")])
return _blank(language, ["planet", "sign"])
if not isinstance(item, dict):
return _blank(language, ["planet", "sign"])
if key == "karakamsha":
return _rows_from([{
"sign": item.get("karakamsha_sign") or item.get("sign"),
"degree": item.get("karakamsha_degree") if "karakamsha_degree" in item else item.get("degree"),
"lord": item.get("karakamsha_lord") or item.get("lord") or item.get("planet"),
"house": item.get("house"),
}], language, [("sign", "sign"), ("degree", "text"), ("lord", "planet"), ("house", "text")])
if key == "darakaraka":
return _rows_from([{
"planet": item.get("dk_planet") or item.get("planet"),
"sign": item.get("dk_sign") or item.get("sign"),
"house": item.get("dk_house") if item.get("dk_house") is not None else item.get("house"),
"degree": item.get("dk_degree") if item.get("dk_degree") is not None else item.get("degree"),
"value": item.get("d9_sign"),
"dignity": _dignity_token(item.get("d9_dignity") or item.get("dignity"), language),
}], language, [("planet", "planet"), ("sign", "sign"), ("house", "text"), ("degree", "text"), ("value", "sign"), ("dignity", "text")])
return _rows_from([item], language, [("planet", "planet"), ("sign", "sign"), ("house", "text")])
def _rashi_tulya(packet: dict, language: str) -> str:
module = _first(packet, ("advanced_systems", "rashi_tulya_navamsa")) or {}
analysis = module.get("analysis") if isinstance(module, dict) else module
if not isinstance(analysis, dict):
return _blank(language, ["name", "value"])
labels = {
"lagna_sign": "上升星座" if language == "zh" else "Ascendant sign",
"strength_score": "力量分" if language == "zh" else "Strength score",
"weakness_score": "薄弱分" if language == "zh" else "Weakness score",
}
rows = []
for key, label in labels.items():
if key in analysis:
rows.append({"name": label, "value": analysis.get(key)})
planets = analysis.get("planets")
if isinstance(planets, dict):
for planet, item in planets.items():
sign = item.get("sign") if isinstance(item, dict) else item
rows.append({"name": planet, "value": sign})
return _rows_from(rows, language, [("name", "text"), ("value", "text")])
del packet
return _missing_module(language, ["name", "value"])
def _moon(packet: dict, language: str) -> str:
@@ -1403,7 +1508,10 @@ def _moon(packet: dict, language: str) -> str:
def _sudarshana(packet: dict, language: str) -> str:
module = _first(packet, ("divisional_and_special_charts", "sudarshana")) or {}
points = module.get("reference_points") if isinstance(module, dict) else {}
raw = module.get("raw") if isinstance(module, dict) and isinstance(module.get("raw"), dict) else {}
points = raw.get("reference_points") if isinstance(raw.get("reference_points"), dict) else None
if not isinstance(points, dict) and isinstance(module, dict):
points = module.get("reference_points")
rows = []
labels = {
"ascendant_lagna": ("Ascendant reference", "出生上升参考点"),
@@ -1419,16 +1527,37 @@ def _sudarshana(packet: dict, language: str) -> str:
def _transit(packet: dict, language: str) -> str:
module = _first(packet, ("timing_and_predictive_systems", "transit_positions")) or _first(packet, ("advanced_systems", "transit_positions"))
if not isinstance(module, dict):
module = {}
planets = module.get("planets") or module.get("positions") or module
multi = _first(packet, ("timing_and_predictive_systems", "transit_multi_reference")) or {}
analysis = multi.get("transit_analysis") if isinstance(multi, dict) else {}
when = multi.get("target_date") if isinstance(multi, dict) else None
overlay_root = _first(packet, ("advanced_systems", "nakshatra_dasha")) or {}
overlay = overlay_root.get("transit_overlay") if isinstance(overlay_root, dict) else {}
if not isinstance(analysis, dict):
analysis = {}
if not isinstance(overlay, dict):
overlay = {}
order = [planet for planet in (*analysis.keys(), *overlay.keys()) if planet in _PLANETS]
seen = []
for planet in order:
if planet not in seen:
seen.append(planet)
rows = []
if isinstance(planets, dict):
for planet, item in planets.items():
if isinstance(item, dict):
rows.append({"planet": planet, "sign": item.get("sign"), "date": item.get("date") or module.get("date")})
return _rows_from(rows, language, [("planet", "planet"), ("sign", "sign"), ("date", "text")])
for planet in seen:
item = analysis.get(planet) if isinstance(analysis.get(planet), dict) else {}
over = overlay.get(planet) if isinstance(overlay.get(planet), dict) else {}
nakshatra = over.get("transit_nakshatra")
if isinstance(nakshatra, str) and "_" in nakshatra:
nakshatra = nakshatra.replace("_", " ")
if not isinstance(nakshatra, str):
nakshatra = None
rows.append({
"planet": planet,
"sign": item.get("sign"),
"degree": item.get("degree_in_sign"),
"date": when if isinstance(when, (str, int, float)) else item.get("date"),
"nakshatra": nakshatra,
})
return _rows_from(rows, language, [("planet", "planet"), ("sign", "sign"), ("degree", "text"), ("date", "text"), ("nakshatra", "text")])
def _multi_transit(packet: dict, language: str) -> str:
@@ -1465,19 +1594,15 @@ def _kp(packet: dict, language: str) -> str:
def _d9(packet: dict, language: str) -> str:
varga = _first(packet, ("divisional_and_special_charts", "varga_full")) or {}
chart = None
if isinstance(varga, dict):
for key in ("D9", "d9", "Navamsa", "navamsa"):
if isinstance(varga.get(key), dict):
chart = varga[key]
break
planets = chart.get("planets") if isinstance(chart, dict) else None
chart = _varga_chart(packet, "D9_Navamsa", "D9", "d9", "Navamsa", "navamsa")
dignity = chart.get("_dignity") if isinstance(chart.get("_dignity"), dict) else {}
rows = []
if isinstance(planets, dict):
for planet, item in planets.items():
if isinstance(item, dict):
rows.append({"planet": planet, "sign": item.get("sign"), "dignity": item.get("dignity") or item.get("status")})
for planet, item in _named_planets(chart):
rows.append({
"planet": planet,
"sign": item.get("sign"),
"dignity": _dignity_token(dignity.get(planet) or item.get("dignity") or item.get("status"), language),
})
return _rows_from(rows, language, [("planet", "planet"), ("sign", "sign"), ("dignity", "text")])
@@ -1486,13 +1611,19 @@ def _mapping(packet: dict, language: str) -> str:
rows = []
if isinstance(varga, dict):
for name, chart in varga.items():
if not isinstance(chart, dict):
continue
if any(token in str(name).upper() for token in ("D81", "D108", "D144")):
continue
sign = None
if isinstance(chart, dict):
asc = chart.get("ascendant") if isinstance(chart.get("ascendant"), dict) else {}
sign = asc.get("sign") or chart.get("asc_sign") or chart.get("lagna_sign")
rows.append({"name": name, "sign": sign})
asc = chart.get("Ascendant") if isinstance(chart.get("Ascendant"), dict) else {}
if not asc and isinstance(chart.get("ascendant"), dict):
asc = chart.get("ascendant") or {}
sign = asc.get("sign") or chart.get("asc_sign") or chart.get("lagna_sign")
if sign in (None, "") and isinstance(asc.get("sign_idx"), int):
sign = asc.get("sign_idx")
if sign in (None, ""):
continue
rows.append({"name": _varga_label(str(name), chart), "sign": sign})
return _rows_from(rows, language, [("name", "text"), ("sign", "sign")])
@@ -1515,7 +1646,9 @@ def _chalit_planets(packet: dict, language: str) -> str:
def _chalit_centres(packet: dict, language: str) -> str:
raw = _bhava_raw(packet)
boundaries = raw.get("boundaries") if isinstance(raw.get("boundaries"), dict) else {}
details = boundaries.get("houses_detail") if isinstance(boundaries, dict) else None
details = boundaries.get("houses_detail") if isinstance(boundaries.get("houses_detail"), list) else None
if not details:
details = boundaries.get("houses") if isinstance(boundaries.get("houses"), list) else []
rows = []
for item in details or []:
if isinstance(item, dict):
@@ -1625,7 +1758,7 @@ def _render_named(packet: dict, language: str, title: str) -> str:
"Tara-Chandra Matrix": lambda: _tara(packet, language),
"Natal Tithi Lord": lambda: _tithi(packet, language),
"Birth Calendar": lambda: _panchanga(packet, language),
"Pancha Pakshi": lambda: _simple_module(packet, ("advanced_systems", "pancha_pakshi"), language, [("name", "text"), ("value", "text"), ("status", "text")]),
"Pancha Pakshi": lambda: _missing_module(language, ["name", "value", "status"]),
"Natal Vivah Saham": lambda: _vivah(packet, language),
"Natal Saham Formula Basis": lambda: _saham_basis(packet, language),
"Arudha / UL / A10": lambda: _special_points(packet, language),