fix(rectification): offer representative time once event-fit is enough
Keep unique-top and width on confirmation only, and stop lagna-frame follow-ups from blocking cards on an already-scored cluster. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -481,11 +481,13 @@ def build_decision_receipt(
|
||||
reasons = [*acceptance_reasons, *confirmation_reasons]
|
||||
|
||||
representative = candidate_decisions[0] if candidate_decisions else None
|
||||
width = indistinguishable_width_minutes(candidate_decisions)
|
||||
packet = build_refinement_packet(
|
||||
request,
|
||||
built,
|
||||
representative_time=representative["time"] if representative else None,
|
||||
candidate_times=[item["time"] for item in candidate_decisions],
|
||||
cluster_width_minutes=width,
|
||||
)
|
||||
if packet["dasha_agreement"]["status"] == "conflict":
|
||||
if overall_confidence == "high":
|
||||
@@ -494,7 +496,6 @@ def build_decision_receipt(
|
||||
overall_confidence = "low"
|
||||
reasons.append("vimshottari_narayana_conflict")
|
||||
confirmation_reasons.append("vimshottari_narayana_conflict")
|
||||
width = indistinguishable_width_minutes(candidate_decisions)
|
||||
adjacent_passed = unique_top["passed"] and width <= MAX_CONFIRMATION_WIDTH_MINUTES
|
||||
confirmation_event_quality = len(scoreable_events) >= MIN_CONFIRMATION_EVENTS
|
||||
confirmation_domain_quality = len(domains) >= MIN_CONFIRMATION_DOMAINS
|
||||
@@ -508,17 +509,23 @@ def build_decision_receipt(
|
||||
confirmation_reasons.append("insufficient_confirmation_margin")
|
||||
if not adjacent_passed:
|
||||
confirmation_reasons.append("adjacent_minutes_indistinguishable")
|
||||
propose_allowed = all((
|
||||
acceptance_allowed,
|
||||
unique_top["passed"],
|
||||
diagnostic_quality["passed"],
|
||||
required_layers["passed"],
|
||||
confirmation_event_quality,
|
||||
confirmation_domain_quality,
|
||||
adjacent_passed,
|
||||
))
|
||||
fit_high = packet["event_fit_rate"].get("band") == "high"
|
||||
propose_allowed = bool(
|
||||
acceptance_allowed
|
||||
and required_layers["passed"]
|
||||
and (
|
||||
fit_high
|
||||
or all((
|
||||
diagnostic_quality["passed"],
|
||||
confirmation_event_quality,
|
||||
confirmation_domain_quality,
|
||||
))
|
||||
)
|
||||
)
|
||||
engine_granted = all((
|
||||
propose_allowed,
|
||||
unique_top["passed"],
|
||||
adjacent_passed,
|
||||
confirmation_margin,
|
||||
not dasha_conflict,
|
||||
))
|
||||
|
||||
@@ -181,18 +181,27 @@ def _scan_layer_value(feature: dict[str, Any], layer: str) -> int | None:
|
||||
return raw if isinstance(raw, int) else None
|
||||
|
||||
|
||||
def window_scan(built: dict[str, Any]) -> dict[str, Any]:
|
||||
def window_scan(
|
||||
built: dict[str, Any],
|
||||
*,
|
||||
start_minute: int | None = None,
|
||||
end_minute: int | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""D1/D9/D10/D4/D5/D7/D12/D24/D2/D11/D30 plus display-only pada/Hora/Ghati/Bhava/Pranapada/KP."""
|
||||
counts: dict[str, set[int]] = {layer: set() for layer in _LAYER_LABEL}
|
||||
transitions: list[dict[str, Any]] = []
|
||||
previous: dict[str, int | None] | None = None
|
||||
for feature in _features(built):
|
||||
time = _feature_time(feature)
|
||||
if time and start_minute is not None and end_minute is not None:
|
||||
clock = _clock(time)
|
||||
if clock < start_minute or clock > end_minute:
|
||||
continue
|
||||
current = {layer: _scan_layer_value(feature, layer) for layer in _LAYER_LABEL}
|
||||
for layer, bucket in counts.items():
|
||||
value = current[layer]
|
||||
if isinstance(value, int):
|
||||
bucket.add(value)
|
||||
time = _feature_time(feature)
|
||||
if previous and time:
|
||||
for layer, label in _LAYER_LABEL.items():
|
||||
before = previous[layer]
|
||||
@@ -492,14 +501,43 @@ def oos_blind_prompts(request: dict[str, Any]) -> list[dict[str, Any]]:
|
||||
return prompts[:3]
|
||||
|
||||
|
||||
def cluster_scan(
|
||||
built: dict[str, Any],
|
||||
candidate_times: Sequence[str],
|
||||
representative_time: str | None,
|
||||
width_minutes: int | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Scan only the indistinguishable candidate cluster, not the full declared range."""
|
||||
clocks: list[int] = []
|
||||
for raw in [*candidate_times, representative_time]:
|
||||
if isinstance(raw, str) and len(raw) >= 5:
|
||||
clocks.append(_clock(raw[:5]))
|
||||
if not clocks:
|
||||
return window_scan(built)
|
||||
lo, hi = min(clocks), max(clocks)
|
||||
span = hi - lo + 1
|
||||
width = max(int(width_minutes or 0), span, 1)
|
||||
if width > span:
|
||||
extra = width - span
|
||||
lo -= extra // 2
|
||||
hi += extra - extra // 2
|
||||
return window_scan(
|
||||
built,
|
||||
start_minute=max(0, lo),
|
||||
end_minute=min(24 * 60 - 1, hi),
|
||||
)
|
||||
|
||||
|
||||
def build_refinement_packet(
|
||||
request: dict[str, Any],
|
||||
built: dict[str, Any],
|
||||
*,
|
||||
representative_time: str | None,
|
||||
candidate_times: Sequence[str],
|
||||
cluster_width_minutes: int | None = None,
|
||||
) -> dict[str, Any]:
|
||||
scan = window_scan(built)
|
||||
cluster = cluster_scan(built, candidate_times, representative_time, cluster_width_minutes)
|
||||
ledger = event_dasha_ledger(request, built, representative_time)
|
||||
agreement = dasha_agreement(built, candidate_times)
|
||||
return {
|
||||
@@ -509,7 +547,7 @@ def build_refinement_packet(
|
||||
"dasha_agreement": agreement,
|
||||
"lagna_contrast": lagna_contrast(built),
|
||||
"nakshatra_boundary": nakshatra_boundary(built, representative_time),
|
||||
"precision_stage": precision_stage(scan, len(request.get("events") or [])),
|
||||
"precision_stage": precision_stage(cluster, len(request.get("events") or [])),
|
||||
"oos_blind_prompts": oos_blind_prompts(request),
|
||||
"unique_minute_claim": False,
|
||||
"confirmation_allowed": False,
|
||||
|
||||
Reference in New Issue
Block a user