fix(rectification): ask finance and health, show Bhava and Pranapada

Interviews skipped D2/D11 and D30 unless the user volunteered them, so those scoring layers almost never ran. Ask them after family, keep relocation out of rotation, and display Bhava/Pranapada transitions without delaying adopt.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-20 11:49:27 +08:00
parent c1bd09351b
commit 1b93afc594
28 changed files with 860 additions and 51 deletions
@@ -165,6 +165,7 @@ def test_family_event_engine_rows_include_d12_and_are_not_skipped() -> None:
assert all(context["varga_charts"]["D3"] is not None for context in contexts)
assert all(isinstance(context["feature"].get("pada_index"), int) for context in contexts)
assert all(0 <= context["feature"]["pada_index"] <= 107 for context in contexts)
assert all(isinstance(context["feature"].get("bhava_sign_index"), int) for context in contexts)
rows = compute_event_candidate_rows(request, static_contexts=contexts)
assert [row["time"] for row in rows] == ["05:13", "05:14"]
for row in rows:
@@ -193,5 +194,9 @@ def test_family_event_engine_rows_include_d12_and_are_not_skipped() -> None:
assert "d3-drekkana" in family_layers
education_layers = public_technique_layers("education", ["vim_md_domain_house"])
assert "d5-panchamsha" in education_layers and "d24-chaturvimshamsha" in education_layers
finance_layers = public_technique_layers("finance", ["vim_md_domain_house"])
assert "d2-hora" in finance_layers and "d11-labhamsha" in finance_layers
health_layers = public_technique_layers("health_pressure", ["vim_md_domain_house"])
assert "d30-trimshamsha" in health_layers
assert all("D10" in context["feature"]["available_layers"] for context in contexts)
assert all("D5" in context["feature"]["available_layers"] for context in contexts)
@@ -23,10 +23,15 @@ def feature(
d7: int | None = None,
d12: int | None = None,
d24: int | None = None,
d2: int | None = None,
d11: int | None = None,
d30: int | None = None,
degree: float | None = None,
pada: int | None = None,
hora: int | None = None,
ghati: int | None = None,
bhava: int | None = None,
pranapada: int | None = None,
) -> dict:
vargas = {}
if d9 is not None:
@@ -43,6 +48,12 @@ def feature(
vargas["D12"] = d12
if d24 is not None:
vargas["D24"] = d24
if d2 is not None:
vargas["D2"] = d2
if d11 is not None:
vargas["D11"] = d11
if d30 is not None:
vargas["D30"] = d30
row: dict = {"time": time, "varga_ascendants": vargas}
if d1 is not None:
row["ascendant_sign_index"] = d1
@@ -54,6 +65,10 @@ def feature(
row["hora_sign_index"] = hora
if ghati is not None:
row["ghati_sign_index"] = ghati
if bhava is not None:
row["bhava_sign_index"] = bhava
if pranapada is not None:
row["pranapada_sign_index"] = pranapada
return {"feature": row}
@@ -152,6 +167,39 @@ class RefinementPacketTest(unittest.TestCase):
self.assertFalse(scan["confirmation_allowed"])
self.assertEqual(precision_stage(scan, 2)["current"], "d5_refine")
def test_window_scan_reports_finance_health_and_bhava_without_delaying_adopt(self):
scan = window_scan({
"static_contexts": [
feature("05:13", d1=1, d2=2, d11=4, d30=6, bhava=1, hora=2, ghati=6, pranapada=8),
feature("05:14", d1=1, d2=3, d11=4, d30=7, bhava=2, hora=2, ghati=6, pranapada=8),
]
})
self.assertTrue(scan["d2_candidates_differ"])
self.assertFalse(scan["d11_candidates_differ"])
self.assertTrue(scan["d30_candidates_differ"])
self.assertTrue(scan["bhava_candidates_differ"])
self.assertFalse(scan["pranapada_candidates_differ"])
meanings = [item["user_meaning"] for item in scan["transitions"]]
self.assertIn("D2 在 05:14 发生变化", meanings)
self.assertIn("D30 在 05:14 发生变化", meanings)
self.assertIn("Bhava Lagna 在 05:14 发生变化", meanings)
self.assertNotIn("Pranapada Lagna 在 05:14 发生变化", meanings)
self.assertEqual(precision_stage(scan, 2)["current"], "ready_to_adopt")
self.assertFalse(scan["unique_minute_claim"])
pranapada_scan = window_scan({
"static_contexts": [
feature("05:13", d1=1, d11=4, pranapada=8),
feature("05:14", d1=1, d11=5, pranapada=9),
]
})
self.assertTrue(pranapada_scan["d11_candidates_differ"])
self.assertTrue(pranapada_scan["pranapada_candidates_differ"])
self.assertIn(
"Pranapada Lagna 在 05:14 发生变化",
[item["user_meaning"] for item in pranapada_scan["transitions"]],
)
self.assertEqual(precision_stage(pranapada_scan, 2)["current"], "ready_to_adopt")
def test_packet_ledger_oos_and_nakshatra_without_scores(self):
request = request_events()
built = {