fix(rectification): emit finer dated probes on refresh only (BUG-664/665)
After six dated answers, refresh can use 30-day same-year windows plus pratyantar and D9/D10 Narayana. First-round probe rules stay at 45 days. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -66,6 +66,7 @@ MAX_PROBES_PER_DOMAIN = 3
|
||||
# MAX_PROBES is the published cap after a global information_gain sort.
|
||||
MAX_BOUNDARY_CANDIDATES_PER_DOMAIN = 8
|
||||
MIN_BOUNDARY_DAYS = 45
|
||||
REFRESH_MIN_BOUNDARY_DAYS = 30
|
||||
MAX_QUALITY_DISTINGUISH_PROBES = 2
|
||||
QUALITY_DISTINGUISH_EVENT_KINDS = frozenset({
|
||||
"education_start",
|
||||
@@ -525,15 +526,21 @@ def _as_start_date(value: date | datetime | int) -> date | None:
|
||||
return None
|
||||
|
||||
|
||||
def _boundary_windows(left: Sequence[date | datetime | int], right: Sequence[date | datetime | int]) -> list[date]:
|
||||
def _boundary_windows(
|
||||
left: Sequence[date | datetime | int],
|
||||
right: Sequence[date | datetime | int],
|
||||
*,
|
||||
min_days: int | None = None,
|
||||
) -> list[date]:
|
||||
windows: list[date] = []
|
||||
seen: set[tuple[int, int]] = set()
|
||||
threshold = MIN_BOUNDARY_DAYS if min_days is None else min_days
|
||||
for raw_left, raw_right in zip(left, right):
|
||||
one = _as_start_date(raw_left)
|
||||
two = _as_start_date(raw_right)
|
||||
if one is None or two is None:
|
||||
continue
|
||||
if one.year == two.year and abs((one - two).days) < MIN_BOUNDARY_DAYS:
|
||||
if one.year == two.year and abs((one - two).days) < threshold:
|
||||
continue
|
||||
for item in (one, two):
|
||||
key = (item.year, item.month)
|
||||
@@ -605,54 +612,77 @@ def _union_boundary_dates(
|
||||
birth_date: str,
|
||||
lo: int,
|
||||
hi: int,
|
||||
min_boundary_days: int | None = None,
|
||||
include_pratyantar: bool = False,
|
||||
varga_narayana: bool = False,
|
||||
) -> list[date]:
|
||||
threshold = MIN_BOUNDARY_DAYS if min_boundary_days is None else min_boundary_days
|
||||
vim_cache: dict[tuple[Any, ...], list[date]] = {}
|
||||
narayana_cache: dict[tuple[Any, ...], list[date] | None] = {}
|
||||
dates_by_key: dict[tuple[int, int], date] = {}
|
||||
for left, right in _representative_pairs(reps):
|
||||
left_moon = float(left["planet_longitudes"]["Moon"])
|
||||
right_moon = float(right["planet_longitudes"]["Moon"])
|
||||
left_vim_key = _vim_cache_key(birth_date, left_moon, lo, hi)
|
||||
right_vim_key = _vim_cache_key(birth_date, right_moon, lo, hi)
|
||||
left_vim_key = (*_vim_cache_key(birth_date, left_moon, lo, hi), include_pratyantar)
|
||||
right_vim_key = (*_vim_cache_key(birth_date, right_moon, lo, hi), include_pratyantar)
|
||||
if left_vim_key not in vim_cache:
|
||||
vim_cache[left_vim_key] = _vim_start_dates(birth_date, left_moon, lo, hi)
|
||||
vim_cache[left_vim_key] = (
|
||||
_vim_start_dates(
|
||||
birth_date, left_moon, lo, hi, include_pratyantar=True,
|
||||
)
|
||||
if include_pratyantar
|
||||
else _vim_start_dates(birth_date, left_moon, lo, hi)
|
||||
)
|
||||
if right_vim_key not in vim_cache:
|
||||
vim_cache[right_vim_key] = _vim_start_dates(birth_date, right_moon, lo, hi)
|
||||
windows = list(_boundary_windows(vim_cache[left_vim_key], vim_cache[right_vim_key]))
|
||||
left_nara_key = _narayana_cache_key(
|
||||
int(left["ascendant_index"]),
|
||||
left["planet_longitudes"],
|
||||
birth_date,
|
||||
lo,
|
||||
hi,
|
||||
)
|
||||
right_nara_key = _narayana_cache_key(
|
||||
int(right["ascendant_index"]),
|
||||
right["planet_longitudes"],
|
||||
birth_date,
|
||||
lo,
|
||||
hi,
|
||||
)
|
||||
if left_nara_key not in narayana_cache:
|
||||
narayana_cache[left_nara_key] = _narayana_start_dates(
|
||||
int(left["ascendant_index"]),
|
||||
left["planet_longitudes"],
|
||||
birth_date,
|
||||
lo,
|
||||
hi,
|
||||
vim_cache[right_vim_key] = (
|
||||
_vim_start_dates(
|
||||
birth_date, right_moon, lo, hi, include_pratyantar=True,
|
||||
)
|
||||
if include_pratyantar
|
||||
else _vim_start_dates(birth_date, right_moon, lo, hi)
|
||||
)
|
||||
if right_nara_key not in narayana_cache:
|
||||
narayana_cache[right_nara_key] = _narayana_start_dates(
|
||||
int(right["ascendant_index"]),
|
||||
right["planet_longitudes"],
|
||||
birth_date,
|
||||
lo,
|
||||
hi,
|
||||
)
|
||||
left_narayana = narayana_cache[left_nara_key]
|
||||
right_narayana = narayana_cache[right_nara_key]
|
||||
if left_narayana is not None and right_narayana is not None:
|
||||
windows.extend(_boundary_windows(left_narayana, right_narayana))
|
||||
window_kw = {} if threshold == MIN_BOUNDARY_DAYS else {"min_days": threshold}
|
||||
windows = list(_boundary_windows(
|
||||
vim_cache[left_vim_key],
|
||||
vim_cache[right_vim_key],
|
||||
**window_kw,
|
||||
))
|
||||
layers: list[str | None] = [None]
|
||||
if varga_narayana:
|
||||
layers.extend(["d9", "d10"])
|
||||
for layer in layers:
|
||||
if layer is None:
|
||||
left_asc = int(left["ascendant_index"])
|
||||
right_asc = int(right["ascendant_index"])
|
||||
else:
|
||||
left_raw = _layer_value(left, layer)
|
||||
right_raw = _layer_value(right, layer)
|
||||
if not isinstance(left_raw, int) or not isinstance(right_raw, int):
|
||||
continue
|
||||
left_asc = left_raw
|
||||
right_asc = right_raw
|
||||
left_nara_key = (*_narayana_cache_key(
|
||||
left_asc, left["planet_longitudes"], birth_date, lo, hi,
|
||||
), layer)
|
||||
right_nara_key = (*_narayana_cache_key(
|
||||
right_asc, right["planet_longitudes"], birth_date, lo, hi,
|
||||
), layer)
|
||||
if left_nara_key not in narayana_cache:
|
||||
narayana_cache[left_nara_key] = _narayana_start_dates(
|
||||
left_asc, left["planet_longitudes"], birth_date, lo, hi,
|
||||
)
|
||||
if right_nara_key not in narayana_cache:
|
||||
narayana_cache[right_nara_key] = _narayana_start_dates(
|
||||
right_asc, right["planet_longitudes"], birth_date, lo, hi,
|
||||
)
|
||||
left_narayana = narayana_cache[left_nara_key]
|
||||
right_narayana = narayana_cache[right_nara_key]
|
||||
if left_narayana is not None and right_narayana is not None:
|
||||
windows.extend(_boundary_windows(
|
||||
left_narayana,
|
||||
right_narayana,
|
||||
**window_kw,
|
||||
))
|
||||
for item in windows:
|
||||
dates_by_key.setdefault((item.year, item.month), item)
|
||||
return sorted(dates_by_key.values(), key=lambda item: (item.year, item.month))
|
||||
@@ -1567,7 +1597,20 @@ def _discriminating_event_probe_lists(
|
||||
d1_differs="d1" in remaining_layers or bool(scan.get("d1_candidates_differ")),
|
||||
)
|
||||
lo, hi = birth_year + 5, min(now.year, birth_year + 80)
|
||||
boundary_dates = _union_boundary_dates(reps, birth_date=birth_date, lo=lo, hi=hi) if domains else []
|
||||
union_kw: dict[str, Any] = {}
|
||||
if refresh:
|
||||
union_kw = {
|
||||
"min_boundary_days": REFRESH_MIN_BOUNDARY_DAYS,
|
||||
"include_pratyantar": True,
|
||||
"varga_narayana": True,
|
||||
}
|
||||
boundary_dates = _union_boundary_dates(
|
||||
reps,
|
||||
birth_date=birth_date,
|
||||
lo=lo,
|
||||
hi=hi,
|
||||
**union_kw,
|
||||
) if domains else []
|
||||
probes: list[dict[str, Any]] = []
|
||||
for domain in domains:
|
||||
if domain not in DOMAIN_CATALOG:
|
||||
|
||||
Reference in New Issue
Block a user