Files
Jyotisha/scripts/vedastro_evidence_orchestrator.py
T
2026-06-29 10:26:54 +08:00

134 lines
5.0 KiB
Python

#!/usr/bin/env python3
"""Shared VedAstro evidence orchestration layer.
The orchestrator does not expose hundreds of VedAstro nodes to users. It picks
the smallest useful domain scan set for the current route and delegates the
actual external boundary to ``vedastro_service_adapter``.
"""
from __future__ import annotations
from datetime import datetime, timedelta
from typing import Any
try:
from scripts.vedastro_service_adapter import (
VEDASTRO_CALCULATION_COVERAGE,
run_range_scan_for_case,
)
except ModuleNotFoundError: # pragma: no cover - script execution path
from vedastro_service_adapter import VEDASTRO_CALCULATION_COVERAGE, run_range_scan_for_case
ROUTE_DOMAIN_MAP = {
"relationship": ["marriage"],
"marriage": ["marriage"],
"career": ["career"],
"finance": ["wealth"],
"wealth": ["wealth"],
"rectification": ["marriage", "career", "wealth"],
"timing": ["career", "marriage", "wealth"],
"general": ["career", "marriage", "wealth"],
"overview": ["career", "marriage", "wealth"],
}
def _default_window(reference_date: str | None, days: int = 180) -> tuple[str, str]:
raw = str(reference_date or datetime.utcnow().strftime("%Y-%m-%d"))[:10]
try:
start = datetime.strptime(raw, "%Y-%m-%d").date()
except ValueError:
return raw, raw
return start.isoformat(), (start + timedelta(days=days)).isoformat()
def _normalize_case(birth_payload: dict[str, Any]) -> dict[str, Any]:
return {
"year": birth_payload.get("year"),
"month": birth_payload.get("month"),
"day": birth_payload.get("day"),
"hour": birth_payload.get("hour"),
"minute": birth_payload.get("minute"),
"second": birth_payload.get("second", 0),
"lat": birth_payload.get("lat"),
"lon": birth_payload.get("lon"),
"tz": birth_payload.get("tz"),
"ayanamsa_policy": birth_payload.get("ayanamsa_policy")
or birth_payload.get("ayanamsa")
or "lahiri",
"node_policy": birth_payload.get("node_policy")
or birth_payload.get("node_mode")
or birth_payload.get("nodeMode")
or "mean",
}
def orchestrate_vedastro_evidence(
birth_payload: dict[str, Any],
*,
route: str = "general",
reference_date: str | None = None,
start_date: str | None = None,
end_date: str | None = None,
case_id: str = "vedastro_orchestrator",
) -> dict[str, Any]:
domains = ROUTE_DOMAIN_MAP.get(route, ROUTE_DOMAIN_MAP["general"])
window_start, window_end = (start_date, end_date) if start_date and end_date else _default_window(reference_date)
case = _normalize_case(birth_payload)
domain_reports: dict[str, Any] = {}
evidence_ledger: list[dict[str, Any]] = []
top_events_by_domain: dict[str, Any] = {}
domain_statuses: dict[str, Any] = {}
domain_event_counts: dict[str, int] = {}
available = False
first_reason = None
for domain in domains:
report = run_range_scan_for_case(
case,
domain,
str(window_start),
str(window_end),
case_id=f"{case_id}_{domain}",
)
domain_reports[domain] = report
domain_statuses[domain] = report.get("status")
domain_event_counts[domain] = int(report.get("event_count", 0) or 0)
available = available or bool(report.get("available"))
first_reason = first_reason or report.get("reason")
if isinstance(report.get("top_event"), dict):
top_events_by_domain[domain] = report["top_event"]
for event in report.get("evidence_ledger") or []:
if isinstance(event, dict):
evidence_ledger.append(event)
status = "ok" if any(item == "ok" for item in domain_statuses.values()) else next(iter(domain_statuses.values()), "blocked")
return {
"backend": "vedastro_service_adapter_candidate",
"available": available,
"status": status,
"operation": "range_scan",
"domain": domains[0] if len(domains) == 1 else "overview",
"route": route,
"event_count": len(evidence_ledger),
"top_event": next(iter(top_events_by_domain.values()), None),
"top_events_by_domain": top_events_by_domain,
"evidence_ledger": evidence_ledger,
"reason": None if status == "ok" else first_reason,
"domain_reports": domain_reports,
"source_metadata": {
"auto_ingested_by": "VedAstroEvidenceOrchestrator",
"strategy": "minimal_route_scoped_orchestration",
"node_coverage": {
"strategy": "domain_scoped_range_scan",
"official_calculation_coverage": VEDASTRO_CALCULATION_COVERAGE,
"selected_domains": domains,
"not_user_exposed": True,
},
"route": route,
"scan_window": {"start_date": str(window_start), "end_date": str(window_end)},
"domain_statuses": domain_statuses,
"domain_event_counts": domain_event_counts,
},
}