fix(rectification): split D4/D5 stages and recast after adopt
Keep family on D12+D7 instead of mixing it into D4, score D5 on education, and show a natal recast plus technique audit after adopt without unique-minute claims. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -40,6 +40,105 @@ def _decimal(value: Any, default: str = "0") -> Decimal:
|
||||
return Decimal(default)
|
||||
|
||||
|
||||
_AUDIT_LABELS = {
|
||||
"d1-rashi": ("D1 本命盘", "本轮已按该分钟重算本命宫位。"),
|
||||
"d2-hora": ("D2 财帛分盘", "本轮已对照财帛主题。"),
|
||||
"d4-chaturthamsha": ("D4 迁移分盘", "本轮已对照居所或迁移。"),
|
||||
"d5-panchamsha": ("D5 成就分盘", "本轮已对照学业或被委以责任的变化。"),
|
||||
"d7-saptamsha": ("D7 子女分盘", "本轮已对照子女或伴侣细节。"),
|
||||
"d9-navamsa": ("D9 婚姻分盘", "本轮已对照关系主题,未给类型标签。"),
|
||||
"d10-dashamsa": ("D10 事业分盘", "本轮已对照事业主题,未给类型标签。"),
|
||||
"d11-labhamsha": ("D11 收益分盘", "本轮已对照收益主题。"),
|
||||
"d12-dwadashamsha": ("D12 父母分盘", "本轮已对照家人主题。"),
|
||||
"d24-chaturvimshamsha": ("D24 教育分盘", "本轮已对照学业主题。"),
|
||||
"d30-trimshamsha": ("D30 健康压力分盘", "本轮已对照健康压力主题。"),
|
||||
"vimshottari-dasha": ("Vimshottari", "本轮已对照主限。"),
|
||||
"narayana-dasha": ("Narayana", "本轮已对照分盘大运。"),
|
||||
"gochara": ("Gochara", "本轮已做受控行运辅助对照。"),
|
||||
"ashtakavarga": ("Ashtakavarga", "本轮已做 Ashtakavarga 辅助对照。"),
|
||||
"shadbala": ("Shadbala", "本轮已做已核验的 Shadbala 分量辅助对照。"),
|
||||
"arudha-pada": ("Arudha Pada", "本轮已做 Arudha 辅助对照。"),
|
||||
"functional-benefic-malefic": ("功能吉凶星", "本轮已叠加本命功能吉凶星。"),
|
||||
}
|
||||
|
||||
|
||||
def natal_recast_copy(time: str, lagna: str) -> dict[str, Any]:
|
||||
return {
|
||||
"time": time[:5],
|
||||
"lagna": lagna,
|
||||
"user_meaning": (
|
||||
f"本命宫位已按 {time[:5]} 重算(上升 {lagna})。"
|
||||
"下面是本轮实际执行的技法,不能当作唯一分钟确认。"
|
||||
),
|
||||
"unique_minute_claim": False,
|
||||
"confirmation_allowed": False,
|
||||
}
|
||||
|
||||
|
||||
def _executed_public_methods(built: dict[str, Any]) -> list[str]:
|
||||
methods: set[str] = set()
|
||||
for contributions in (built.get("matrix") or {}).values():
|
||||
if not isinstance(contributions, dict):
|
||||
continue
|
||||
for cell in contributions.values():
|
||||
if not isinstance(cell, dict):
|
||||
continue
|
||||
for layer in cell.get("technique_layers") or []:
|
||||
if layer in _AUDIT_LABELS:
|
||||
methods.add(str(layer))
|
||||
for rule in cell.get("rule_ids") or []:
|
||||
text = str(rule)
|
||||
if text.startswith("vim_"):
|
||||
methods.add("vimshottari-dasha")
|
||||
elif text.startswith("narayana_"):
|
||||
methods.add("narayana-dasha")
|
||||
elif "functional_benefic" in text or "functional_malefic" in text:
|
||||
methods.add("functional-benefic-malefic")
|
||||
elif text.startswith("gochara") or "controlled_transit" in text:
|
||||
methods.add("gochara")
|
||||
elif "ashtakavarga" in text:
|
||||
methods.add("ashtakavarga")
|
||||
elif "shadbala" in text:
|
||||
methods.add("shadbala")
|
||||
elif "arudha" in text:
|
||||
methods.add("arudha-pada")
|
||||
return [key for key in _AUDIT_LABELS if key in methods]
|
||||
|
||||
|
||||
def build_technique_audit(
|
||||
built: dict[str, Any],
|
||||
*,
|
||||
house_table: dict[str, Any] | None,
|
||||
) -> list[dict[str, str]]:
|
||||
executed = set(_executed_public_methods(built))
|
||||
if house_table:
|
||||
executed.add("d1-rashi")
|
||||
rows: list[dict[str, str]] = []
|
||||
for method in _AUDIT_LABELS:
|
||||
if method not in executed:
|
||||
continue
|
||||
label, note = _AUDIT_LABELS[method]
|
||||
rows.append({"technique": label, "status": "executed", "note": note})
|
||||
rows.append({
|
||||
"technique": "KP 宫头",
|
||||
"status": "blocked",
|
||||
"note": "KP 宫头本轮未计算。",
|
||||
})
|
||||
rows.extend((
|
||||
{
|
||||
"technique": "VedAstro 分钟级校验",
|
||||
"status": "blocked",
|
||||
"note": "官方分钟级校验尚未评估。",
|
||||
},
|
||||
{
|
||||
"technique": "唯一分钟确认",
|
||||
"status": "blocked",
|
||||
"note": "采用不等于确认唯一分钟。",
|
||||
},
|
||||
))
|
||||
return rows
|
||||
|
||||
|
||||
def _quantized_score(row: CandidateScoreRow) -> Decimal:
|
||||
return _decimal(row.get("score")).quantize(SCORE_QUANTUM, rounding=ROUND_HALF_UP)
|
||||
|
||||
@@ -263,12 +362,22 @@ def build_decision_receipt(
|
||||
"exact_confirmation": exact_confirmation,
|
||||
},
|
||||
}
|
||||
house_table = compact_house_table_from_contexts(
|
||||
house_tables_by_time: dict[str, dict[str, Any]] = {}
|
||||
for decision in candidate_decisions:
|
||||
table = compact_house_table_from_contexts(built.get("static_contexts"), decision.get("time"))
|
||||
if table:
|
||||
house_tables_by_time[table["time"]] = table
|
||||
house_table = house_tables_by_time.get(representative["time"] if representative else "") or compact_house_table_from_contexts(
|
||||
built.get("static_contexts"),
|
||||
representative["time"] if representative else None,
|
||||
)
|
||||
if house_table:
|
||||
receipt["house_table"] = house_table
|
||||
recast = natal_recast_copy(house_table["time"], house_table["lagna"])
|
||||
receipt["natal_recast"] = recast
|
||||
if house_tables_by_time:
|
||||
receipt["house_tables_by_time"] = house_tables_by_time
|
||||
receipt["technique_audit_table"] = build_technique_audit(built, house_table=house_table)
|
||||
receipt.update({
|
||||
"window_scan": packet["window_scan"],
|
||||
"event_dasha_ledger": packet["event_dasha_ledger"],
|
||||
|
||||
Reference in New Issue
Block a user