test: add jyotishganit local field comparison
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"scope": "d1_d60_generic_gap_queue",
|
||||
"created_at": "2026-07-19",
|
||||
"status": "queue_ready",
|
||||
"claim_status": "partial",
|
||||
"production_tuning_allowed": false,
|
||||
"truth_matrix_allowed": false,
|
||||
"source_registry": "references/oracle/d1_d60_varga_mapping_registry_2026_07_19.json",
|
||||
"generic_only_divisions": [
|
||||
"D13", "D14", "D15", "D17", "D18", "D19", "D21", "D22", "D23", "D25",
|
||||
"D26", "D28", "D29", "D31", "D32", "D33", "D34", "D35", "D36", "D37",
|
||||
"D38", "D39", "D41", "D42", "D43", "D44", "D46", "D47", "D48", "D49",
|
||||
"D50", "D51", "D52", "D53", "D54", "D55", "D56", "D57", "D58", "D59"
|
||||
],
|
||||
"required_closure_fields": [
|
||||
"traditional_name",
|
||||
"textual_source",
|
||||
"special_formula_or_generic_formula",
|
||||
"traditional_use",
|
||||
"local_formula_path",
|
||||
"api_entry_decision",
|
||||
"ui_entry_decision",
|
||||
"external_worked_example",
|
||||
"claim_boundary"
|
||||
],
|
||||
"next_action": "For each generic-only Dn, either attach a source-backed formal mapping and test, or keep hidden as generic calculation only.",
|
||||
"boundary": "Queue prevents advertising generic fallback as formal D1-D60 support."
|
||||
}
|
||||
@@ -5,8 +5,8 @@
|
||||
"production_tuning_allowed": false,
|
||||
"boundary": "Index of current governance packets only. Raw oracle artifacts remain in references/oracle/artifacts and are not all duplicated here.",
|
||||
"summary": {
|
||||
"packet_count": 34,
|
||||
"blocked_or_partial_count": 28,
|
||||
"packet_count": 45,
|
||||
"blocked_or_partial_count": 40,
|
||||
"human_review_required_count": 1
|
||||
},
|
||||
"packets": [
|
||||
@@ -281,6 +281,94 @@
|
||||
"claim_status": "observation_only",
|
||||
"consumer_policy": "research_observation_only",
|
||||
"claim_boundary": "Permissive OSS candidates and worked-example queues are registered for probes only; no truth-matrix or production-tuning upgrade."
|
||||
},
|
||||
{
|
||||
"packet_id": "local_oss_observation_inventory",
|
||||
"path": "scripts/local_oss_observation_inventory.py",
|
||||
"domain": "oss_reuse_and_worked_examples",
|
||||
"claim_status": "observation_only",
|
||||
"consumer_policy": "research_observation_only",
|
||||
"claim_boundary": "Local OSS fragments are inventoried with hash/license/API hints only; no runtime dependency or truth upgrade."
|
||||
},
|
||||
{
|
||||
"packet_id": "panchanga_api_observation_manifest",
|
||||
"path": "references/oracle/panchanga_api_observation_manifest_2026_07_19.json",
|
||||
"domain": "muhurta_panchanga",
|
||||
"claim_status": "observation_only",
|
||||
"consumer_policy": "research_observation_only",
|
||||
"claim_boundary": "panchanga_api local snapshot is docs-only; no numeric parity claim."
|
||||
},
|
||||
{
|
||||
"packet_id": "jyotishganit_field_closure_queue",
|
||||
"path": "references/oracle/jyotishganit_field_closure_queue_2026_07_19.json",
|
||||
"domain": "three_engine_field_closure",
|
||||
"claim_status": "observation_only",
|
||||
"consumer_policy": "research_observation_only",
|
||||
"claim_boundary": "Field-level closure queue only; does not resolve mismatch rows."
|
||||
},
|
||||
{
|
||||
"packet_id": "vedicastro_kp_surface_locator",
|
||||
"path": "scripts/vedicastro_kp_surface_locator.py",
|
||||
"domain": "kp_precision_timing",
|
||||
"claim_status": "observation_only",
|
||||
"consumer_policy": "research_observation_only",
|
||||
"claim_boundary": "Locates KP source surface and missing/candidate table paths; no cusp truth upgrade."
|
||||
},
|
||||
{
|
||||
"packet_id": "product_skill_source_boundary",
|
||||
"path": "references/oracle/product_skill_source_boundary_2026_07_19.json",
|
||||
"domain": "skill_product_reference",
|
||||
"claim_status": "reference_only",
|
||||
"consumer_policy": "skill_prompt_reference_only",
|
||||
"claim_boundary": "rishi-ai-mcp and vedic-astro-skills stay out of numeric truth layer."
|
||||
},
|
||||
{
|
||||
"packet_id": "jyotishganit_field_probe",
|
||||
"path": "references/oracle/jyotishganit_field_probe_steve_jobs_2026_07_19.json",
|
||||
"domain": "three_engine_field_closure",
|
||||
"claim_status": "observation_only",
|
||||
"consumer_policy": "research_observation_only",
|
||||
"claim_boundary": "jyotishganit D2/D4/D9/D10 Panchanga AV raw/hash attached; Shadbala missing remains partial."
|
||||
},
|
||||
{
|
||||
"packet_id": "vedicastro_kp_api_probe",
|
||||
"path": "references/oracle/vedicastro_kp_api_probe_2026_07_19.json",
|
||||
"domain": "kp_precision_timing",
|
||||
"claim_status": "observation_only",
|
||||
"consumer_policy": "research_observation_only",
|
||||
"claim_boundary": "VedicAstro KP API/source hash captured; exact cusp truth still requires public numeric worked examples."
|
||||
},
|
||||
{
|
||||
"packet_id": "public_worked_example_queue",
|
||||
"path": "references/oracle/public_worked_example_queue_2026_07_19.json",
|
||||
"domain": "worked_example_collection",
|
||||
"claim_status": "open_queue",
|
||||
"consumer_policy": "research_queue_only",
|
||||
"claim_boundary": "Public worked-example queue only; URLs/search terms are not oracle-ready until numeric fields and hashes are captured."
|
||||
},
|
||||
{
|
||||
"packet_id": "d1_d60_varga_mapping_registry",
|
||||
"path": "references/oracle/d1_d60_varga_mapping_registry_2026_07_19.json",
|
||||
"domain": "varga_mapping",
|
||||
"claim_status": "partial",
|
||||
"consumer_policy": "research_to_commercial_contract_only",
|
||||
"claim_boundary": "D1-D60 rows are enumerated; generic fallback rows are not verified formal varga support."
|
||||
},
|
||||
{
|
||||
"packet_id": "jyotishganit_vs_local_field_comparison",
|
||||
"path": "references/oracle/jyotishganit_vs_local_field_comparison_steve_jobs_2026_07_19.json",
|
||||
"domain": "three_engine_field_closure",
|
||||
"claim_status": "observation_only",
|
||||
"consumer_policy": "research_observation_only",
|
||||
"claim_boundary": "Local vs jyotishganit D2/D4/D9/D10 sign comparison with hash; mismatch attribution still pending."
|
||||
},
|
||||
{
|
||||
"packet_id": "d1_d60_generic_gap_queue",
|
||||
"path": "references/oracle/d1_d60_generic_gap_queue_2026_07_19.json",
|
||||
"domain": "varga_mapping",
|
||||
"claim_status": "partial",
|
||||
"consumer_policy": "research_to_commercial_contract_only",
|
||||
"claim_boundary": "40 generic-only Dn rows require source/formula/oracle closure or remain hidden generic fallback."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compare local varga signs with jyotishganit observation raw.
|
||||
|
||||
Only compares fields with shared schema: D2/D4/D9/D10 sign labels plus
|
||||
coverage for Panchanga/BAV/SAV/Shadbala. Observation-only.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
TARGETS = {"D2": "D2_Hora", "D4": "D4_Chaturthamsa", "D9": "D9_Navamsa", "D10": "D10_Dasamsa"}
|
||||
|
||||
|
||||
def stable(data: Any) -> str:
|
||||
return json.dumps(data, ensure_ascii=False, sort_keys=True, separators=(",", ":"), default=str)
|
||||
|
||||
|
||||
def local_varga(args: argparse.Namespace) -> dict[str, Any]:
|
||||
cmd = [
|
||||
sys.executable,
|
||||
"scripts/jyotish_engine.py",
|
||||
"varga-full",
|
||||
"--year",
|
||||
str(args.year),
|
||||
"--month",
|
||||
str(args.month),
|
||||
"--day",
|
||||
str(args.day),
|
||||
"--hour",
|
||||
str(args.hour),
|
||||
"--minute",
|
||||
str(args.minute),
|
||||
"--lat",
|
||||
str(args.latitude),
|
||||
"--lon",
|
||||
str(args.longitude),
|
||||
"--tz",
|
||||
str(args.timezone),
|
||||
"--divisions",
|
||||
"D2,D4,D9,D10",
|
||||
]
|
||||
return json.loads(subprocess.check_output(cmd, cwd=ROOT, text=True))
|
||||
|
||||
|
||||
def jyotishganit_raw(args: argparse.Namespace) -> dict[str, Any]:
|
||||
sys.path.insert(0, str(ROOT / "references/open_source_sources/jyotishganit"))
|
||||
from jyotishganit.main import calculate_birth_chart # type: ignore
|
||||
from datetime import datetime
|
||||
|
||||
chart = calculate_birth_chart(
|
||||
datetime(args.year, args.month, args.day, args.hour, args.minute),
|
||||
args.latitude,
|
||||
args.longitude,
|
||||
args.timezone,
|
||||
args.location,
|
||||
args.name,
|
||||
)
|
||||
return chart.to_dict()
|
||||
|
||||
|
||||
def jyotishganit_signs(raw: dict[str, Any], code: str) -> dict[str, str]:
|
||||
section = raw.get("divisionalCharts", {}).get(code.lower(), {})
|
||||
rows: dict[str, str] = {}
|
||||
asc = section.get("ascendant", {}).get("sign")
|
||||
if asc:
|
||||
rows["Ascendant"] = asc
|
||||
for house in section.get("houses", []):
|
||||
for occ in house.get("occupants", []):
|
||||
planet = occ.get("celestialBody")
|
||||
sign = occ.get("sign")
|
||||
if planet and sign:
|
||||
rows[planet] = sign
|
||||
return rows
|
||||
|
||||
|
||||
def local_signs(raw: dict[str, Any], code: str) -> dict[str, str]:
|
||||
section = raw.get(TARGETS[code], {})
|
||||
return {
|
||||
body: value.get("sign")
|
||||
for body, value in section.items()
|
||||
if isinstance(value, dict) and body != "_meta" and value.get("sign")
|
||||
}
|
||||
|
||||
|
||||
def build(args: argparse.Namespace) -> dict[str, Any]:
|
||||
local = local_varga(args)
|
||||
jyo = jyotishganit_raw(args)
|
||||
rows = []
|
||||
for code in TARGETS:
|
||||
lrows = local_signs(local, code)
|
||||
jrows = jyotishganit_signs(jyo, code)
|
||||
bodies = sorted(set(lrows) | set(jrows))
|
||||
for body in bodies:
|
||||
rows.append(
|
||||
{
|
||||
"section": code,
|
||||
"body": body,
|
||||
"local_sign": lrows.get(body),
|
||||
"jyotishganit_sign": jrows.get(body),
|
||||
"status": "match" if lrows.get(body) == jrows.get(body) else "mismatch",
|
||||
}
|
||||
)
|
||||
summary = {
|
||||
"row_count": len(rows),
|
||||
"match_count": sum(1 for r in rows if r["status"] == "match"),
|
||||
"mismatch_count": sum(1 for r in rows if r["status"] == "mismatch"),
|
||||
}
|
||||
return {
|
||||
"scope": "jyotishganit_vs_local_field_comparison",
|
||||
"created_at": "2026-07-19",
|
||||
"status": "mismatch" if summary["mismatch_count"] else "match",
|
||||
"claim_status": "observation_only",
|
||||
"production_tuning_allowed": False,
|
||||
"truth_matrix_allowed": False,
|
||||
"request": vars(args),
|
||||
"summary": summary,
|
||||
"coverage": {
|
||||
"panchanga_jyotishganit": jyo.get("panchanga") is not None,
|
||||
"BAV_SAV_jyotishganit": isinstance(jyo.get("ashtakavarga"), dict)
|
||||
and "sav" in jyo.get("ashtakavarga", {}),
|
||||
"Shadbala_jyotishganit": jyo.get("shadbala") is not None or jyo.get("strengths") is not None,
|
||||
},
|
||||
"comparison_hash": hashlib.sha256(stable(rows).encode("utf-8")).hexdigest(),
|
||||
"rows": rows,
|
||||
"boundary": "Sign-level comparison only. Mismatch rows require field-level formula/ayanamsa/node/rounding attribution; do not majority-vote truth.",
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--year", type=int, default=1955)
|
||||
ap.add_argument("--month", type=int, default=2)
|
||||
ap.add_argument("--day", type=int, default=24)
|
||||
ap.add_argument("--hour", type=int, default=19)
|
||||
ap.add_argument("--minute", type=int, default=15)
|
||||
ap.add_argument("--latitude", type=float, default=37.3382)
|
||||
ap.add_argument("--longitude", type=float, default=-122.0383)
|
||||
ap.add_argument("--timezone", type=float, default=-8.0)
|
||||
ap.add_argument("--location", default="San Francisco, CA")
|
||||
ap.add_argument("--name", default="Steve Jobs public")
|
||||
ap.add_argument("--output")
|
||||
args = ap.parse_args()
|
||||
payload = build(args)
|
||||
text = json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True)
|
||||
if args.output:
|
||||
Path(args.output).write_text(text + "\n", encoding="utf-8")
|
||||
print(text)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,40 @@
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
INDEX = ROOT / "references/oracle/evidence_packet_index_2026_07_19.json"
|
||||
|
||||
|
||||
def test_jyotishganit_vs_local_comparison_outputs_sign_rows_and_hash():
|
||||
out = subprocess.check_output(["python3", "scripts/jyotishganit_vs_local_field_comparison.py"], cwd=ROOT, text=True)
|
||||
data = json.loads(out)
|
||||
assert data["scope"] == "jyotishganit_vs_local_field_comparison"
|
||||
assert data["claim_status"] == "observation_only"
|
||||
assert data["production_tuning_allowed"] is False
|
||||
assert data["truth_matrix_allowed"] is False
|
||||
assert data["summary"]["row_count"] >= 32
|
||||
assert data["comparison_hash"]
|
||||
assert {row["section"] for row in data["rows"]} == {"D2", "D4", "D9", "D10"}
|
||||
assert data["coverage"]["panchanga_jyotishganit"] is True
|
||||
assert data["coverage"]["BAV_SAV_jyotishganit"] is True
|
||||
assert data["coverage"]["Shadbala_jyotishganit"] is False
|
||||
|
||||
|
||||
def test_d1_d60_generic_gap_queue_lists_all_generic_only_rows():
|
||||
data = json.loads((ROOT / "references/oracle/d1_d60_generic_gap_queue_2026_07_19.json").read_text(encoding="utf-8"))
|
||||
assert data["scope"] == "d1_d60_generic_gap_queue"
|
||||
assert data["claim_status"] == "partial"
|
||||
assert data["production_tuning_allowed"] is False
|
||||
assert len(data["generic_only_divisions"]) == 40
|
||||
assert "D13" in data["generic_only_divisions"]
|
||||
assert "D59" in data["generic_only_divisions"]
|
||||
assert "external_worked_example" in data["required_closure_fields"]
|
||||
|
||||
|
||||
def test_evidence_index_registers_comparison_and_generic_gap_queue():
|
||||
index = json.loads(INDEX.read_text(encoding="utf-8"))
|
||||
packets = {row["packet_id"]: row for row in index["packets"]}
|
||||
assert packets["jyotishganit_vs_local_field_comparison"]["claim_status"] == "observation_only"
|
||||
assert packets["d1_d60_generic_gap_queue"]["claim_status"] == "partial"
|
||||
Reference in New Issue
Block a user