record public PyJHora parity evidence
This commit is contained in:
@@ -329,6 +329,7 @@ def main(argv=None):
|
||||
parser.add_argument('--sample-id', action='append', default=[], help='Run only a named benchmark sample; repeatable.')
|
||||
parser.add_argument('--build-local', action='store_true', help='Explicitly generate missing local canonical baselines.')
|
||||
parser.add_argument('--node-mode', choices=['mean', 'true'], default='mean', help='Match the node convention before comparing.')
|
||||
parser.add_argument('--output-prefix', default='', help='Optional filename prefix for resumable batch artifacts.')
|
||||
args = parser.parse_args(argv)
|
||||
PYJHORA_OUT.mkdir(parents=True, exist_ok=True)
|
||||
samples = json.loads(DATA.read_text())
|
||||
@@ -356,13 +357,14 @@ def main(argv=None):
|
||||
local = json.loads(local_path.read_text())
|
||||
all_rows.extend(compare_one(sample['id'], local, pyjhora))
|
||||
|
||||
matrix = OUT / 'pyjhora_comparison_matrix.csv'
|
||||
prefix = f"{args.output_prefix}_" if args.output_prefix else ''
|
||||
matrix = OUT / f'{prefix}pyjhora_comparison_matrix.csv'
|
||||
with matrix.open('w', newline='') as f:
|
||||
writer = csv.DictWriter(f, fieldnames=['sample_id', 'section', 'body', 'field', 'local_skill', 'pyjhora', 'delta', 'status'])
|
||||
writer.writeheader()
|
||||
writer.writerows(all_rows)
|
||||
|
||||
report = OUT / 'jyotish_benchmark_round3_pyjhora_compare.md'
|
||||
report = OUT / f'{prefix}jyotish_benchmark_round3_pyjhora_compare.md'
|
||||
report.write_text(write_report(samples, all_rows))
|
||||
print(json.dumps({'report': str(report), 'matrix': str(matrix), 'samples': len(samples), 'fields': len(all_rows)}, ensure_ascii=False, indent=2))
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# PyJHora Same-Chart Parity: Public Smoke Batch
|
||||
|
||||
Date: 2026-07-12
|
||||
|
||||
## Scope
|
||||
|
||||
Ten public/synthetic smoke birth records were replayed through the local
|
||||
canonical baseline and an isolated PyJHora comparison runner. Both sides used
|
||||
Lahiri ayanamsa and Mean Node mode. No user birth record or private event data
|
||||
was used.
|
||||
|
||||
## Result
|
||||
|
||||
| Field status | Count |
|
||||
|---|---:|
|
||||
| `match` | 836 |
|
||||
| `boundary_sensitive` | 4 |
|
||||
| `mismatch` | 0 |
|
||||
| Total compared | 840 |
|
||||
|
||||
The four boundary-sensitive rows are D10 values at divisional boundaries. They
|
||||
are retained as downgraded evidence, not silently counted as exact matches.
|
||||
|
||||
Covered outputs:
|
||||
|
||||
- D1: ascendant and nine planetary rows
|
||||
- D9
|
||||
- D10
|
||||
- current Vimshottari boundaries
|
||||
|
||||
Not yet compared:
|
||||
|
||||
- D2 / D4
|
||||
- Shadbala
|
||||
- Ashtakavarga
|
||||
- VedAstro official raw snapshot
|
||||
- JHora desktop export
|
||||
- jyotishganit outside its Panchanga-oriented raw coverage
|
||||
|
||||
## Reproduction
|
||||
|
||||
Use `benchmarks/jyotish/scripts/run_pyjhora_compare.py` with explicit
|
||||
`--build-local --node-mode mean`. Use `--output-prefix` for resumable batches.
|
||||
Summarize each matrix through `scripts/pyjhora_parity_summary.py`.
|
||||
|
||||
## Boundary
|
||||
|
||||
This is partial external verification for the listed outputs only. It does not
|
||||
establish full three-engine parity, global algorithmic accuracy, or event
|
||||
prediction accuracy. VedAstro remains `official_blocked` until an official raw
|
||||
response is captured and normalized.
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"scope": "pyjhora_same_chart_parity_public_smoke",
|
||||
"status": "partial_verified",
|
||||
"tested": true,
|
||||
"birth_data_policy": "public_synthetic_smoke_only",
|
||||
"settings": {
|
||||
"ayanamsa": "lahiri",
|
||||
"node_mode": "mean"
|
||||
},
|
||||
"sample_count": 10,
|
||||
"comparison_rows": {
|
||||
"total": 840,
|
||||
"match": 836,
|
||||
"boundary_sensitive": 4,
|
||||
"mismatch": 0
|
||||
},
|
||||
"covered_outputs": ["D1", "D9", "D10", "Vimshottari"],
|
||||
"missing_required_outputs": ["D2", "D4", "Shadbala", "Ashtakavarga"],
|
||||
"source_report": "docs/research/pyjhora_same_chart_parity_2026_07_12.md",
|
||||
"boundary": "Partial PyJHora verification only. It is not JHora desktop verification, VedAstro official raw closure, jyotishganit full-chart parity, or global predictive validation."
|
||||
}
|
||||
@@ -5,6 +5,7 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
from diagnose_vedastro_mode import build_report as build_vedastro_report
|
||||
@@ -21,13 +22,22 @@ except Exception: # pragma: no cover - import path varies in tests/CLI
|
||||
REQUIRED_PARITY_OUTPUTS = ["D1", "D9", "D10", "D2", "D4", "Vimshottari", "Shadbala", "Ashtakavarga"]
|
||||
|
||||
|
||||
def _public_pyjhora_parity_manifest() -> dict:
|
||||
path = Path("references/oracle/pyjhora_same_chart_parity_public_smoke_manifest.json")
|
||||
try:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
except (OSError, json.JSONDecodeError):
|
||||
return {"status": "not_available", "tested": False}
|
||||
|
||||
|
||||
def _same_chart_parity_contract(engines: dict) -> dict:
|
||||
pyjhora_public = _public_pyjhora_parity_manifest()
|
||||
engine_states = {}
|
||||
for name, engine in engines.items():
|
||||
available = engine["status"] == "available"
|
||||
engine_states[name] = {
|
||||
"available": available,
|
||||
"tested": False,
|
||||
"tested": bool(name == "PyJHora/JHora" and pyjhora_public.get("tested")),
|
||||
"blocked": not available,
|
||||
"blocking_reason": "" if available else engine["status"],
|
||||
}
|
||||
@@ -60,7 +70,8 @@ def _same_chart_parity_contract(engines: dict) -> dict:
|
||||
},
|
||||
"engine_states": engine_states,
|
||||
"replay_manifest": replay_manifest,
|
||||
"boundary": "This is a parity contract, not proof that the same-chart comparison has run.",
|
||||
"partial_verifications": {"PyJHora/JHora": pyjhora_public},
|
||||
"boundary": "This is a parity contract. Public PyJHora partial verification does not close missing outputs or other engine raw-oracle requirements.",
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@ def test_external_engine_adapter_diagnostics_aggregates_three_engines() -> None:
|
||||
assert "official_raw_response" in contract["expected_oracle_fields"]["VedAstro"]
|
||||
assert "raw_output_path" in contract["expected_oracle_fields"]["PyJHora/JHora"]
|
||||
assert contract["engine_states"]["jyotishganit"]["available"] is True
|
||||
assert contract["engine_states"]["PyJHora/JHora"]["tested"] is False
|
||||
assert contract["engine_states"]["PyJHora/JHora"]["tested"] is True
|
||||
pyjhora = contract["partial_verifications"]["PyJHora/JHora"]
|
||||
assert pyjhora["status"] == "partial_verified"
|
||||
assert pyjhora["missing_required_outputs"] == ["D2", "D4", "Shadbala", "Ashtakavarga"]
|
||||
assert contract["replay_manifest"]["tested"] is False
|
||||
assert contract["replay_manifest"]["blocked_reason"] == "no_same_chart_oracle_rows_imported"
|
||||
assert report["status"] in {"complete", "partial"}
|
||||
|
||||
@@ -14,4 +14,5 @@ def test_pyjhora_compare_help_is_non_executing():
|
||||
|
||||
assert result.returncode == 0
|
||||
assert "--build-local" in result.stdout
|
||||
assert "--output-prefix" in result.stdout
|
||||
assert "FileNotFoundError" not in result.stderr
|
||||
|
||||
Reference in New Issue
Block a user