feat: queue VedAstro rectification evidence packets

* feat: queue VedAstro rectification evidence packets

* fix: make report artifacts portable and normalize d11

* test: use portable runtime smoke temp directory

* test: make frontend smoke temp paths portable
This commit is contained in:
732642856
2026-07-20 01:28:57 +08:00
committed by GitHub
parent b4fee10439
commit 64fcb62f83
12 changed files with 228 additions and 7 deletions
+10 -2
View File
@@ -20,6 +20,7 @@ import secrets
import sqlite3
import threading
import time
import tempfile
import uuid
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timedelta
@@ -1312,7 +1313,10 @@ MAX_IMPORT_FILE_BYTES = 1536 * 1024
MAX_IMPORT_TEXT_CHARS = 500_000
MAX_REPORT_HTML_CHARS = 1_200_000
MAX_REPORT_BASE64_BYTES = 8 * 1024 * 1024
REPORT_ARTIFACT_DIR = os.path.join('/private/tmp', 'jyotish-reports')
REPORT_ARTIFACT_DIR = os.environ.get(
'JYOTISH_REPORT_ARTIFACT_DIR',
os.path.join(tempfile.gettempdir(), 'jyotish-reports'),
)
API_COMMAND_MAP = {
'chart': '/api/chart',
@@ -6986,7 +6990,11 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'lat': lat,
'lon': lon,
'tz': tz,
})
},
enqueue_vedastro_gateway=True,
vedastro_question='High-rigor birth-time rectification evidence packet',
vedastro_reference_date=datetime.now().strftime('%Y-%m-%d'),
)
result['can_apply'] = False
result.setdefault('reasons', []).append('three_engine_parity_not_passed')
return {
+11
View File
@@ -4923,6 +4923,17 @@ def cmd_full_reading(args):
)
except Exception as d11_error:
varga_result["D11_Rudramsa"] = {"error": str(d11_error)}
d11 = varga_result.get("D11_Rudramsa")
if isinstance(d11, dict) and isinstance(d11.get("Ascendant"), dict):
asc_sign = d11["Ascendant"].get("sign_idx")
if isinstance(asc_sign, int):
d11["planets"] = {
name: {**data, "house": ((int(data["sign_idx"]) - asc_sign) % 12) + 1}
for name, data in d11.items()
if name not in {"_meta", "Ascendant", "planets"}
and isinstance(data, dict)
and isinstance(data.get("sign_idx"), int)
}
report['modules']['varga_full'] = varga_result
# v6.1.7: Re-run Yoga with D9/D60 context after varga-full is available.
@@ -0,0 +1,48 @@
#!/usr/bin/env python3
"""Validate the public, minute-specific rectification holdout gate."""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
DEFAULT_MANIFEST = ROOT / "references" / "real_case_calibration" / "minute_rectification_holdout_v1.json"
def validate(manifest_path: Path = DEFAULT_MANIFEST) -> dict[str, Any]:
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
gate = manifest.get("minimum_gate") if isinstance(manifest.get("minimum_gate"), dict) else {}
cases = manifest.get("cases") if isinstance(manifest.get("cases"), list) else []
valid_cases = 0
invalid: list[str] = []
for case in cases:
if not isinstance(case, dict):
invalid.append("non_object_case")
continue
birth = case.get("birth_source") if isinstance(case.get("birth_source"), dict) else {}
events = case.get("events") if isinstance(case.get("events"), list) else []
negatives = case.get("negative_minutes") if isinstance(case.get("negative_minutes"), list) else []
required = birth.get("time_accuracy_rating") == "AA" and bool(birth.get("url"))
required = required and len(events) >= int(gate.get("events_per_case", 3))
required = required and len(negatives) >= int(gate.get("negative_minutes_per_case", 4))
if required:
valid_cases += 1
else:
invalid.append(str(case.get("case_id") or "unnamed_case"))
needed = int(gate.get("public_aa_cases", 20))
status = "ready_for_blind_replay" if valid_cases >= needed else "blocked_awaiting_public_aa_cases"
return {
"scope": "minute_rectification_holdout_validation",
"benchmark_id": manifest.get("benchmark_id"),
"status": status,
"valid_public_aa_cases": valid_cases,
"minimum_public_aa_cases": needed,
"invalid_cases": invalid,
"verified_minute_claim_allowed": False,
"boundary": manifest.get("boundary"),
}
if __name__ == "__main__":
print(json.dumps(validate(), ensure_ascii=False, indent=2, sort_keys=True))
+54 -2
View File
@@ -51,7 +51,44 @@ def _jyotishganit_d1(case: dict[str, Any]) -> dict[str, str]:
sys.path.remove(str(JYOTISHGANIT_ROOT))
def build_packet(case: dict[str, Any]) -> dict[str, Any]:
def _gateway_job_receipt(job: dict[str, Any]) -> dict[str, Any]:
"""Return only pollable, non-sensitive VedAstro job state for a packet."""
archive = job.get("raw_response_archive")
archive = archive if isinstance(archive, dict) else {}
return {
"scope": "vedastro_gateway_job_receipt",
"status": str(job.get("status") or "blocked"),
"job_id": str(job.get("job_id") or ""),
"poll_path": str(job.get("poll_path") or ""),
"raw_response_archive": {
"status": str(archive.get("status") or "unknown"),
"official_raw_response_available": bool(archive.get("official_raw_response_available")),
},
"boundary": "VedAstro raw response remains server-side; this receipt never returns request data or raw evidence.",
}
def _enqueue_vedastro_gateway_job(
case: dict[str, Any], *, question: str = "", reference_date: str = ""
) -> dict[str, Any]:
from scripts.vedastro_gateway import enqueue_gateway_job
job = enqueue_gateway_job(
case,
question=question,
themes=["rectification"],
reference_date=reference_date,
)
return _gateway_job_receipt(job)
def build_packet(
case: dict[str, Any],
*,
enqueue_vedastro_gateway: bool = False,
vedastro_question: str = "",
vedastro_reference_date: str = "",
) -> dict[str, Any]:
"""Compare local/PyJHora/jyotishganit D1 without persisting private input."""
required = {"year", "month", "day", "hour", "minute", "lat", "lon", "tz"}
if not required <= set(case):
@@ -66,6 +103,21 @@ def build_packet(case: dict[str, Any]) -> dict[str, Any]:
outputs[name] = {}
engine_status[name] = f"blocked:{exc.__class__.__name__}"
rows = [{"planet": planet, "values": {name: data.get(planet) for name, data in outputs.items()}, "status": "match" if len({data.get(planet) for data in outputs.values()}) == 1 else "mismatch"} for planet in PLANETS]
vedastro = {"status": "requires_gateway_raw_archive"}
if enqueue_vedastro_gateway:
try:
vedastro = _enqueue_vedastro_gateway_job(
case,
question=vedastro_question,
reference_date=vedastro_reference_date,
)
except Exception as exc:
vedastro = {
"scope": "vedastro_gateway_job_receipt",
"status": "blocked",
"reason": f"gateway_enqueue_failed:{exc.__class__.__name__}",
"boundary": "VedAstro raw response remains server-side; no raw evidence was returned.",
}
return {
"scope": "request_level_three_engine_d1_parity",
"case_hash": case_hash(case),
@@ -73,7 +125,7 @@ def build_packet(case: dict[str, Any]) -> dict[str, Any]:
"match_count": sum(row["status"] == "match" for row in rows),
"mismatch_count": sum(row["status"] == "mismatch" for row in rows),
"rows": rows,
"vedastro": {"status": "requires_gateway_raw_archive"},
"vedastro": vedastro,
"can_confirm": False,
"boundary": "D1 parity alone never confirms a rectified minute; VedAstro raw and domain-level parity remain required.",
}