Files
Jyotisha/scripts/western_oracle_adapter.py
2026-07-10 22:31:28 +08:00

135 lines
5.0 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Normalize external Western astrology oracle JSON into a western evidence packet."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
from typing import Any
try:
from western_evidence_packet import build_western_evidence_packet
except Exception: # pragma: no cover - import path varies in tests/CLI
from scripts.western_evidence_packet import build_western_evidence_packet
_ASPECT_ALIASES = {
"conj": "conjunction",
"conjunction": "conjunction",
"trine": "trine",
"sextile": "sextile",
"square": "square",
"opposition": "opposition",
"opp": "opposition",
}
def _norm(value: Any) -> str:
return str(value or "").strip().lower().replace("-", "_").replace(" ", "_")
def _aspect_label(item: dict[str, Any]) -> tuple[str, str, str]:
planet = _norm(item.get("planet") or item.get("transit_planet"))
aspect = _ASPECT_ALIASES.get(_norm(item.get("aspect")), _norm(item.get("aspect")))
target = _norm(item.get("target") or item.get("point") or item.get("natal_point"))
return planet, aspect, target
def _timing(item: dict[str, Any]) -> str:
return str(item.get("timing") or item.get("date") or item.get("window") or "unspecified")
def _signals_from_aspects(aspects: list[dict[str, Any]]) -> list[dict[str, Any]]:
signals: list[dict[str, Any]] = []
for item in aspects:
if not isinstance(item, dict):
continue
planet, aspect, target = _aspect_label(item)
timing = _timing(item)
source = str(item.get("source") or f"{planet} {aspect} {target}").replace("_", " ")
if planet == "uranus" and aspect == "conjunction" and target in {"mc", "midheaven"}:
signals.append(
{
"theme": "career_relocation",
"claim": "career_triggered_relocation",
"timing": timing,
"source": source,
}
)
if planet == "jupiter" and aspect in {"trine", "sextile"} and target in {"mercury", "venus", "mc", "midheaven"}:
signals.append(
{
"theme": "career",
"claim": "client_cooperation_opportunity",
"timing": timing,
"source": source,
}
)
if planet == "saturn" and aspect == "conjunction" and target in {"sun", "mercury", "venus"}:
signals.append(
{
"theme": "career",
"claim": "career_responsibility_test",
"timing": timing,
"source": source,
}
)
return signals
def build_packet_from_oracle_payload(
payload: dict[str, Any],
*,
route_packet: dict[str, Any],
) -> dict[str, Any]:
"""Build a standard Western packet from an external-oracle JSON payload."""
explicit_signals = payload.get("signals") if isinstance(payload.get("signals"), list) else []
aspects = payload.get("aspects") if isinstance(payload.get("aspects"), list) else []
signals = list(explicit_signals) or _signals_from_aspects(aspects)
timing_techniques = payload.get("timing_techniques")
if not isinstance(timing_techniques, dict):
timing_techniques = {}
if aspects and "aspects" not in timing_techniques:
timing_techniques = {**timing_techniques, "aspects": aspects}
packet = build_western_evidence_packet(
route_packet=route_packet,
natal=payload.get("natal") if isinstance(payload.get("natal"), dict) else {},
timing_techniques=timing_techniques,
signals=signals,
)
packet["source_engine"] = str(payload.get("source_engine") or payload.get("engine") or "external_western_oracle_json")
packet["adapter_boundary"] = {
"bundles_external_code": False,
"accepted_input": "external_json_export",
"role": "western_cross_validation_evidence",
}
return packet
def _parse_args(argv: list[str]) -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--input", required=True, help="Path to external Western oracle JSON export.")
parser.add_argument("--theme", default="general", help="Primary theme, e.g. career/marriage/wealth.")
parser.add_argument("--question-type", default=None, help="Question type override.")
return parser.parse_args(argv)
def main(argv: list[str] | None = None) -> int:
args = _parse_args(list(argv or sys.argv[1:]))
payload = json.loads(Path(args.input).read_text(encoding="utf-8"))
route_packet = {
"question_type": args.question_type or args.theme,
"primary_theme": args.theme,
}
packet = build_packet_from_oracle_payload(payload, route_packet=route_packet)
print(json.dumps(packet, ensure_ascii=False, indent=2, sort_keys=True))
return 0
if __name__ == "__main__": # pragma: no cover
raise SystemExit(main())