diff --git a/README.md b/README.md index c155ee6d..5e1c4cda 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,18 @@ python3 scripts/public_benchmark_dashboard.py \ 当前看板固定输出 `can_claim_global_first: false`,直到外部 oracle 样本、差异审计和长期公开 benchmark 都达到生产调参标准。 +外部 oracle 总控 closure 看板会合并 Dasha、Shadbala 与 Tajika/Sahams 三条硬闭环战线,给出总任务数、已验证数、第一优先级和下一条执行命令: + +```bash +python3 scripts/oracle_closure_master_dashboard.py \ + --dasha-oracle-file references/oracle/dasha_shadbala_oracle_cases.json \ + --tajika-oracle-file references/oracle/tajika_annual_oracle_cases.json \ + --format markdown \ + --output docs/benchmark/jyotish_external_oracle_closure_master_dashboard.md +``` + +当前总控看板固定输出 `total_tasks: 12`、`external_verified_tasks: 0`、`can_claim_global_oracle_closure: false`。推荐执行顺序是先填 Dasha 第一条 6 个字段,再填 Tajika/Sahams 第一条 15 个字段,最后填 Shadbala 第一条 54 个字段。 + Dasha 外部 oracle 最短闭环状态板用于把“大运外部真值”从 Shadbala 绝对值大包中拆出来,优先推进第一条可验证边界日期: ```bash diff --git a/docs/benchmark/jyotish_external_oracle_closure_master_dashboard.json b/docs/benchmark/jyotish_external_oracle_closure_master_dashboard.json new file mode 100644 index 00000000..cf8a4d79 --- /dev/null +++ b/docs/benchmark/jyotish_external_oracle_closure_master_dashboard.json @@ -0,0 +1,167 @@ +{ + "scope": "jyotish_external_oracle_closure_master_dashboard", + "schema_version": 1, + "generated_at": "2026-06-26T10:13:06.681297+00:00", + "summary": { + "total_tasks": 12, + "external_verified_tasks": 0, + "open_tasks": 12, + "can_claim_global_oracle_closure": false, + "production_tuning_allowed": false + }, + "fronts": { + "dasha": { + "front": "dasha", + "task_count": 3, + "external_verified_tasks": 0, + "open_tasks": 3, + "can_claim_closure": false, + "production_tuning_allowed": false, + "first_priority": { + "case_id": "template_steve_jobs_dasha_lahiri", + "capture_id": "external_template_steve_jobs_dasha_lahiri", + "packet_path": "references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json", + "missing_field_count": 6, + "missing_fields": [ + "metadata.tool_name", + "metadata.tool_version_or_url", + "metadata.capture_date", + "metadata.operator_note", + "metadata.source_artifact", + "target.vimshottari_start_date" + ], + "apply_command": "python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json --format json", + "validate_command": "python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --format json > /tmp/jyotish_oracle_queue_filled.json && python3 scripts/oracle_evidence_validator.py --queue-file /tmp/jyotish_oracle_queue_filled.json" + } + }, + "shadbala": { + "front": "shadbala", + "task_count": 4, + "external_verified_tasks": 0, + "open_tasks": 4, + "can_claim_closure": false, + "production_tuning_allowed": false, + "first_priority": { + "case_id": "template_redacted_place_shadbala_raman", + "capture_id": "external_template_redacted_place_shadbala_raman", + "packet_path": "references/oracle/artifacts/pending_packets/external_template_redacted_place_shadbala_raman.json", + "missing_field_count": 54, + "missing_fields": [ + "metadata.tool_name", + "metadata.tool_version_or_url", + "metadata.capture_date", + "metadata.operator_note", + "metadata.source_artifact", + "target.shadbala_components.Sun.sthana", + "target.shadbala_components.Sun.dig", + "target.shadbala_components.Sun.kala", + "target.shadbala_components.Sun.chesta", + "target.shadbala_components.Sun.naisargika", + "target.shadbala_components.Sun.drik", + "target.shadbala_components.Sun.total_rupa", + "target.shadbala_components.Moon.sthana", + "target.shadbala_components.Moon.dig", + "target.shadbala_components.Moon.kala", + "target.shadbala_components.Moon.chesta", + "target.shadbala_components.Moon.naisargika", + "target.shadbala_components.Moon.drik", + "target.shadbala_components.Moon.total_rupa", + "target.shadbala_components.Mars.sthana", + "target.shadbala_components.Mars.dig", + "target.shadbala_components.Mars.kala", + "target.shadbala_components.Mars.chesta", + "target.shadbala_components.Mars.naisargika", + "target.shadbala_components.Mars.drik", + "target.shadbala_components.Mars.total_rupa", + "target.shadbala_components.Mercury.sthana", + "target.shadbala_components.Mercury.dig", + "target.shadbala_components.Mercury.kala", + "target.shadbala_components.Mercury.chesta", + "target.shadbala_components.Mercury.naisargika", + "target.shadbala_components.Mercury.drik", + "target.shadbala_components.Mercury.total_rupa", + "target.shadbala_components.Jupiter.sthana", + "target.shadbala_components.Jupiter.dig", + "target.shadbala_components.Jupiter.kala", + "target.shadbala_components.Jupiter.chesta", + "target.shadbala_components.Jupiter.naisargika", + "target.shadbala_components.Jupiter.drik", + "target.shadbala_components.Jupiter.total_rupa", + "target.shadbala_components.Venus.sthana", + "target.shadbala_components.Venus.dig", + "target.shadbala_components.Venus.kala", + "target.shadbala_components.Venus.chesta", + "target.shadbala_components.Venus.naisargika", + "target.shadbala_components.Venus.drik", + "target.shadbala_components.Venus.total_rupa", + "target.shadbala_components.Saturn.sthana", + "target.shadbala_components.Saturn.dig", + "target.shadbala_components.Saturn.kala", + "target.shadbala_components.Saturn.chesta", + "target.shadbala_components.Saturn.naisargika", + "target.shadbala_components.Saturn.drik", + "target.shadbala_components.Saturn.total_rupa" + ], + "apply_command": "python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_redacted_place_shadbala_raman.json --format json", + "validate_command": "python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --format json > /tmp/jyotish_oracle_queue_filled.json && python3 scripts/oracle_evidence_validator.py --queue-file /tmp/jyotish_oracle_queue_filled.json" + } + }, + "tajika_sahams": { + "front": "tajika_sahams", + "task_count": 5, + "external_verified_tasks": 0, + "open_tasks": 5, + "can_claim_closure": false, + "production_tuning_allowed": false, + "first_priority": { + "case_id": "template_steve_jobs_varshaphala_1984_lahiri", + "capture_id": "external_template_steve_jobs_varshaphala_1984_lahiri", + "packet_path": "references/oracle/artifacts/pending_packets/external_template_steve_jobs_varshaphala_1984_lahiri.json", + "missing_field_count": 15, + "missing_fields": [ + "metadata.tool_name", + "metadata.tool_version_or_url", + "metadata.capture_date", + "metadata.operator_note", + "metadata.source_artifact", + "target.solar_return_datetime", + "target.varsha_lagna_deg", + "target.muntha_sign", + "target.year_lord", + "target.mudda_dasha_first_lord", + "target.sahams.punya_saham", + "target.sahams.rajya_saham", + "target.sahams.vivah_saham", + "target.tajika_yogas", + "target.source_artifact" + ], + "apply_command": "python3 scripts/tajika_annual_oracle_queue.py --oracle-file references/oracle/tajika_annual_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_steve_jobs_varshaphala_1984_lahiri.json --format json", + "validate_command": "python3 scripts/tajika_annual_oracle_queue.py --oracle-file references/oracle/tajika_annual_oracle_cases.json --format json && python3 scripts/tajika_annual_benchmark_dashboard.py --oracle-file references/oracle/tajika_annual_oracle_cases.json --format json" + } + } + }, + "next_action_order": [ + { + "front": "dasha", + "case_id": "template_steve_jobs_dasha_lahiri", + "capture_id": "external_template_steve_jobs_dasha_lahiri", + "missing_field_count": 6, + "apply_command": "python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json --format json" + }, + { + "front": "tajika_sahams", + "case_id": "template_steve_jobs_varshaphala_1984_lahiri", + "capture_id": "external_template_steve_jobs_varshaphala_1984_lahiri", + "missing_field_count": 15, + "apply_command": "python3 scripts/tajika_annual_oracle_queue.py --oracle-file references/oracle/tajika_annual_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_steve_jobs_varshaphala_1984_lahiri.json --format json" + }, + { + "front": "shadbala", + "case_id": "template_redacted_place_shadbala_raman", + "capture_id": "external_template_redacted_place_shadbala_raman", + "missing_field_count": 54, + "apply_command": "python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_redacted_place_shadbala_raman.json --format json" + } + ], + "boundary": "This dashboard merges external evidence readiness only. It does not claim prediction accuracy, does not tune production constants, and does not treat local engine output as oracle evidence." +} \ No newline at end of file diff --git a/docs/benchmark/jyotish_external_oracle_closure_master_dashboard.md b/docs/benchmark/jyotish_external_oracle_closure_master_dashboard.md new file mode 100644 index 00000000..f88381b5 --- /dev/null +++ b/docs/benchmark/jyotish_external_oracle_closure_master_dashboard.md @@ -0,0 +1,55 @@ +# Jyotish External Oracle Closure Master Dashboard + +Generated: `2026-06-26T10:13:07.673185+00:00` + +## Summary + +- total_tasks: `12` +- external_verified_tasks: `0` +- open_tasks: `12` +- can_claim_global_oracle_closure: `false` +- production_tuning_allowed: `false` + +## Fronts + +| front | tasks | verified | first priority | missing fields | +|---|---:|---:|---|---:| +| `dasha` | 3 | 0 | `template_steve_jobs_dasha_lahiri` | 6 | +| `tajika_sahams` | 5 | 0 | `template_steve_jobs_varshaphala_1984_lahiri` | 15 | +| `shadbala` | 4 | 0 | `template_redacted_place_shadbala_raman` | 54 | + +## Next Action Order + +### dasha + +- case_id: `template_steve_jobs_dasha_lahiri` +- capture_id: `external_template_steve_jobs_dasha_lahiri` +- missing_field_count: `6` + +```bash +python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json --format json +``` + +### tajika_sahams + +- case_id: `template_steve_jobs_varshaphala_1984_lahiri` +- capture_id: `external_template_steve_jobs_varshaphala_1984_lahiri` +- missing_field_count: `15` + +```bash +python3 scripts/tajika_annual_oracle_queue.py --oracle-file references/oracle/tajika_annual_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_steve_jobs_varshaphala_1984_lahiri.json --format json +``` + +### shadbala + +- case_id: `template_redacted_place_shadbala_raman` +- capture_id: `external_template_redacted_place_shadbala_raman` +- missing_field_count: `54` + +```bash +python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_redacted_place_shadbala_raman.json --format json +``` + +## Boundary + +This dashboard merges external evidence readiness only. It does not claim prediction accuracy, does not tune production constants, and does not treat local engine output as oracle evidence. diff --git a/scripts/oracle_closure_master_dashboard.py b/scripts/oracle_closure_master_dashboard.py new file mode 100644 index 00000000..466916b7 --- /dev/null +++ b/scripts/oracle_closure_master_dashboard.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +"""Generate a unified dashboard for Jyotish external-oracle closure fronts.""" + +from __future__ import annotations + +import argparse +import json +import subprocess +import sys +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + + +ROOT = Path(__file__).resolve().parents[1] +PYTHON = sys.executable + + +def _run_json(command: list[str]) -> dict[str, Any]: + completed = subprocess.run( + command, + cwd=ROOT, + text=True, + capture_output=True, + timeout=90, + check=False, + ) + if completed.returncode != 0: + raise RuntimeError(completed.stderr.strip() or completed.stdout.strip()) + return json.loads(completed.stdout) + + +def _front_from_status(name: str, status: dict[str, Any], task_key: str, verified_key: str, claim_key: str) -> dict[str, Any]: + summary = status["summary"] + first = status["first_priority"] + task_count = int(summary[task_key]) + verified = int(summary[verified_key]) + missing_fields = first.get("missing_fields", []) + return { + "front": name, + "task_count": task_count, + "external_verified_tasks": verified, + "open_tasks": task_count - verified, + "can_claim_closure": bool(summary[claim_key]), + "production_tuning_allowed": bool(summary.get("production_tuning_allowed", False)), + "first_priority": { + "case_id": first["case_id"], + "capture_id": first["capture_id"], + "packet_path": first["packet_path"], + "missing_field_count": len(missing_fields), + "missing_fields": missing_fields, + "apply_command": first.get("apply_command", ""), + "validate_command": first.get("validate_command", ""), + }, + } + + +def build_dashboard(dasha_oracle_file: str, tajika_oracle_file: str) -> dict[str, Any]: + dasha_status = _run_json([ + PYTHON, + "scripts/dasha_oracle_closure_status.py", + "--oracle-file", + dasha_oracle_file, + "--format", + "json", + ]) + shadbala_status = _run_json([ + PYTHON, + "scripts/shadbala_oracle_closure_status.py", + "--oracle-file", + dasha_oracle_file, + "--format", + "json", + ]) + tajika_status = _run_json([ + PYTHON, + "scripts/tajika_annual_closure_status.py", + "--oracle-file", + tajika_oracle_file, + "--format", + "json", + ]) + + fronts = { + "dasha": _front_from_status( + "dasha", + dasha_status, + "dasha_task_count", + "external_verified_dasha_tasks", + "can_claim_dasha_oracle_closure", + ), + "shadbala": _front_from_status( + "shadbala", + shadbala_status, + "shadbala_task_count", + "external_verified_shadbala_tasks", + "can_claim_shadbala_absolute_closure", + ), + "tajika_sahams": _front_from_status( + "tajika_sahams", + tajika_status, + "annual_task_count", + "external_verified_annual_tasks", + "can_claim_tajika_sahams_closure", + ), + } + total_tasks = sum(front["task_count"] for front in fronts.values()) + verified_tasks = sum(front["external_verified_tasks"] for front in fronts.values()) + next_action_order = sorted( + [ + { + "front": front["front"], + "case_id": front["first_priority"]["case_id"], + "capture_id": front["first_priority"]["capture_id"], + "missing_field_count": front["first_priority"]["missing_field_count"], + "apply_command": front["first_priority"]["apply_command"], + } + for front in fronts.values() + if not front["can_claim_closure"] + ], + key=lambda item: item["missing_field_count"], + ) + return { + "scope": "jyotish_external_oracle_closure_master_dashboard", + "schema_version": 1, + "generated_at": datetime.now(timezone.utc).isoformat(), + "summary": { + "total_tasks": total_tasks, + "external_verified_tasks": verified_tasks, + "open_tasks": total_tasks - verified_tasks, + "can_claim_global_oracle_closure": total_tasks > 0 and verified_tasks == total_tasks, + "production_tuning_allowed": False, + }, + "fronts": fronts, + "next_action_order": next_action_order, + "boundary": ( + "This dashboard merges external evidence readiness only. It does not claim prediction accuracy, " + "does not tune production constants, and does not treat local engine output as oracle evidence." + ), + } + + +def render_markdown(report: dict[str, Any]) -> str: + summary = report["summary"] + lines = [ + "# Jyotish External Oracle Closure Master Dashboard", + "", + f"Generated: `{report['generated_at']}`", + "", + "## Summary", + "", + f"- total_tasks: `{summary['total_tasks']}`", + f"- external_verified_tasks: `{summary['external_verified_tasks']}`", + f"- open_tasks: `{summary['open_tasks']}`", + f"- can_claim_global_oracle_closure: `{str(summary['can_claim_global_oracle_closure']).lower()}`", + f"- production_tuning_allowed: `{str(summary['production_tuning_allowed']).lower()}`", + "", + "## Fronts", + "", + "| front | tasks | verified | first priority | missing fields |", + "|---|---:|---:|---|---:|", + ] + for key in ["dasha", "tajika_sahams", "shadbala"]: + front = report["fronts"][key] + first = front["first_priority"] + lines.append( + f"| `{key}` | {front['task_count']} | {front['external_verified_tasks']} | `{first['case_id']}` | {first['missing_field_count']} |" + ) + lines.extend(["", "## Next Action Order", ""]) + for item in report["next_action_order"]: + lines.extend( + [ + f"### {item['front']}", + "", + f"- case_id: `{item['case_id']}`", + f"- capture_id: `{item['capture_id']}`", + f"- missing_field_count: `{item['missing_field_count']}`", + "", + "```bash", + item["apply_command"], + "```", + "", + ] + ) + lines.extend(["## Boundary", "", report["boundary"], ""]) + return "\n".join(lines) + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Generate unified external-oracle closure dashboard") + parser.add_argument("--dasha-oracle-file", default="references/oracle/dasha_shadbala_oracle_cases.json") + parser.add_argument("--tajika-oracle-file", default="references/oracle/tajika_annual_oracle_cases.json") + parser.add_argument("--format", choices=["json", "markdown"], default="json") + parser.add_argument("--output", help="Optional output path") + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(argv) + report = build_dashboard(args.dasha_oracle_file, args.tajika_oracle_file) + text = json.dumps(report, ensure_ascii=False, indent=2) if args.format == "json" else render_markdown(report) + if args.output: + output = Path(args.output) + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(text, encoding="utf-8") + print(text) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_oracle_closure_master_dashboard.py b/tests/test_oracle_closure_master_dashboard.py new file mode 100644 index 00000000..45fb84e5 --- /dev/null +++ b/tests/test_oracle_closure_master_dashboard.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Tests for the unified external-oracle closure master dashboard.""" + +from __future__ import annotations + +import json +import subprocess +import sys +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] + + +def run_dashboard(*args: str) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [ + sys.executable, + "scripts/oracle_closure_master_dashboard.py", + "--dasha-oracle-file", + "references/oracle/dasha_shadbala_oracle_cases.json", + "--tajika-oracle-file", + "references/oracle/tajika_annual_oracle_cases.json", + *args, + ], + cwd=ROOT, + text=True, + capture_output=True, + timeout=90, + check=False, + ) + + +def test_oracle_closure_master_dashboard_aggregates_all_hard_fronts() -> None: + completed = run_dashboard("--format", "json") + + assert completed.returncode == 0, completed.stderr or completed.stdout + report = json.loads(completed.stdout) + assert report["scope"] == "jyotish_external_oracle_closure_master_dashboard" + assert report["schema_version"] == 1 + assert report["summary"]["total_tasks"] == 12 + assert report["summary"]["external_verified_tasks"] == 0 + assert report["summary"]["open_tasks"] == 12 + assert report["summary"]["can_claim_global_oracle_closure"] is False + assert report["fronts"]["dasha"]["task_count"] == 3 + assert report["fronts"]["shadbala"]["task_count"] == 4 + assert report["fronts"]["tajika_sahams"]["task_count"] == 5 + assert report["fronts"]["dasha"]["first_priority"]["case_id"] == "template_steve_jobs_dasha_lahiri" + assert report["fronts"]["shadbala"]["first_priority"]["case_id"] == "template_redacted_place_shadbala_raman" + assert report["fronts"]["tajika_sahams"]["first_priority"]["case_id"] == "template_steve_jobs_varshaphala_1984_lahiri" + assert report["next_action_order"][0]["front"] == "dasha" + assert report["next_action_order"][0]["missing_field_count"] == 6 + assert report["next_action_order"][1]["front"] == "tajika_sahams" + assert report["next_action_order"][2]["front"] == "shadbala" + + +def test_oracle_closure_master_dashboard_markdown_can_be_written(tmp_path: Path) -> None: + output = tmp_path / "oracle_master.md" + completed = run_dashboard("--format", "markdown", "--output", str(output)) + + assert completed.returncode == 0, completed.stderr or completed.stdout + assert output.exists() + markdown = output.read_text(encoding="utf-8") + assert "# Jyotish External Oracle Closure Master Dashboard" in markdown + assert "total_tasks: `12`" in markdown + assert "can_claim_global_oracle_closure: `false`" in markdown + assert "template_steve_jobs_dasha_lahiri" in markdown + assert "template_redacted_place_shadbala_raman" in markdown + assert "template_steve_jobs_varshaphala_1984_lahiri" in markdown