fix(web): rank remaining-minute probes by split and match choice kind
Independent Staging Quality Gate / validate (push) Failing after 22m30s
Independent Staging Quality Gate / publish (push) Has been skipped

Choice cards used a hardcoded domain menu and always asked existence.
Rank scoring layers by remaining-minute entropy, keep finance and health
volunteer-only, and ask D9/D10 style or exam quality so taps match outcomes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-25 20:44:55 +08:00
co-authored by Cursor
parent 7a4360d848
commit f5e73ef326
21 changed files with 921 additions and 114 deletions
+95
View File
@@ -345,6 +345,101 @@ class EventProbesTest(unittest.TestCase):
self.assertTrue(times <= {"05:00", "05:06", "05:07"})
self.assertIn("05:00", times)
self.assertTrue(times & {"05:06", "05:07"})
covered = set(row["expected_outcomes"][0]["supports"] + row["expected_outcomes"][0]["conflicts"])
self.assertEqual(covered, {"05:00", "05:06", "05:07"})
def test_remaining_family_layer_outranks_stable_relationship(self) -> None:
built = {
"static_contexts": [
{
"feature": {
"time": "05:13",
"varga_ascendants": {"D9": 1, "D10": 1, "D4": 1, "D12": 1, "D7": 1},
}
},
{
"feature": {
"time": "05:14",
"varga_ascendants": {"D9": 1, "D10": 1, "D4": 1, "D12": 2, "D7": 2},
}
},
]
}
probes = discriminating_event_probes(
_request(),
built,
scan=window_scan(built),
candidate_times=["05:13", "05:14"],
representative_time="05:13",
precision_current="d9_refine",
today=date(2026, 8, 22),
)
self.assertTrue(probes)
self.assertEqual(probes[0]["domain"], "family")
self.assertFalse(any(item["domain"] == "relationship" for item in probes))
self.assertFalse(any(item["domain"] == "finance" for item in probes))
def test_finance_layer_stays_volunteer_only(self) -> None:
built = {
"static_contexts": [
{"feature": {"time": "05:13", "varga_ascendants": {"D2": 1, "D9": 1, "D10": 1}}},
{"feature": {"time": "05:14", "varga_ascendants": {"D2": 2, "D9": 1, "D10": 1}}},
]
}
probes = discriminating_event_probes(
_request(),
built,
scan=window_scan(built),
candidate_times=["05:13", "05:14"],
representative_time="05:13",
today=date(2026, 8, 22),
)
self.assertFalse(any(item["domain"] == "finance" for item in probes))
def test_highest_gain_year_is_kept_not_first_hit(self) -> None:
from unittest.mock import patch
from scripts.rectification import event_probes as probes_mod
built = {
"static_contexts": [
_context("05:13", d4_asc=0, sun_house=4, sun_varga_sign=3, moon=100.0),
_context("05:14", d4_asc=1, sun_house=10, sun_varga_sign=9, moon=101.0),
]
}
def fake_vim(_birth_date: str, moon: float, _lo: int, _hi: int) -> list[int]:
return [2010, 2020] if moon <= 100.0 else [2009, 2019]
def fake_narayana(_asc: int, planets: dict, _birth_date: str, _lo: int, _hi: int) -> list[int]:
moon = float(planets.get("Moon") or 0)
return [2010, 2020] if moon <= 100.0 else [2009, 2019]
def fake_score(context: dict, *, birth_date: str, domain: str, year: int) -> dict:
del birth_date, domain
early = probes_mod._context_time(context) == "05:13"
if year == 2010:
return {"rule_ids": ["vim_ad_domain_lord"] if early else ["no_domain_activation"]}
if year == 2020:
return {"rule_ids": ["vim_md_domain_house"] if early else ["no_domain_activation"]}
return {"rule_ids": ["no_domain_activation"]}
with (
patch.object(probes_mod, "_vim_start_years", side_effect=fake_vim),
patch.object(probes_mod, "_narayana_start_years", side_effect=fake_narayana),
patch.object(probes_mod, "_score_year", side_effect=fake_score),
):
probes = discriminating_event_probes(
_request(),
built,
scan=window_scan(built),
candidate_times=["05:13", "05:14"],
representative_time="05:13",
today=date(2026, 8, 22),
)
row = next(item for item in probes if item["domain"] == "relocation")
self.assertEqual(row["year"], 2020)
self.assertEqual(row["source"], "dasha_boundary")
if __name__ == "__main__":
@@ -101,6 +101,8 @@ class RefinementPacketTest(unittest.TestCase):
"layer": "d9",
"at": "05:14",
"user_meaning": "D9 在 05:14 发生变化",
"from_sign": "金牛座",
"to_sign": "天蝎座",
}])
encoded = str(scan)
self.assertNotIn("Aries", encoded)