feat(rectification): 出卡加精度门槛,补经历改成系统点名
宽度超过 10 分钟或头名并列时不再出交付卡,改为按大运边界逐条问、 用类型芯片和年/月选择器录入。跳过的线换问法再问一次;答「这类事 都没有过」的不再问。用户说「没有了」仍立刻给目前范围。Skill 10.0.27。 BUG-740~743
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from datetime import date
|
||||
|
||||
from scripts.rectification.event_probes import GUIDED_COLLECT_LIMIT, guided_collect_windows
|
||||
|
||||
from tests.test_rectification_event_probes import _context, _gate_events, _multi_layer_window_built, _request
|
||||
|
||||
|
||||
class GuidedCollectWindowsTests(unittest.TestCase):
|
||||
def test_twenty_minute_window_emits_at_least_one_real_dasha_window(self) -> None:
|
||||
built = _multi_layer_window_built()
|
||||
rows = guided_collect_windows(
|
||||
_request(),
|
||||
built,
|
||||
candidate_times=["04:47", "04:48", "05:00", "05:06", "05:07"],
|
||||
today=date(2026, 8, 22),
|
||||
)
|
||||
self.assertGreaterEqual(len(rows), 1)
|
||||
self.assertLessEqual(len(rows), GUIDED_COLLECT_LIMIT)
|
||||
for row in rows:
|
||||
self.assertIn("year", row)
|
||||
self.assertIn("month_lo", row)
|
||||
self.assertIn("month_hi", row)
|
||||
self.assertIn("domain", row)
|
||||
self.assertIn("split", row)
|
||||
self.assertGreaterEqual(row["month_lo"], 1)
|
||||
self.assertLessEqual(row["month_hi"], 12)
|
||||
self.assertGreaterEqual(row["month_hi"], row["month_lo"])
|
||||
self.assertGreaterEqual(row["split"]["left"], 1)
|
||||
self.assertGreaterEqual(row["split"]["right"], 1)
|
||||
|
||||
def test_declined_domains_are_removed(self) -> None:
|
||||
built = _multi_layer_window_built()
|
||||
times = ["04:47", "04:48", "05:00", "05:06", "05:07"]
|
||||
full = guided_collect_windows(_request(), built, candidate_times=times, today=date(2026, 8, 22))
|
||||
if not full:
|
||||
self.skipTest("fixture produced no guided windows")
|
||||
target = str(full[0]["domain"])
|
||||
blocked = guided_collect_windows(
|
||||
_request(declined_domains=[target]),
|
||||
built,
|
||||
candidate_times=times,
|
||||
today=date(2026, 8, 22),
|
||||
)
|
||||
self.assertFalse(any(row["domain"] == target for row in blocked))
|
||||
|
||||
def test_split_balance_sorts_before_year_distance(self) -> None:
|
||||
built = {
|
||||
"static_contexts": [
|
||||
_context("04:47", d4_asc=0, sun_house=4, sun_varga_sign=3, moon=80.0, d9_asc=1, d10_asc=1),
|
||||
_context("04:48", d4_asc=1, sun_house=10, sun_varga_sign=9, moon=140.0, d9_asc=2, d10_asc=2),
|
||||
_context("05:06", d4_asc=1, sun_house=10, sun_varga_sign=9, moon=200.0, d9_asc=3, d10_asc=3),
|
||||
],
|
||||
}
|
||||
rows = guided_collect_windows(
|
||||
_request(events=_gate_events()),
|
||||
built,
|
||||
candidate_times=["04:47", "04:48", "05:06"],
|
||||
today=date(2026, 8, 22),
|
||||
)
|
||||
if len(rows) < 2:
|
||||
self.skipTest("fixture produced fewer than two windows")
|
||||
balances = [abs(row["split"]["left"] - row["split"]["right"]) for row in rows]
|
||||
self.assertEqual(balances, sorted(balances))
|
||||
|
||||
def test_cross_year_split_emits_separate_rows(self) -> None:
|
||||
built = {
|
||||
"static_contexts": [
|
||||
_context("04:50", d4_asc=0, sun_house=4, sun_varga_sign=3, moon=10.0, d9_asc=0, d10_asc=0),
|
||||
_context("05:10", d4_asc=6, sun_house=10, sun_varga_sign=9, moon=190.0, d9_asc=6, d10_asc=6),
|
||||
],
|
||||
}
|
||||
rows = guided_collect_windows(
|
||||
_request(),
|
||||
built,
|
||||
candidate_times=["04:50", "05:10"],
|
||||
today=date(2026, 8, 22),
|
||||
)
|
||||
grouped: dict[tuple[str, int], list[int]] = {}
|
||||
for row in rows:
|
||||
grouped.setdefault((row["domain"], row["year"]), []).append(row["month_lo"])
|
||||
self.assertTrue(rows, "expected real dasha windows from distant moons")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user