Files
Jyotisha/scripts/research/precision_gate_lib.py
T
jesse-ux dfb572fc7f
Independent Staging Quality Gate / validate (push) Failing after 13m3s
Independent Staging Quality Gate / publish (push) Skipped
docs(research): measure precision-adaptive probe gates; no variant clears the bar
20 public AA cases, raman/mean. Lowering MIN_BOUNDARY_DAYS narrows ±10 from
15 to 11 minutes but drops top-1 0.80→0.75; wider radii get wider ranges.
Varga sensitivity weights (V1/V2) match production; D60 (V3) hurts ±10.
Day-precision events offset ±7 never squeeze the true minute out. Production
45/30 gate and equal varga weights stay unchanged.
2026-09-15 09:04:03 +08:00

533 lines
19 KiB
Python

"""Pure helpers for the precision-adaptive probe-gate research sweep.
Does not change production defaults in event_probes.py or the scoring engine.
"""
from __future__ import annotations
from contextlib import contextmanager
from copy import deepcopy
from dataclasses import dataclass, field
from datetime import date, timedelta
from random import Random
from typing import Any, Iterator, Sequence
from scripts.active_rectification_event_engine import (
AUXILIARY_DOMAINS,
AUXILIARY_SCORE_FACTOR,
DOMAIN_CONFIG,
OBSERVATION_ONLY_LAYERS,
_active_narayana,
_active_vimshottari,
_ashtakavarga_auxiliary,
_controlled_transit_rules,
_event_datetime,
_house_lords,
_planet_house,
_relative_house,
_shadbala_verified_components_auxiliary,
_varga_chart,
_varga_house,
)
from scripts.active_rectification_events import precision_weight
from scripts.rectification.event_probes import (
REFRESH_MIN_BOUNDARY_DAYS,
_boundary_windows,
)
import functional_benefics
import varga
GATES: dict[str, dict[str, int]] = {
"G0": {"year": 45, "month": 45, "day": 45},
"G1": {"year": 45, "month": 30, "day": 10},
"G2": {"year": 45, "month": 30, "day": 7},
"G3": {"year": 45, "month": 21, "day": 5},
"G4": {"year": 60, "month": 30, "day": 3},
}
TREATMENTS = ("A", "B", "C")
JITTER_SPANS = (3, 7, 14)
VARGA_CAP = 1.0
UPSTREAM_VARGA_MINUTES: dict[str, float] = {
"D1": 120.0,
"D9": 13.3,
"D10": 12.0,
"D12": 10.0,
"D4": 7.5,
"D24": 5.0,
"D30": 4.0,
"D60": 2.0,
}
PRODUCTION_VARGA_PREFIXES = (
"D2", "D3", "D4", "D5", "D7", "D9", "D10", "D11", "D12", "D24", "D30",
)
JITTER_SEED = 20260914
@dataclass
class VargaPolicy:
name: str
window_minutes: float
changing: frozenset[str] = field(default_factory=frozenset)
use_d60: bool = False
cap: float = VARGA_CAP
hits: dict[str, int] = field(default_factory=dict)
points: dict[str, float] = field(default_factory=dict)
points_by_time: dict[str, dict[str, float]] = field(default_factory=dict)
@property
def is_baseline(self) -> bool:
return self.name in {"V0", "baseline", ""}
def window_minutes_for_radius(radius: int) -> float:
return float(2 * int(radius))
def varga_minutes(prefix: str) -> float:
if prefix in UPSTREAM_VARGA_MINUTES:
return UPSTREAM_VARGA_MINUTES[prefix]
number = int(str(prefix)[1:])
return 120.0 / max(number, 1)
def varga_factor(prefix: str, window_minutes: float, cap: float = VARGA_CAP) -> float:
minutes = varga_minutes(prefix)
if minutes <= 0 or window_minutes <= 0:
return 0.0
return min(float(window_minutes) / minutes, float(cap))
def finest_precision(events: Sequence[dict[str, Any]]) -> str:
ranks = {"day": 3, "month": 2, "quarter": 2, "year": 1, "range": 1, "unknown": 0}
best = "year"
best_rank = 0
for event in events:
precision = str(event.get("precision") or "year")
rank = ranks.get(precision, 0)
if rank > best_rank:
best = precision if precision in {"day", "month", "year"} else "year"
best_rank = rank
if best_rank >= 3:
return "day"
if best_rank >= 2:
return "month"
return "year"
def participating_precision(events: Sequence[dict[str, Any]], domain: str | None = None) -> str:
pool = [
event for event in events
if domain is None or str(event.get("domain") or "") == domain
]
return finest_precision(pool or events)
def threshold_for(gate: str, precision: str, *, refresh: bool) -> int:
spec = GATES[gate]
key = precision if precision in spec else "year"
if refresh and gate == "G0":
return REFRESH_MIN_BOUNDARY_DAYS
return int(spec[key])
def count_precision(events: Sequence[dict[str, Any]]) -> dict[str, int]:
tallies = {"day": 0, "month": 0, "year": 0, "other": 0}
for event in events:
precision = str(event.get("precision") or "year")
if precision in tallies:
tallies[precision] += 1
else:
tallies["other"] += 1
return tallies
def treat_events(events: Sequence[dict[str, Any]], treatment: str) -> list[dict[str, Any]]:
if treatment == "A":
return [dict(event) for event in events]
rows: list[dict[str, Any]] = []
for event in events:
item = dict(event)
precision = str(item.get("precision") or "year")
if treatment == "B" and precision == "day":
item["precision"] = "month"
elif treatment == "C":
item["precision"] = "year"
rows.append(item)
return rows
def jitter_day_events(
events: Sequence[dict[str, Any]],
span: int,
*,
case_id: str,
seed: int = JITTER_SEED,
) -> list[dict[str, Any]]:
rows: list[dict[str, Any]] = []
for event in events:
item = dict(event)
if str(item.get("precision") or "") != "day":
rows.append(item)
continue
raw = str(item.get("date") or "")
try:
original = date.fromisoformat(raw[:10])
except ValueError:
rows.append(item)
continue
rng = Random(f"{seed}:{case_id}:{item.get('id')}:{span}")
offset = 0
while offset == 0:
offset = rng.randint(-int(span), int(span))
item["date"] = (original + timedelta(days=offset)).isoformat()
item["jitter_days"] = offset
rows.append(item)
return rows
def varga_sign_index(context: dict[str, Any], prefix: str) -> int | None:
charts = context.get("varga_charts") if isinstance(context.get("varga_charts"), dict) else {}
chart = charts.get(prefix)
if not isinstance(chart, dict):
return None
raw = (chart.get("Ascendant") or {}).get("sign_idx")
return int(raw) if isinstance(raw, int) else None
def changing_vargas(
contexts: Sequence[dict[str, Any]],
prefixes: Sequence[str] = PRODUCTION_VARGA_PREFIXES,
) -> frozenset[str]:
changed: set[str] = set()
for prefix in prefixes:
previous = None
for context in contexts:
current = varga_sign_index(context, prefix)
if previous is not None and current is not None and current != previous:
changed.add(prefix)
break
previous = current
return frozenset(changed)
def ensure_d60(context: dict[str, Any]) -> dict[str, Any] | None:
charts = context.setdefault("varga_charts", {})
existing = charts.get("D60")
if isinstance(existing, dict):
return existing
planets = context.get("planet_longitudes") or {}
natal = context.get("chart") or {}
ascendant = natal.get("ascendant") if isinstance(natal.get("ascendant"), dict) else {}
lon = ascendant.get("lon")
if not isinstance(lon, (int, float)) or not planets:
return None
computed = varga.calc_all_vargas(planets, float(lon), divisions=[60])
chart = _varga_chart(computed, "D60")
if isinstance(chart, dict):
charts["D60"] = chart
return chart
def attach_d60(contexts: Sequence[dict[str, Any]]) -> None:
for context in contexts:
ensure_d60(context)
@contextmanager
def patched_boundary_gate(*, initial: int, refresh: int) -> Iterator[None]:
import scripts.rectification.event_probes as ep
previous = (ep.MIN_BOUNDARY_DAYS, ep.REFRESH_MIN_BOUNDARY_DAYS)
ep.MIN_BOUNDARY_DAYS = int(initial)
ep.REFRESH_MIN_BOUNDARY_DAYS = int(refresh)
try:
yield
finally:
ep.MIN_BOUNDARY_DAYS, ep.REFRESH_MIN_BOUNDARY_DAYS = previous
def production_defaults_intact() -> bool:
import scripts.rectification.event_probes as ep
return ep.MIN_BOUNDARY_DAYS == 45 and ep.REFRESH_MIN_BOUNDARY_DAYS == 30
def close_same_year_windows(left: date, right: date, min_days: int) -> list[date]:
return list(_boundary_windows([left], [right], min_days=min_days))
def _record_varga(policy: VargaPolicy, time: str, prefix: str, delta: float) -> None:
policy.hits[prefix] = policy.hits.get(prefix, 0) + 1
policy.points[prefix] = round(policy.points.get(prefix, 0.0) + delta, 6)
by_time = policy.points_by_time.setdefault(time, {})
by_time[prefix] = round(by_time.get(prefix, 0.0) + delta, 6)
def score_event_with_policy(
*,
candidate_time: str,
event: dict[str, Any],
natal_chart: dict[str, Any],
varga_by_prefix: dict[str, dict[str, Any]],
vimshottari: tuple[str, str, str],
narayana: tuple[int | None, int | None],
arudha_padas: dict[str, Any],
policy: VargaPolicy,
) -> dict[str, Any]:
_, target_houses = DOMAIN_CONFIG[event["domain"]]
ascendant_index = int(natal_chart["ascendant"]["lon"] // 30)
target_lords = _house_lords(ascendant_index, target_houses)
functional = functional_benefics.derive_functional_benefic_malefic(
natal_chart["ascendant"].get("sign")
)
functional_benefics_set = set(functional.get("functional_benefics") or [])
functional_malefics_set = set(functional.get("functional_malefics") or [])
major_lord, minor_lord, pratyantar_lord = vimshottari
rules: list[str] = []
points = 0.0
active = list(varga_by_prefix.items())
count = max(len(active), 1)
for lord, weight, label in (
(major_lord, 2.0, "vim_md"),
(minor_lord, 1.5, "vim_ad"),
(pratyantar_lord, 0.75, "vim_pd"),
):
if _planet_house(natal_chart, lord) in target_houses:
rules.append(f"{label}_domain_house")
points += weight
if lord in target_lords:
rules.append(f"{label}_domain_lord")
points += weight
if not active:
pass
else:
for prefix, varga_chart in active:
if _varga_house(varga_chart, lord) not in target_houses:
continue
factor = 1.0 if policy.is_baseline else varga_factor(
prefix, policy.window_minutes, policy.cap,
)
delta = weight * factor / (2 * count)
rules.append(f"{label}_domain_varga")
points += delta
_record_varga(policy, candidate_time, prefix, delta)
if lord in functional_benefics_set:
rules.append(f"{label}_functional_benefic_auxiliary")
points += 0.2
elif lord in functional_malefics_set:
rules.append(f"{label}_functional_malefic_auxiliary")
points -= 0.1
for sign_index, weight, label in (
(narayana[0], 2.0, "narayana_md"),
(narayana[1], 1.0, "narayana_ad"),
):
if sign_index is not None and _relative_house(sign_index, ascendant_index) in target_houses:
rules.append(f"{label}_domain_house")
points += weight
arudha_keys = (
("A7", "UL") if event["domain"] == "relationship"
else ("A10",) if event["domain"] in {"career", "occupation"}
else ()
)
arudha_signs = {
value.get("sign_idx") for key in arudha_keys
if isinstance((value := arudha_padas.get(key)), dict) and isinstance(value.get("sign_idx"), int)
}
if arudha_signs:
for lord, label in ((major_lord, "vim_md"), (minor_lord, "vim_ad"), (pratyantar_lord, "vim_pd")):
planet = natal_chart.get("planets", {}).get(lord) or {}
if isinstance(planet.get("lon"), (int, float)) and int(planet["lon"] // 30) in arudha_signs:
rules.append(f"{label}_arudha_auxiliary")
points += 0.35
event_kind = event.get("event_kind", event["domain"])
if event["domain"] in AUXILIARY_DOMAINS:
points *= AUXILIARY_SCORE_FACTOR
rules.append(
"occupation_auxiliary_not_primary"
if event["domain"] == "occupation"
else "appearance_auxiliary_not_primary"
)
if not rules:
rules.append("no_domain_activation")
rules.append(f"event_kind:{event_kind}")
weighted_points = round(points * precision_weight(event["precision"]), 4)
return {
"event_id": event["id"],
"domain": event["domain"],
"candidate_time": candidate_time,
"rule_ids": rules,
"points": weighted_points,
}
def domain_varga_prefixes(domain: str, policy: VargaPolicy) -> tuple[str, ...]:
prefixes = list(DOMAIN_CONFIG[domain][0])
if policy.use_d60 and "D60" not in prefixes:
prefixes.append("D60")
if policy.name in {"V2", "V3"}:
prefixes = [item for item in prefixes if item in policy.changing]
return tuple(prefixes)
def candidate_row_with_policy(
request: dict[str, Any],
context: dict[str, Any],
policy: VargaPolicy,
) -> dict[str, Any]:
candidate_at = context["candidate_at"]
chart = context["chart"]
planet_longitudes = context["planet_longitudes"]
ascendant_index = context["ascendant_index"]
arudha_padas = context["arudha_padas"]
varga_charts = context["varga_charts"]
moon_longitude = planet_longitudes["Moon"]
evidence: list[dict[str, Any]] = []
missing_layers: list[str] = []
stamp = candidate_at.strftime("%H:%M")
for event in request["events"]:
event_at = _event_datetime(event)
prefixes = domain_varga_prefixes(event["domain"], policy)
selected = {prefix: varga_charts.get(prefix) for prefix in prefixes}
if prefixes and any(chart is None for chart in selected.values()):
missing_layers.extend(prefixes)
continue
try:
vimshottari = _active_vimshottari(candidate_at.date().isoformat(), moon_longitude, event_at)
except (KeyError, TypeError, ValueError):
missing_layers.append("Vimshottari_MD_AD_PD")
continue
try:
narayana = _active_narayana(
ascendant_index, planet_longitudes, candidate_at, event_at,
)
except (KeyError, TypeError, ValueError):
missing_layers.append("Narayana_MD_AD")
continue
if narayana[0] is None or narayana[1] is None:
missing_layers.append("Narayana_MD_AD")
continue
usable = {prefix: chart for prefix, chart in selected.items() if isinstance(chart, dict)}
evidence.append(score_event_with_policy(
candidate_time=stamp,
event=event,
natal_chart=chart,
varga_by_prefix=usable,
vimshottari=vimshottari,
narayana=narayana,
arudha_padas=arudha_padas,
policy=policy,
))
transit_rules = _controlled_transit_rules(
request, event, ascendant_index, DOMAIN_CONFIG[event["domain"]][1],
)
if transit_rules:
evidence[-1]["rule_ids"].extend(transit_rules)
evidence[-1]["points"] = round(
evidence[-1]["points"] + 0.25 * len(transit_rules) * precision_weight(event["precision"]),
4,
)
av_rules, av_points = _ashtakavarga_auxiliary(
chart, ascendant_index, DOMAIN_CONFIG[event["domain"]][1],
)
if av_rules:
evidence[-1]["rule_ids"].extend(av_rules)
evidence[-1]["points"] = round(
evidence[-1]["points"] + av_points * precision_weight(event["precision"]), 4,
)
shadbala_rules, shadbala_points = _shadbala_verified_components_auxiliary(
chart, candidate_at.hour + candidate_at.minute / 60, vimshottari,
)
if shadbala_rules:
evidence[-1]["rule_ids"].extend(shadbala_rules)
evidence[-1]["points"] = round(
evidence[-1]["points"] + shadbala_points * precision_weight(event["precision"]), 4,
)
return {
"time": stamp,
"score": round(sum(item["points"] for item in evidence), 4),
"evidence": evidence,
"missing_layers": sorted(set(
missing_layers
+ [layer for layer in context["feature"]["blocked_layers"] if layer not in OBSERVATION_ONLY_LAYERS]
)),
}
def make_row_provider(static_contexts: Sequence[dict[str, Any]], policy: VargaPolicy):
def provider(request: dict[str, Any]) -> list[dict[str, Any]]:
return [candidate_row_with_policy(request, context, policy) for context in static_contexts]
return provider
def ablate_top1(
scores: dict[str, float],
varga_points_by_time: dict[str, dict[str, float]],
true_time: str,
) -> dict[str, Any]:
if not scores:
return {"baseline_top1": None, "flips": {}}
baseline = max(scores, key=lambda time: (scores[time], time))
flips: dict[str, int] = {}
prefixes = sorted({prefix for row in varga_points_by_time.values() for prefix in row})
for prefix in prefixes:
adjusted = {
time: scores[time] - float((varga_points_by_time.get(time) or {}).get(prefix) or 0.0)
for time in scores
}
leader = max(adjusted, key=lambda time: (adjusted[time], time))
flips[prefix] = int(leader != baseline)
return {
"baseline_top1": baseline,
"true_is_top1": baseline == true_time[:5],
"flips": flips,
}
def coverage_ok(candidate: dict[str, Any], baseline: dict[str, Any]) -> bool:
if candidate.get("coverage") is None or baseline.get("coverage") is None:
return False
return float(candidate["coverage"]) + 1e-9 >= float(baseline["coverage"])
def squeezed_ok(candidate: dict[str, Any], baseline: dict[str, Any]) -> bool:
return int(candidate.get("squeezed") or 0) <= int(baseline.get("squeezed") or 0)
def gate_verdict(
baseline: dict[str, Any],
candidate: dict[str, Any],
*,
jitter7_squeezed: int | None = None,
) -> str:
if not baseline.get("n") or not candidate.get("n"):
return "uncertain"
if jitter7_squeezed is not None and int(jitter7_squeezed) > 0:
return "no_benefit"
if not coverage_ok(candidate, baseline) or not squeezed_ok(candidate, baseline):
return "no_benefit"
hit_same_or_up = float(candidate["top1"]) + 1e-9 >= float(baseline["top1"])
width_down = (
candidate.get("width_median") is not None
and baseline.get("width_median") is not None
and float(candidate["width_median"]) < float(baseline["width_median"]) - 1e-9
)
extra = float(candidate.get("refresh_mean") or 0) - float(baseline.get("refresh_mean") or 0)
width_gain = 0.0
if candidate.get("width_median") is not None and baseline.get("width_median") is not None:
width_gain = float(baseline["width_median"]) - float(candidate["width_median"])
if not hit_same_or_up:
return "no_benefit"
if width_down:
if extra >= 8 and width_gain <= 2:
return "no_benefit"
return "benefit"
return "no_benefit"
def clone_events(events: Sequence[dict[str, Any]]) -> list[dict[str, Any]]:
return [deepcopy(dict(event)) for event in events]