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()