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
@@ -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 = {