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:
@@ -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",)
|
||||
assert prefixes == ("D12", "D7")
|
||||
assert houses == (3, 4, 5, 9)
|
||||
event = {
|
||||
"id": "00000000-0000-4000-8000-000000000001",
|
||||
@@ -158,11 +158,14 @@ 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(context["varga_charts"]["D12"] is not None for context in contexts)
|
||||
assert all(context["varga_charts"]["D7"] is not None 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:
|
||||
assert "D12" not in row["missing_layers"]
|
||||
assert "D7" not in row["missing_layers"]
|
||||
assert row["evidence"], "family events must enter scoring instead of being skipped"
|
||||
assert row["evidence"][0]["domain"] == "family"
|
||||
assert "event_kind:family_event" in row["evidence"][0]["rule_ids"]
|
||||
@@ -181,4 +184,9 @@ def test_family_event_engine_rows_include_d12_and_are_not_skipped() -> None:
|
||||
career_rules = [rule for row in career_rows for item in row["evidence"] for rule in item["rule_ids"]]
|
||||
layers = public_technique_layers("career", career_rules)
|
||||
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
|
||||
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)
|
||||
assert all("D5" in context["feature"]["available_layers"] for context in contexts)
|
||||
|
||||
@@ -12,7 +12,7 @@ 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, 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, degree: float | None = None) -> dict:
|
||||
vargas = {}
|
||||
if d9 is not None:
|
||||
vargas["D9"] = d9
|
||||
@@ -20,6 +20,12 @@ def feature(time: str, *, d1: int | None = None, d9: int | None = None, d10: int
|
||||
vargas["D10"] = d10
|
||||
if d4 is not None:
|
||||
vargas["D4"] = d4
|
||||
if d5 is not None:
|
||||
vargas["D5"] = d5
|
||||
if d7 is not None:
|
||||
vargas["D7"] = d7
|
||||
if d12 is not None:
|
||||
vargas["D12"] = d12
|
||||
row: dict = {"time": time, "varga_ascendants": vargas}
|
||||
if d1 is not None:
|
||||
row["ascendant_sign_index"] = d1
|
||||
@@ -87,7 +93,11 @@ class RefinementPacketTest(unittest.TestCase):
|
||||
self.assertEqual(precision_stage({"d1_candidates_differ": True}, 2)["current"], "lagna_frame")
|
||||
self.assertEqual(precision_stage({"d9_candidates_differ": True}, 2)["current"], "d9_refine")
|
||||
self.assertEqual(precision_stage({"d10_candidates_differ": True}, 2)["current"], "d10_refine")
|
||||
self.assertEqual(precision_stage({"d4_candidates_differ": True}, 2)["current"], "theme_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.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"])
|
||||
ready = precision_stage({}, 3)
|
||||
self.assertEqual(ready["current"], "ready_to_adopt")
|
||||
self.assertFalse(ready["unique_minute_claim"])
|
||||
@@ -170,6 +180,57 @@ class RefinementPacketTest(unittest.TestCase):
|
||||
self.assertIn("vimshottari_narayana_conflict", receipt["reasons"])
|
||||
self.assertEqual(receipt["dasha_agreement"]["status"], "conflict")
|
||||
self.assertEqual(receipt["event_dasha_ledger"][0]["match_label"], "强相关")
|
||||
self.assertTrue(any(row["technique"] == "唯一分钟确认" and row["status"] == "blocked" for row in receipt["technique_audit_table"]))
|
||||
self.assertTrue(any(row["technique"] == "VedAstro 分钟级校验" and row["status"] == "blocked" for row in receipt["technique_audit_table"]))
|
||||
self.assertFalse(receipt["unique_minute_claim"])
|
||||
|
||||
def test_receipt_recasts_house_tables_per_candidate_and_blocks_unique_minute(self):
|
||||
request = request_events()
|
||||
rows = [
|
||||
{"time": "05:13", "score": 20, "evidence": [], "missing_layers": []},
|
||||
{"time": "05:14", "score": 8, "evidence": [], "missing_layers": []},
|
||||
]
|
||||
decisions = build_candidate_decisions(rows, result_id="00000000-0000-4000-8000-000000000099")
|
||||
chart_a = {"ascendant": {"sign": "Taurus", "lon": 40.0}, "planets": {"Sun": {"sign": "Aries", "house": 12}}}
|
||||
chart_b = {"ascendant": {"sign": "Gemini", "lon": 70.0}, "planets": {"Sun": {"sign": "Aries", "house": 11}}}
|
||||
built = {
|
||||
"missing_layers": [],
|
||||
"static_contexts": [
|
||||
{**feature("05:13", d1=1, d9=1, d10=4), "chart": chart_a},
|
||||
{**feature("05:14", d1=2, d9=1, d10=4), "chart": chart_b},
|
||||
],
|
||||
"matrix": {
|
||||
request["events"][0]["id"]: {
|
||||
"05:13": {"points": 8, "rule_ids": ["vim_md_domain_house"], "technique_layers": ["d1-rashi", "d10-dashamsa"]},
|
||||
"05:14": {"points": 1, "rule_ids": ["vim_ad_domain_house"], "technique_layers": ["d1-rashi", "d10-dashamsa"]},
|
||||
},
|
||||
request["events"][1]["id"]: {
|
||||
"05:13": {"points": 1, "rule_ids": ["narayana_ad_domain_house"], "technique_layers": ["d1-rashi", "d9-navamsa"]},
|
||||
"05:14": {"points": 9, "rule_ids": ["narayana_md_domain_house"], "technique_layers": ["d1-rashi", "d9-navamsa"]},
|
||||
},
|
||||
request["events"][2]["id"]: {
|
||||
"05:13": {"points": 1, "rule_ids": ["vim_md_domain_varga"], "technique_layers": ["d1-rashi", "d5-panchamsha"]},
|
||||
"05:14": {"points": 1, "rule_ids": ["vim_md_domain_varga"], "technique_layers": ["d1-rashi", "d5-panchamsha"]},
|
||||
},
|
||||
},
|
||||
}
|
||||
receipt = build_decision_receipt(request, decisions, built, {
|
||||
"leave_one_event_out_retention_rate": 1,
|
||||
"leave_one_domain_out_retention_rate": 1,
|
||||
"date_sensitivity_retention_rate": 1,
|
||||
"primary_secondary_margin_percent": 50,
|
||||
})
|
||||
self.assertEqual(receipt["house_table"]["time"], "05:13")
|
||||
self.assertEqual(receipt["house_table"]["lagna"], "金牛座")
|
||||
self.assertEqual(receipt["house_tables_by_time"]["05:14"]["lagna"], "双子座")
|
||||
self.assertEqual(receipt["natal_recast"]["time"], "05:13")
|
||||
self.assertFalse(receipt["natal_recast"]["unique_minute_claim"])
|
||||
self.assertFalse(receipt["confirmation_allowed"])
|
||||
techniques = {row["technique"]: row["status"] for row in receipt["technique_audit_table"]}
|
||||
self.assertEqual(techniques["D1 本命盘"], "executed")
|
||||
self.assertEqual(techniques["D5 成就分盘"], "executed")
|
||||
self.assertEqual(techniques["KP 宫头"], "blocked")
|
||||
self.assertEqual(techniques["唯一分钟确认"], "blocked")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -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", "D9", "D10", "D11", "D12", "D24", "D30"} <= set(contract["used_divisional_charts"])
|
||||
assert {"D2", "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"]
|
||||
|
||||
@@ -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", "vim_md_domain_house",
|
||||
"d1-rashi", "d12-dwadashamsha", "d7-saptamsha", "vim_md_domain_house",
|
||||
])
|
||||
|
||||
def test_declared_date_precision_changes_real_contribution_weight(self):
|
||||
|
||||
Reference in New Issue
Block a user