fix(rectification): fold D24 into education refine and score family D3

Window scan now drives d5_refine when D24 changes, family events use D3, and pada/Hora/Ghati are display-only. New cases bind Skill 10.0.7 without unique-minute confirmation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-20 11:04:55 +08:00
co-authored by Cursor
parent 9a5cf67209
commit 70efb56926
35 changed files with 894 additions and 72 deletions
@@ -20,7 +20,7 @@ from scripts.rectification.scoring_service import public_technique_layers
def test_family_event_is_scoreable_with_d12_and_kin_houses() -> None:
prefixes, houses = DOMAIN_CONFIG["family"]
assert prefixes == ("D12", "D7")
assert prefixes == ("D12", "D7", "D3")
assert houses == (3, 4, 5, 9)
event = {
"id": "00000000-0000-4000-8000-000000000001",
@@ -159,8 +159,12 @@ def test_family_event_engine_rows_include_d12_and_are_not_skipped() -> None:
contexts = compute_candidate_static_contexts(request)
assert all("D12" in context["feature"]["available_layers"] for context in contexts)
assert all("D7" in context["feature"]["available_layers"] for context in contexts)
assert all("D3" in context["feature"]["available_layers"] for context in contexts)
assert all(context["varga_charts"]["D12"] is not None for context in contexts)
assert all(context["varga_charts"]["D7"] is not None for context in contexts)
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)
rows = compute_event_candidate_rows(request, static_contexts=contexts)
assert [row["time"] for row in rows] == ["05:13", "05:14"]
for row in rows:
@@ -186,6 +190,7 @@ def test_family_event_engine_rows_include_d12_and_are_not_skipped() -> None:
assert "d1-rashi" in layers and "d10-dashamsa" in layers
family_layers = public_technique_layers("family", ["vim_md_domain_house", "vim_md_domain_varga"])
assert "d12-dwadashamsha" in family_layers and "d7-saptamsha" in family_layers
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
assert all("D10" in context["feature"]["available_layers"] for context in contexts)
+51 -1
View File
@@ -12,7 +12,22 @@ from scripts.rectification.refinement_packet import (
)
def feature(time: str, *, d1: int | None = None, d9: int | None = None, d10: int | None = None, d4: int | None = None, d5: int | None = None, d7: int | None = None, d12: int | None = None, degree: float | None = None) -> dict:
def feature(
time: str,
*,
d1: int | None = None,
d9: int | None = None,
d10: int | None = None,
d4: int | None = None,
d5: int | None = None,
d7: int | None = None,
d12: int | None = None,
d24: int | None = None,
degree: float | None = None,
pada: int | None = None,
hora: int | None = None,
ghati: int | None = None,
) -> dict:
vargas = {}
if d9 is not None:
vargas["D9"] = d9
@@ -26,11 +41,19 @@ def feature(time: str, *, d1: int | None = None, d9: int | None = None, d10: int
vargas["D7"] = d7
if d12 is not None:
vargas["D12"] = d12
if d24 is not None:
vargas["D24"] = d24
row: dict = {"time": time, "varga_ascendants": vargas}
if d1 is not None:
row["ascendant_sign_index"] = d1
if degree is not None:
row["ascendant_degree"] = degree
if pada is not None:
row["pada_index"] = pada
if hora is not None:
row["hora_sign_index"] = hora
if ghati is not None:
row["ghati_sign_index"] = ghati
return {"feature": row}
@@ -95,6 +118,10 @@ class RefinementPacketTest(unittest.TestCase):
self.assertEqual(precision_stage({"d10_candidates_differ": True}, 2)["current"], "d10_refine")
self.assertEqual(precision_stage({"d4_candidates_differ": True}, 2)["current"], "d4_refine")
self.assertEqual(precision_stage({"d5_candidates_differ": True}, 2)["current"], "d5_refine")
self.assertEqual(
precision_stage({"d24_candidates_differ": True, "d5_candidates_differ": False}, 2)["current"],
"d5_refine",
)
self.assertNotEqual(precision_stage({"d4_candidates_differ": True}, 2)["current"], "theme_refine")
self.assertIn("搬家", precision_stage({"d4_candidates_differ": True}, 2)["user_meaning"])
self.assertNotIn("家人", precision_stage({"d4_candidates_differ": True}, 2)["user_meaning"])
@@ -102,6 +129,29 @@ class RefinementPacketTest(unittest.TestCase):
self.assertEqual(ready["current"], "ready_to_adopt")
self.assertFalse(ready["unique_minute_claim"])
def test_window_scan_reports_d24_and_fine_minute_changes_without_unique_claim(self):
scan = window_scan({
"static_contexts": [
feature("05:13", d1=1, d5=3, d24=4, pada=10, hora=2, ghati=6),
feature("05:14", d1=1, d5=3, d24=8, pada=11, hora=3, ghati=6),
]
})
self.assertEqual(scan["d24_lagna_count"], 2)
self.assertTrue(scan["d24_candidates_differ"])
self.assertFalse(scan["d5_candidates_differ"])
self.assertEqual(scan["pada_count"], 2)
self.assertTrue(scan["pada_candidates_differ"])
self.assertTrue(scan["hora_candidates_differ"])
self.assertFalse(scan["ghati_candidates_differ"])
meanings = [item["user_meaning"] for item in scan["transitions"]]
self.assertIn("D24 在 05:14 发生变化", meanings)
self.assertIn("Nakshatra pada 在 05:14 发生变化", meanings)
self.assertIn("Hora Lagna 在 05:14 发生变化", meanings)
self.assertNotIn("Ghati Lagna 在 05:14 发生变化", meanings)
self.assertFalse(scan["unique_minute_claim"])
self.assertFalse(scan["confirmation_allowed"])
self.assertEqual(precision_stage(scan, 2)["current"], "d5_refine")
def test_packet_ledger_oos_and_nakshatra_without_scores(self):
request = request_events()
built = {
@@ -10,7 +10,7 @@ def test_zero_events_are_not_a_completed_rectification() -> None:
def test_contract_discloses_used_and_missing_layers() -> None:
contract = build_rectification_technique_contract(event_count=4, domain_count=3)
assert {"D2", "D4", "D5", "D7", "D9", "D10", "D11", "D12", "D24", "D30"} <= set(contract["used_divisional_charts"])
assert {"D2", "D3", "D4", "D5", "D7", "D9", "D10", "D11", "D12", "D24", "D30"} <= set(contract["used_divisional_charts"])
assert contract["dasha_tracks"] == ["vimshottari_md_ad_pd", "narayana_md_ad"]
assert contract["used_arudha"] == ["A7", "UL", "A10"]
assert contract["missing_layers"] == ["shadbala_kala_dig_chesta_total"]
+1 -1
View File
@@ -154,7 +154,7 @@ class RectificationV5ServicesTest(unittest.TestCase):
built = build_event_contribution_matrix(normalized, row_provider=rows)
self.assertEqual(seen, ["family"])
self.assertEqual(built["matrix"][normalized["events"][0]["id"]]["05:13"]["technique_layers"], [
"d1-rashi", "d12-dwadashamsha", "d7-saptamsha", "vim_md_domain_house",
"d1-rashi", "d12-dwadashamsha", "d3-drekkana", "d7-saptamsha", "vim_md_domain_house",
])
def test_declared_date_precision_changes_real_contribution_weight(self):