"""Run the consultation evidence-card inventory. Read-only toward the engine. External VedAstro is not called. The product foreground path still joins a background gateway; this process replaces that join with the engine's own blocked payload so local timing is not a network wait. Status text from that blocked payload is what the model sees when the gateway does not return. """ from __future__ import annotations import argparse import json import os import subprocess import sys import time from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[2] SCRIPTS = ROOT / "scripts" RESEARCH = Path(__file__).resolve().parent for path in (ROOT, SCRIPTS, RESEARCH): if str(path) not in sys.path: sys.path.insert(0, str(path)) from consult_evidence_card_lib import ( # noqa: E402 QUESTIONS, card_dependencies, category_report, cut_evidence_card, duplicate_report, engine_facts, estimate_tokens, load_public_charts, part_b_coverage, source_matrix, verbatim_check, ) def _block_external_vedastro() -> None: import vedastro_foreground as gateway def start(self): self.meta = { "freshness": "research_not_called", "external_vedastro": "not_called", } self.cached_gateway = gateway._blocked_foreground_vedastro( reason="research_external_vedastro_not_called", ) self.future = None return self gateway.ForegroundVedastroSession.start = start def _workflow_body(chart: dict[str, Any], question: dict[str, str]) -> dict[str, Any]: from consultation_plan_contract import PLAN_VERSION, plan_route_contract domain = question["domain"] contract = plan_route_contract(domain) if contract is None: raise RuntimeError(f"no plan contract for {domain}") body = dict(chart["body"]) body.update({ "question": question["question"], "question_text": question["question"], "theme": list(contract.themes), "plan_version": PLAN_VERSION, "strict_workflow_route": domain, "required_layers": list(contract.required_layers), "claim_boundary": contract.claim_boundary, "plan_depth": "standard", "requested_domains": list(contract.requested_domains), "timing_horizon": None, "precision_boundary": "server_evidence_required", "required_evidence_categories": list(contract.required_evidence_categories), "surface": "api_web", }) return body def _run_workflow(body: dict[str, Any]) -> dict[str, Any]: # Reuse the existing golden-capture handler instead of adding another # handler-forgery site (tests/test_api_server_growth_contract.py). from capture_report_blocked_repairs_golden import _handler return _handler()._compute_consultation_workflow(body) def _project(jobs: list[dict[str, str]], summary_path: Path) -> list[dict[str, Any]]: spec_path = summary_path.with_suffix(".jobs.json") spec_path.write_text(json.dumps({"items": jobs}), encoding="utf-8") tsx = ROOT / "frontend" / "node_modules" / "tsx" / "dist" / "cli.mjs" env = os.environ.copy() env["JYOTISHA_PROJECT_ROOT"] = str(ROOT) command = [ "node", str(tsx), str(ROOT / "scripts" / "research" / "project_consult_model_context.ts"), "project", str(spec_path), str(summary_path), ] completed = subprocess.run(command, cwd=ROOT, env=env, capture_output=True, text=True) if completed.returncode != 0: raise RuntimeError(completed.stderr[-4000:] or completed.stdout[-4000:]) return json.loads(summary_path.read_text(encoding="utf-8")) def _time_layers(chart_body: dict[str, Any]) -> dict[str, float]: """Time local layers on one birth payload. VedAstro stays blocked.""" from capture_report_blocked_repairs_golden import _handler from jyotish_api_server import ( _attach_local_consultation_layers, _build_consultation_varga_spectrum, _custom_research_dn_chart, _planet_longitudes, ) handler = _handler() timings: dict[str, float] = {} def elapsed(name: str, fn, *args, **kwargs): started = time.perf_counter() result = fn(*args, **kwargs) timings[name] = round(time.perf_counter() - started, 4) return result chart = elapsed("compute_chart", handler._compute_chart, { **chart_body, "skip_vedastro_main_entry_overview": True, }) planets = chart.get("planets") if isinstance(chart, dict) else {} ascendant = chart.get("ascendant") if isinstance(chart, dict) else {} elapsed("attach_local_layers", _attach_local_consultation_layers, handler, chart, chart_body, chart_body) if isinstance(planets, dict) and isinstance(ascendant, dict) and planets and ascendant: elapsed("varga_spectrum", _build_consultation_varga_spectrum, handler, planets, ascendant) elapsed("shadbala", handler._compute_shadbala, {**chart_body, "planets": planets, "ascendant": ascendant}) elapsed("ashtakavarga", handler._compute_ashtakavarga, {"planets": planets, "ascendant": ascendant}) elapsed("functional_benefic_malefic", handler._functional_benefic_malefic_snapshot, planets, ascendant) try: module = __import__("divisional_charts_extended", fromlist=["DivisionalChartsCalculator"]) calc = module.DivisionalChartsCalculator() planet_lons = _planet_longitudes(planets) asc_lon = float(ascendant.get("lon")) elapsed("one_research_division", _custom_research_dn_chart, calc, planet_lons, asc_lon, 3) except Exception as exc: timings["one_research_division_error"] = exc.__class__.__name__ return timings def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--out", default=str(ROOT / "docs" / "research" / "consult_evidence_card_inventory_2026_09_27.json")) parser.add_argument("--cache", default="") parser.add_argument("--only-chart", action="append", default=[]) parser.add_argument("--only-question", action="append", default=[]) parser.add_argument("--skip-timing", action="store_true") args = parser.parse_args() if os.environ.get("PYTHONHASHSEED") != "0": raise SystemExit("Set PYTHONHASHSEED=0 before starting this process (ERR-111).") _block_external_vedastro() cache = Path(args.cache) if args.cache else Path(os.environ.get("TEMP", ".")) / "consult-evidence-card-20260927" cache.mkdir(parents=True, exist_ok=True) charts = load_public_charts(ROOT) questions = list(QUESTIONS) if args.only_chart: charts = [chart for chart in charts if chart["id"] in args.only_chart] if args.only_question: questions = [item for item in questions if item["id"] in args.only_question] runs = [] jobs = [] for chart in charts: for question in questions: run_id = f"{chart['id']}__{question['id']}" workflow_path = cache / f"{run_id}.workflow.json" started = time.perf_counter() workflow = _run_workflow(_workflow_body(chart, question)) wall = round(time.perf_counter() - started, 3) workflow_path.write_text(json.dumps(workflow, ensure_ascii=False), encoding="utf-8") projected_path = cache / f"{run_id}.model.json" jobs.append({ "id": run_id, "domain": question["domain"], "question": question["question"], "workflow_path": str(workflow_path), "out_path": str(projected_path), }) runs.append({ "id": run_id, "chart_id": chart["id"], "chart_label": chart["label"], "question_id": question["id"], "domain": question["domain"], "wall_seconds": wall, "workflow_chars": workflow_path.stat().st_size, "route": (workflow.get("routing") or {}).get("question_type"), "focus_techniques": (workflow.get("routing") or {}).get("focus_techniques"), "success": workflow.get("success"), }) print(f"{run_id} wall={wall}s route={runs[-1]['route']}", flush=True) summary_path = cache / "projection-summary.json" projected = {item["id"]: item for item in _project(jobs, summary_path)} inventory = [] for run, job in zip(runs, jobs): model_context = json.loads(Path(job["out_path"]).read_text(encoding="utf-8")) workflow = json.loads(Path(job["workflow_path"]).read_text(encoding="utf-8")) categories = category_report(model_context) card = cut_evidence_card(model_context, run["question_id"]) facts = engine_facts(workflow) check = verbatim_check(card["card"], facts) inventory.append({ **run, "projection": projected.get(run["id"]), "categories": categories, "duplicates": duplicate_report(model_context), "card_size": card["size"], "card_gaps": card["gaps"], "part_b": part_b_coverage(card["card"], run["question_id"]), "verbatim": check, "card_dependencies": card_dependencies(run["question_id"]), "sample_card": card["card"] if run["chart_id"] == "steve_jobs" and run["question_id"] in {"parents", "career"} else None, }) timings = {} if not args.skip_timing: for chart in charts: print(f"timing {chart['id']}", flush=True) try: timings[chart["id"]] = _time_layers(chart["body"]) except Exception as exc: timings[chart["id"]] = {"error": exc.__class__.__name__, "message": str(exc)[:300]} payload = { "baseline": "76924e3362c0a47d9d8de896c448c66055826f70", "reference_date": "2026-09-27", "ayanamsa": "raman", "node_mode": "mean", "pythonhashseed": "0", "external_vedastro": "not_called", "token_method": estimate_tokens("")["token_method"], "charts": [ {"id": chart["id"], "label": chart["label"], "source": chart["source"], "case_id": chart["case_id"], "rodden_rating": chart["rodden_rating"]} for chart in load_public_charts(ROOT) ], "source_matrix": source_matrix(ROOT), "runs": inventory, "layer_timings_seconds": timings, } out = Path(args.out) out.parent.mkdir(parents=True, exist_ok=True) out.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") print(f"wrote {out}", flush=True) return 0 if __name__ == "__main__": raise SystemExit(main())