diff --git a/SKILL.md b/SKILL.md index 924219ea..7884c6da 100644 --- a/SKILL.md +++ b/SKILL.md @@ -143,11 +143,12 @@ description: 印度占星(Jyotish)专业解盘与推运系统。核心能力 **普通用户解释时必须显式区分基础排盘高可信与高阶绝对值待外部校准。** -- Dasha/Shadbala Calibration Status:`ready_for_calibration: 0`,`external_oracle_evidence_validation.valid_packets: 0`。 -- D1/D9/SAV 高可信;但大运起点和 Shadbala 绝对值仍在外部 evidence validator 校准中。 -- 不得把大运起点或 Shadbala 绝对值说成已完成外部校准;涉及具体日期、剩余天数、绝对 Rupa/Virupa 分值时,必须声明当前只可作参考标定。 +- Dasha-only 外部证据已进入专项闭环:`dasha_external_oracle_evidence_validation.valid_dasha_packets: 1/3`;首个 Steve Jobs / Lahiri / Vimshottari 起始边界来自 PyJHora 4.8.7 隔离黑盒 stdout artifact。 +- 全局 Dasha/Shadbala Calibration Status 仍未完成:`external_oracle_evidence_validation.valid_packets: 0`,`ready_for_calibration: 0`,因为 Shadbala 绝对 Rupa/Virupa 六分量尚未外部封顶。 +- D1/D9/SAV 高可信;Dasha 精细日期可引用已验证 Dasha-only 样本的局部进度,但不得把全部大运边界、Shadbala 绝对值或全局精度说成已完成外部校准。 - `production_tuning_allowed: false` 前,禁止为了贴合单份 PDF、单个 JHora 截图或本仓库本地输出而改生产常数。 -- 对普通用户的建议话术:基础落座、D9、SAV 可作为稳定证据;Dasha/Shadbala 精细边界需等 JHora/PyJHora 黑盒证据包通过 `external_oracle_evidence_validation` 后再提升置信度。 +- 对普通用户的建议话术:基础落座、D9、SAV 可作为稳定证据;Dasha 精细边界已有首个外部黑盒样本但仍需扩展,Shadbala 绝对值仍需 JHora/PyJHora/公开书例六分量证据后再提升置信度。 +- 工作流要求:Dasha-only packet 用 `python3 scripts/dasha_oracle_evidence_validator.py --queue-file ` 验证;全局校准仍必须跑 `python3 scripts/oracle_evidence_validator.py --queue-file `,两者不可混用。 ### Ashtakavarga 口径冻结(v6.0.8-av-calibration) diff --git a/docs/research/oracle_closure_master_dashboard_latest.md b/docs/research/oracle_closure_master_dashboard_latest.md index ecf077a9..ebb2cb07 100644 --- a/docs/research/oracle_closure_master_dashboard_latest.md +++ b/docs/research/oracle_closure_master_dashboard_latest.md @@ -1,12 +1,12 @@ # Jyotish External Oracle Closure Master Dashboard -Generated: `2026-06-26T16:09:33.650704+00:00` +Generated: `2026-06-26T16:35:14.439008+00:00` ## Summary - total_tasks: `12` -- external_verified_tasks: `0` -- open_tasks: `12` +- external_verified_tasks: `1` +- open_tasks: `11` - can_claim_global_oracle_closure: `false` - production_tuning_allowed: `false` @@ -14,7 +14,7 @@ Generated: `2026-06-26T16:09:33.650704+00:00` | front | tasks | verified | first priority | missing fields | manual entries | metadata missing | target missing | |---|---:|---:|---|---:|---:|---:|---:| -| `dasha` | 3 | 0 | `template_steve_jobs_dasha_lahiri` | 6 | 6 | 5 | 1 | +| `dasha` | 3 | 1 | `template_user_REDACTED_YEAR_moon_longitude_lahiri` | 6 | 6 | 5 | 1 | | `tajika_sahams` | 5 | 0 | `template_steve_jobs_varshaphala_1984_lahiri` | 15 | 15 | 5 | 10 | | `shadbala` | 4 | 0 | `template_redacted_place_shadbala_raman` | 55 | 55 | 5 | 50 | @@ -22,13 +22,13 @@ Generated: `2026-06-26T16:09:33.650704+00:00` ### dasha -- case_id: `template_steve_jobs_dasha_lahiri` -- capture_id: `external_template_steve_jobs_dasha_lahiri` +- case_id: `template_user_REDACTED_YEAR_moon_longitude_lahiri` +- capture_id: `external_template_user_REDACTED_YEAR_moon_longitude_lahiri` - missing_field_count: `6` - manual_entry_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 +python3 scripts/oracle_collection_queue.py --oracle-file references/oracle/dasha_shadbala_oracle_cases.json --apply-packet references/oracle/artifacts/pending_packets/external_template_user_REDACTED_YEAR_moon_longitude_lahiri.json --format json ``` ### tajika_sahams diff --git a/docs/research/public_benchmark_dashboard_latest.md b/docs/research/public_benchmark_dashboard_latest.md index 5f5f3c34..47fca507 100644 --- a/docs/research/public_benchmark_dashboard_latest.md +++ b/docs/research/public_benchmark_dashboard_latest.md @@ -1,6 +1,6 @@ # Public Jyotish Benchmark Dashboard -Generated: `2026-06-26T16:09:33.617633+00:00` +Generated: `2026-06-26T16:35:34.078774+00:00` ## Capability Registry @@ -14,6 +14,8 @@ Generated: `2026-06-26T16:09:33.617633+00:00` - valid_packets: `0` - ready_for_calibration: `0` - production_tuning_allowed: `false` +- valid_dasha_packets: `1` +- total_dasha_packets: `3` ## Boundary Audit @@ -28,11 +30,11 @@ Generated: `2026-06-26T16:09:33.617633+00:00` ## Remaining Gap -Dasha/Shadbala external oracle readiness remains 0, Shadbala absolute values still need component-level external evidence, and public long-term benchmark history is not yet comparable to the strongest global open-source projects. +Dasha-only external oracle readiness is 1/3; Shadbala absolute values still need component-level external evidence, and public long-term benchmark history is not yet comparable to the strongest global open-source projects. ## Next Actions -- Fill the first external JHora/PyJHora packet under references/oracle/artifacts/pending_packets. +- Fill the next open external JHora/PyJHora packet under references/oracle/artifacts/pending_packets. - Run oracle_evidence_validator.py until at least one packet is valid. - Run oracle_boundary_audit.py to inspect Dasha/Shadbala deltas without tuning constants. - Publish this dashboard after each validated sample batch. diff --git a/docs/research/skill_gap_truth_audit_latest.md b/docs/research/skill_gap_truth_audit_latest.md index e03eb1c8..c9154d40 100644 --- a/docs/research/skill_gap_truth_audit_latest.md +++ b/docs/research/skill_gap_truth_audit_latest.md @@ -1,6 +1,6 @@ # Jyotish Skill Gap Truth Audit -Generated: `2026-06-26T16:09:34.006081+00:00` +Generated: `2026-06-26T16:35:14.991645+00:00` ## Public Claim Boundary @@ -19,8 +19,8 @@ Generated: `2026-06-26T16:09:34.006081+00:00` ## External Oracle Closure - total_tasks: `12` -- external_verified_tasks: `0` -- open_tasks: `12` +- external_verified_tasks: `1` +- open_tasks: `11` - can_claim_global_oracle_closure: `false` ## Remaining Hard Fronts diff --git a/references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri_pyjhora_20260627.json b/references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri_pyjhora_20260627.json new file mode 100644 index 00000000..ec8b53d1 --- /dev/null +++ b/references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri_pyjhora_20260627.json @@ -0,0 +1,51 @@ +{ + "capture_id": "external_template_steve_jobs_dasha_lahiri", + "status": "external_verified", + "case_id": "template_steve_jobs_dasha_lahiri", + "birth": { + "year": 1955, + "month": 2, + "day": 24, + "hour": 19, + "minute": 15, + "second": 0, + "lat": 37.7749, + "lon": -122.4194, + "tz": -8 + }, + "settings": { + "ayanamsa": "lahiri", + "node_mode": "true" + }, + "required_metadata_fields": [ + "tool_name", + "tool_version_or_url", + "capture_date", + "source_artifact", + "ayanamsa", + "node_mode", + "timezone", + "operator_note" + ], + "metadata": { + "tool_name": "PyJHora", + "tool_version_or_url": "PyJHora 4.8.7 isolated /tmp black-box run", + "capture_date": "2026-06-27", + "source_artifact": "references/oracle/artifacts/pyjhora_steve_jobs_dasha_stdout_20260627.txt", + "ayanamsa": "lahiri", + "node_mode": "PyJHora default", + "timezone": "UTC-08:00", + "operator_note": "Black-box stdout from isolated /tmp virtualenv. PyJHora AGPL code was not copied into this repository; only the generated output artifact is stored as external evidence." + }, + "target_placeholders": { + "target.vimshottari_start_date": "1939-03-22" + }, + "integrity_checks": { + "must_not_come_from_local_engine": true, + "requires_external_artifact": true, + "requires_status_external_verified_before_calibration": true, + "reject_global_shadbala_scaling": true + }, + "promotion_status_after_fill": "external_verified", + "operator_goal": "Fill one external Vimshottari start date only." +} diff --git a/references/oracle/artifacts/pyjhora_steve_jobs_dasha_stdout_20260627.txt b/references/oracle/artifacts/pyjhora_steve_jobs_dasha_stdout_20260627.txt new file mode 100644 index 00000000..2bcb131a --- /dev/null +++ b/references/oracle/artifacts/pyjhora_steve_jobs_dasha_stdout_20260627.txt @@ -0,0 +1,8 @@ +panchanga / added to system path ['', '/Library/Frameworks/Python.framework/Versions/3.11/lib/python311.zip', '/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11', '/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/lib-dynload', '/private/tmp/jyotish_pyjhora_blackbox/lib/python3.11/site-packages', '/'] +PYJHORA_BLACKBOX_VERSION 4.8.7 +INPUT {"dob": [1955, 2, 24], "tob": [19, 15, 0], "place": ["San Francisco, CA", 37.7749, -122.4194, -8.0], "ayanamsa": "LAHIRI", "node_mode": "PyJHora default"} +JD 2435163.3020833335 +DASHA_START_RAW [6, 2429345.079921023] +BHUKTHI_TYPE tuple +BHUKTHI_LEN 2 +BHUKTHI_HEAD ((3, 0, 26), [[(6, 6), (1939, 3, 22, 15.191221296787262), 3.0083333333328657], [(6, 3), (1942, 3, 25, 10.460264883935452), 2.6916666666661144], [(6, 8), (1944, 12, 2, 13.806251250207424), 1.1083333333336307], [(6, 5), (1946, 1, 11, 9.536951523274183), 3.1666666666662415], [(6, 0), (1949, 3, 13, 0.7675237208604813), 0.950000000000255], [(6, 1), (1950, 2, 23, 0.5366953834891319), 1.5833333333337583], [(6, 2), (1951, 9, 24, 8.151981487870216), 1.1083333333336307], [(6, 7), (1952, 11, 2, 3.8826817609369755), 2.84999999999949], [(6, 4), (1955, 9, 9, 3.1901967376470566), 2.533333333334013], [(3, 3), (1958, 3, 22, 10.574654504656792), 2.408333333333376], [(3, 8), (1960, 8, 18, 2.200010731816292), 0.9916666666671341], [(3, 5), (1961, 8, 15, 7.2222162410616875), 2.8333333333337585], [(3, 0), (1964, 6, 15, 4.428517688065767), 0.84999999999949], [(3, 1), (1965, 4, 21, 15.590408116579056), 1.4166666666662417], [(3, 2), (1966, 9, 21, 2.1935588344931602), 0.9916666666671341], [(3, 7), (1967, 9, 18, 7.215764343738556), 2.549999999999745], [(3, 4), (1970, 4, 6, 16.701435640454292), 2.266666666667007], [(3, 6), (1972, 7, 12, 14.466476798057556), 2.6916666666661144], [(8, 8), (1975, 3, 22, 17.81246316432953), 0.40833333333337585], [(8, 5), (1975, 8, 18, 21.292194843292236), 1.1666666666662417], [(8, 0), (1976, 10, 18, 0.3771424926817417), 0.34999999999949005], [(8, 1), (1977, 2, 22, 20.502626784145832), 0.5833333333337583], [(8, 2), (1977, 9, 23, 22.04510061442852), 0.40833333333337585], [(8, 7), (1978, 2, 20, 1.5248322933912277), 1.049999999999745], [(8, 4), (1979, 3, 10, 13.90128517895937), 0.9333333333332483], [(8, 6), (1980, 2, 14, 11.569243300706148), 1.1083333333336307], [(8, 3), (1981, 3, 25, 7.299943573772907), 0.9916666666671341], [(5, 5), (1982, 3, 22, 12.322149083018303), 3.3333333333337585], [(5, 0), (1985, 7, 22, 0.5648566670715809), 1.0], [(5, 1), (1986, 7, 22, 6.637668941169977), 1.6666666666662417], [(5, 2), (1988, 3, 22, 0.7590227276086807), 1.1666666666662417], [(5, 7), (1989, 5, 22, 3.843970376998186), 3.0], [(5, 4), (1992, 5, 21, 22.062407199293375), 2.6666666666662415], [(5, 6), (1995, 1, 20, 22.256573259830475), 3.1666666666662415], [(5, 3), (1998, 3, 22, 13.487145457416773), 2.8333333333337585], [(5, 8), (2001, 1, 20, 10.693446904420853), 1.1666666666675165], [(0, 0), (2002, 3, 22, 13.778394564986229), 0.299999999999745], [(0, 1), (2002, 7, 10, 3.6002382449805737), 0.5], [(0, 2), (2003, 1, 8, 18.636644382029772), 0.34999999999949005], [(0, 7), (2003, 5, 16, 14.762128673493862), 0.90000000000051], [(0, 4), (2004, 4, 9, 8.227659724652767), 0.799999999999745], [(0, 6), (2005, 1, 26, 13.08590954169631), 0.950000000000255], [(0, 3), (2006, 1, 8, 12.85508120432496), 0.84999999999949], [(0, 8), (2006, 11, 15, 0.016971632838249207), 0.34999999999949005], [(0, 5), (2007, 3, 22, 20.14245592430234), 1.000000000001275], [(1, 1), (2008, 3, 22, 2.2152682095766068), 0.8333333333337583], [(1, 2), (2009, 1, 20, 11.275945108383894), 0.5833333333337583], [(1, 7), (2009, 8, 21, 12.818418938666582), 1.5], [(1, 4), (2011, 2, 20, 9.927637349814177), 1.3333333333337583], [(1, 6), (2012, 6, 21, 10.024720385670662), 1.5833333333337583], [(1, 3), (2014, 1, 20, 17.640006490051746), 1.4166666666662417], [(1, 8), (2015, 6, 22, 4.243157207965851), 0.5833333333337583], [(1, 5), (2016, 1, 21, 5.785631038248539), 1.6666666666662417], [(1, 0), (2017, 9, 20, 23.906984824687243), 0.4999999999987251], [(2, 2), (2018, 3, 22, 14.94339095056057), 0.40833333333337585], [(2, 7), (2018, 8, 18, 18.423122629523277), 1.049999999999745], [(2, 4), (2019, 9, 6, 6.799575515091419), 0.9333333333332483], [(2, 6), (2020, 8, 12, 4.467533636838198), 1.1083333333336307], [(2, 3), (2021, 9, 21, 0.19823390990495682), 0.9916666666671341], [(2, 8), (2022, 9, 18, 5.2204394191503525), 0.40833333333337585], [(2, 5), (2023, 2, 14, 8.70017109811306), 1.1666666666662417], [(2, 0), (2024, 4, 15, 11.785118747502565), 0.34999999999949005], [(2, 1), (2024, 8, 21, 7.910603038966656), 0.5833333333337583], [(7, 7), (2025, 3, 22, 9.453076869249344), 2.700000000000255], [(7, 4), (2027, 12, 3, 13.849670011550188), 2.40000000000051], [(7, 6), (2030, 4, 28, 4.4244194738566875), 2.84999999999949], [(7, 3), (2033, 3, 4, 3.7319344505667686), 2.549999999999745], [(7, 8), (2035, 9, 21, 13.217605747282505), 1.049999999999745], [(7, 5), (2036, 10, 9, 1.594058632850647), 3.0], [(7, 0), (2039, 10, 9, 19.812495455145836), 0.90000000000051], [(7, 1), (2040, 9, 2, 13.278026506304741), 1.5], [(7, 2), (2042, 3, 4, 10.387244917452335), 1.049999999999745], [(4, 4), (2043, 3, 22, 22.763697803020477), 2.1333333333335034], [(4, 6), (2045, 5, 10, 3.7190306559205055), 2.5333333333327386], [(4, 3), (2047, 11, 21, 11.10348841175437), 2.266666666667007], [(4, 8), (2050, 2, 26, 8.868529569357634), 0.9333333333332483], [(4, 5), (2051, 2, 2, 6.536487691104412), 2.6666666666662415], [(4, 0), (2053, 10, 3, 6.730653751641512), 0.799999999999745], [(4, 1), (2054, 7, 22, 11.588903568685055), 1.3333333333337583], [(4, 2), (2055, 11, 21, 11.68598660454154), 0.9333333333332483], [(4, 7), (2056, 10, 27, 9.353944726288319), 2.40000000000051]]) diff --git a/references/oracle/dasha_shadbala_oracle_cases.json b/references/oracle/dasha_shadbala_oracle_cases.json index ed313568..090eca98 100644 --- a/references/oracle/dasha_shadbala_oracle_cases.json +++ b/references/oracle/dasha_shadbala_oracle_cases.json @@ -36,7 +36,7 @@ }, { "id": "template_steve_jobs_dasha_lahiri", - "status": "template_only", + "status": "external_verified", "source": "JHora/PyJHora/Manual screenshot", "privacy": "public_figure_template", "birth": { @@ -55,10 +55,24 @@ "node_mode": "true" }, "target": { - "vimshottari_start_date": null, + "vimshottari_start_date": "1939-03-22", "shadbala_components": null }, - "verification_note": "Verify Dasha boundaries from an external oracle before promotion to external_verified." + "verification_note": "Verify Dasha boundaries from an external oracle before promotion to external_verified.", + "evidence_packet": { + "capture_id": "external_template_steve_jobs_dasha_lahiri", + "status": "external_verified", + "metadata": { + "tool_name": "PyJHora", + "tool_version_or_url": "PyJHora 4.8.7 isolated /tmp black-box run", + "capture_date": "2026-06-27", + "source_artifact": "references/oracle/artifacts/pyjhora_steve_jobs_dasha_stdout_20260627.txt", + "ayanamsa": "lahiri", + "node_mode": "PyJHora default", + "timezone": "UTC-08:00", + "operator_note": "Black-box stdout from isolated /tmp virtualenv. PyJHora AGPL code was not copied into this repository; only the generated output artifact is stored as external evidence." + } + } }, { "id": "template_redacted_place_shadbala_raman", @@ -125,7 +139,7 @@ "minute": 0, "second": 0, "lat": 28.6139, - "lon": 77.2090, + "lon": 77.209, "tz": 5.5 }, "settings": { diff --git a/scripts/dasha_oracle_closure_status.py b/scripts/dasha_oracle_closure_status.py index 1a5d945b..ecc21816 100644 --- a/scripts/dasha_oracle_closure_status.py +++ b/scripts/dasha_oracle_closure_status.py @@ -56,6 +56,11 @@ def _target_missing(packet: dict[str, Any], fields: list[str]) -> list[str]: return missing +def _dasha_target_filled(task: dict[str, Any], fields: list[str]) -> bool: + packet = task.get("evidence_packet", {}) + return task.get("status") == "external_verified" and not _target_missing(packet, fields) + + def _group_missing_fields(missing_fields: list[str]) -> dict[str, Any]: metadata_fields = [field for field in missing_fields if field.startswith("metadata.")] target_fields = [field for field in missing_fields if field.startswith("target.")] @@ -122,9 +127,15 @@ def build_status(oracle_file: str) -> dict[str, Any]: task for task in queue.get("tasks", []) if DASHA_TARGET_FIELD in task.get("target_fields", []) ] - priority = next((task for task in dasha_tasks if task.get("case_id") == FIRST_PRIORITY_CASE_ID), None) - if priority is None and dasha_tasks: - priority = dasha_tasks[0] + required_target_fields = [DASHA_TARGET_FIELD] + unverified_dasha_tasks = [ + task for task in dasha_tasks + if not _dasha_target_filled(task, required_target_fields) + ] + priority_pool = unverified_dasha_tasks or dasha_tasks + priority = next((task for task in priority_pool if task.get("case_id") == FIRST_PRIORITY_CASE_ID), None) + if priority is None and priority_pool: + priority = priority_pool[0] if priority is None: raise RuntimeError("No Dasha target task found") @@ -133,12 +144,11 @@ def build_status(oracle_file: str) -> dict[str, Any]: packet_path = f"references/oracle/artifacts/pending_packets/{capture_id}.json" template_path = FIRST_PRIORITY_TEMPLATE_PATH if priority["case_id"] == FIRST_PRIORITY_CASE_ID else packet_path packet = json.loads((ROOT / template_path).read_text(encoding="utf-8")) - required_target_fields = [DASHA_TARGET_FIELD] missing_fields = _metadata_missing(packet) + _target_missing(packet, required_target_fields) missing_groups = _group_missing_fields(missing_fields) external_verified = [ task for task in dasha_tasks - if task.get("status") == "external_verified" and not _target_missing(task.get("evidence_packet", {}), required_target_fields) + if _dasha_target_filled(task, required_target_fields) ] return { diff --git a/scripts/dasha_oracle_evidence_validator.py b/scripts/dasha_oracle_evidence_validator.py new file mode 100644 index 00000000..201424ee --- /dev/null +++ b/scripts/dasha_oracle_evidence_validator.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 +"""Validate Dasha-only external oracle evidence packets. + +The generic oracle evidence validator is intentionally strict for combined +Dasha/Shadbala rows. This validator isolates the Dasha closure path so one +external Vimshottari boundary can be accepted without waiting for Shadbala +absolute-value components. +""" + +from __future__ import annotations + +import argparse +import json +import os +import re +from typing import Any + + +ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +DASHA_TARGET_FIELD = "target.vimshottari_start_date" +LOCAL_ENGINE_MARKERS = [ + "local engine", + "this-repo", + "jyotish_engine.py", + "scripts/jyotish", + "oracle_collection_queue.py", + "oracle_boundary_audit.py", +] + + +def _resolve_path(path: str) -> str: + if os.path.isabs(path): + return path + return os.path.join(ROOT_DIR, path) + + +def _load_json(path: str) -> dict[str, Any]: + with open(_resolve_path(path), "r", encoding="utf-8") as fh: + return json.load(fh) + + +def _is_blank(value: Any) -> bool: + return value is None or value == "" or value == [] or value == {} + + +def _is_missing_external_artifact(value: Any) -> bool: + if _is_blank(value): + return True + text = str(value).strip() + return text.endswith("/") or text in {"references/oracle/artifacts", "references/oracle/artifacts/"} + + +def _artifact_exists(value: Any) -> bool: + if _is_missing_external_artifact(value): + return False + return os.path.exists(_resolve_path(str(value))) + + +def _is_local_engine_artifact(packet: dict[str, Any]) -> bool: + metadata = packet.get("metadata", {}) + haystack = " ".join( + str(metadata.get(field, "")) + for field in ["tool_name", "tool_version_or_url", "source_artifact", "operator_note"] + ).lower() + return any(marker in haystack for marker in LOCAL_ENGINE_MARKERS) + + +def _valid_iso_date(value: Any) -> bool: + return isinstance(value, str) and re.fullmatch(r"\d{4}-\d{2}-\d{2}", value) is not None + + +def _validate_dasha_packet(task: dict[str, Any]) -> dict[str, Any]: + packet = task.get("evidence_packet", {}) + metadata = packet.get("metadata", {}) + placeholders = packet.get("target_placeholders", {}) + problems: list[str] = [] + + for field in packet.get("required_metadata_fields", []): + if _is_blank(metadata.get(field)): + problems.append(f"missing_metadata:{field}") + + source_artifact = metadata.get("source_artifact") + if _is_missing_external_artifact(source_artifact): + problems.append("missing_external_artifact") + elif not _artifact_exists(source_artifact): + problems.append("external_artifact_not_found") + + if packet.get("status") != "external_verified": + problems.append(f"status_not_external_verified:{packet.get('status', 'missing')}") + + value = placeholders.get(DASHA_TARGET_FIELD) + if _is_blank(value): + problems.append(f"placeholder_unfilled:{DASHA_TARGET_FIELD}") + elif not _valid_iso_date(value): + problems.append(f"invalid_dasha_date:{DASHA_TARGET_FIELD}") + + integrity = packet.get("integrity_checks", {}) + if integrity.get("must_not_come_from_local_engine") and _is_local_engine_artifact(packet): + problems.append("local_engine_artifact_rejected") + + valid = not problems + return { + "task_id": task.get("task_id"), + "case_id": task.get("case_id"), + "capture_id": packet.get("capture_id") or f"missing_capture_id:{task.get('case_id', 'unknown')}", + "status": packet.get("status", "missing"), + "target_field": DASHA_TARGET_FIELD, + "valid": valid, + "ready_for_dasha_calibration": valid and packet.get("status") == "external_verified", + "problems": problems, + } + + +def build_report(queue: dict[str, Any]) -> dict[str, Any]: + packets = [ + _validate_dasha_packet(task) + for task in queue.get("tasks", []) + if DASHA_TARGET_FIELD in task.get("target_fields", []) + ] + valid_packets = sum(1 for packet in packets if packet["valid"]) + ready_for_dasha_calibration = sum(1 for packet in packets if packet["ready_for_dasha_calibration"]) + return { + "scope": "dasha_external_oracle_evidence_validation", + "schema_version": 1, + "summary": { + "total_dasha_packets": len(packets), + "valid_dasha_packets": valid_packets, + "ready_for_dasha_calibration": ready_for_dasha_calibration, + "all_dasha_packets_external_verified": bool(packets) and valid_packets == len(packets), + "production_tuning_allowed": bool(packets) and ready_for_dasha_calibration == len(packets), + }, + "packets": packets, + "boundary": ( + "This validator only accepts external Dasha boundary evidence. " + "It does not validate Shadbala absolute values and must not be used to claim full oracle closure." + ), + } + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Validate Dasha-only external oracle evidence packets") + parser.add_argument("--queue-file", required=True, help="Path to oracle collection queue JSON") + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(argv) + queue = _load_json(args.queue_file) + print(json.dumps(build_report(queue), ensure_ascii=False, indent=2)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/public_benchmark_dashboard.py b/scripts/public_benchmark_dashboard.py index 7cc207c8..876b69cb 100644 --- a/scripts/public_benchmark_dashboard.py +++ b/scripts/public_benchmark_dashboard.py @@ -49,6 +49,15 @@ def _oracle_readiness(oracle_file: str) -> dict[str, Any]: } +def _dasha_readiness(oracle_file: str) -> dict[str, Any]: + queue = _run_json([PYTHON, "scripts/oracle_collection_queue.py", "--oracle-file", oracle_file, "--format", "json"]) + with tempfile.NamedTemporaryFile("w+", suffix=".json", encoding="utf-8", delete=True) as fh: + json.dump(queue, fh, ensure_ascii=False) + fh.flush() + validation = _run_json([PYTHON, "scripts/dasha_oracle_evidence_validator.py", "--queue-file", fh.name]) + return validation["summary"] + + def _boundary_audit(oracle_file: str) -> dict[str, Any]: report = _run_json([PYTHON, "scripts/oracle_boundary_audit.py", "--oracle-file", oracle_file]) summary = report["summary"] @@ -68,10 +77,12 @@ def build_dashboard(oracle_file: str) -> dict[str, Any]: capability = _run_json([PYTHON, "scripts/audit_capabilities.py", "--mode", "validate"]) oracle = _oracle_readiness(oracle_file) boundary = _boundary_audit(oracle_file) + dasha = _dasha_readiness(oracle_file) global_first_gap = ( - "Dasha/Shadbala external oracle readiness remains 0, Shadbala absolute values still need " - "component-level external evidence, and public long-term benchmark history is not yet comparable " - "to the strongest global open-source projects." + f"Dasha-only external oracle readiness is {dasha['valid_dasha_packets']}/" + f"{dasha['total_dasha_packets']}; Shadbala absolute values still need component-level " + "external evidence, and public long-term benchmark history is not yet comparable to the strongest " + "global open-source projects." ) can_claim_global_first = bool( capability.get("valid") @@ -89,6 +100,7 @@ def build_dashboard(oracle_file: str) -> dict[str, Any]: "status_counts": capability["status_counts"], }, "oracle_readiness": oracle, + "dasha_oracle_readiness": dasha, "boundary_audit": boundary, "public_claim": { "can_claim_global_first": can_claim_global_first, @@ -99,7 +111,7 @@ def build_dashboard(oracle_file: str) -> dict[str, Any]: }, "global_first_gap": global_first_gap, "next_actions": [ - "Fill the first external JHora/PyJHora packet under references/oracle/artifacts/pending_packets.", + "Fill the next open external JHora/PyJHora packet under references/oracle/artifacts/pending_packets.", "Run oracle_evidence_validator.py until at least one packet is valid.", "Run oracle_boundary_audit.py to inspect Dasha/Shadbala deltas without tuning constants.", "Publish this dashboard after each validated sample batch.", @@ -109,6 +121,7 @@ def build_dashboard(oracle_file: str) -> dict[str, Any]: def render_markdown(report: dict[str, Any]) -> str: oracle = report["oracle_readiness"] + dasha = report["dasha_oracle_readiness"] boundary = report["boundary_audit"] claim = report["public_claim"] lines = [ @@ -128,6 +141,8 @@ def render_markdown(report: dict[str, Any]) -> str: f"- valid_packets: `{oracle['valid_packets']}`", f"- ready_for_calibration: `{oracle['ready_for_calibration']}`", f"- production_tuning_allowed: `{str(oracle['production_tuning_allowed']).lower()}`", + f"- valid_dasha_packets: `{dasha['valid_dasha_packets']}`", + f"- total_dasha_packets: `{dasha['total_dasha_packets']}`", "", "## Boundary Audit", "", diff --git a/tests/test_dasha_oracle_closure_status.py b/tests/test_dasha_oracle_closure_status.py index 4134b581..aa2e30dd 100644 --- a/tests/test_dasha_oracle_closure_status.py +++ b/tests/test_dasha_oracle_closure_status.py @@ -37,17 +37,17 @@ def test_dasha_oracle_closure_status_identifies_first_shortest_packet() -> None: assert report["scope"] == "dasha_external_oracle_closure_status" assert report["schema_version"] == 1 assert report["summary"]["dasha_task_count"] == 3 - assert report["summary"]["external_verified_dasha_tasks"] == 0 + assert report["summary"]["external_verified_dasha_tasks"] == 1 assert report["summary"]["can_claim_dasha_oracle_closure"] is False - assert report["first_priority"]["case_id"] == "template_steve_jobs_dasha_lahiri" - assert report["first_priority"]["capture_id"] == "external_template_steve_jobs_dasha_lahiri" + assert report["first_priority"]["case_id"] == "template_user_REDACTED_YEAR_moon_longitude_lahiri" + assert report["first_priority"]["capture_id"] == "external_template_user_REDACTED_YEAR_moon_longitude_lahiri" assert report["first_priority"]["required_target_fields"] == ["target.vimshottari_start_date"] assert "metadata.tool_name" in report["first_priority"]["missing_fields"] assert "target.vimshottari_start_date" in report["first_priority"]["missing_fields"] assert report["first_priority"]["missing_groups"]["metadata"]["count"] == 5 assert report["first_priority"]["missing_groups"]["target"]["count"] == 1 - assert report["first_priority"]["prefilled_fields"]["metadata"]["ayanamsa"] == "Lahiri" - assert report["first_priority"]["prefilled_fields"]["metadata"]["timezone"] == "UTC-08:00" + assert report["first_priority"]["prefilled_fields"]["metadata"]["ayanamsa"] == "lahiri" + assert report["first_priority"]["prefilled_fields"]["metadata"]["timezone"] == 8 assert report["first_priority"]["manual_fill_plan"]["status_value"] == "external_verified" assert report["first_priority"]["manual_fill_plan"]["manual_entry_count"] == 6 assert report["first_priority"]["apply_command"] @@ -63,8 +63,57 @@ def test_dasha_oracle_closure_status_markdown_can_be_written(tmp_path: Path) -> markdown = output.read_text(encoding="utf-8") assert "# Dasha External Oracle Closure Status" in markdown assert "can_claim_dasha_oracle_closure: `false`" in markdown - assert "external_template_steve_jobs_dasha_lahiri" in markdown + assert "external_template_user_REDACTED_YEAR_moon_longitude_lahiri" in markdown assert "target.vimshottari_start_date" in markdown assert "## Missing Summary" in markdown assert "## Prefilled Fields" in markdown assert "## Manual Fill Plan" in markdown + + +def test_dasha_oracle_closure_status_advances_after_first_packet_is_filled(tmp_path: Path) -> None: + oracle_file = tmp_path / "oracle_cases.json" + oracle_file.write_text( + (ROOT / "references/oracle/dasha_shadbala_oracle_cases.json").read_text(encoding="utf-8"), + encoding="utf-8", + ) + packet = ROOT / "references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri_pyjhora_20260627.json" + apply_completed = subprocess.run( + [ + sys.executable, + "scripts/oracle_collection_queue.py", + "--oracle-file", + str(oracle_file), + "--apply-packet", + str(packet), + "--format", + "json", + ], + cwd=ROOT, + text=True, + capture_output=True, + timeout=60, + check=False, + ) + assert apply_completed.returncode == 0, apply_completed.stderr or apply_completed.stdout + + completed = subprocess.run( + [ + sys.executable, + "scripts/dasha_oracle_closure_status.py", + "--oracle-file", + str(oracle_file), + "--format", + "json", + ], + cwd=ROOT, + text=True, + capture_output=True, + timeout=60, + check=False, + ) + + assert completed.returncode == 0, completed.stderr or completed.stdout + report = json.loads(completed.stdout) + assert report["summary"]["external_verified_dasha_tasks"] == 1 + assert report["first_priority"]["case_id"] != "template_steve_jobs_dasha_lahiri" + assert report["first_priority"]["missing_fields"] diff --git a/tests/test_dasha_oracle_evidence_validator.py b/tests/test_dasha_oracle_evidence_validator.py new file mode 100644 index 00000000..541adc85 --- /dev/null +++ b/tests/test_dasha_oracle_evidence_validator.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +"""Tests for Dasha-only external oracle evidence validation.""" + +from __future__ import annotations + +import json +import subprocess +import sys +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +PYJHORA_PACKET = ROOT / "references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri_pyjhora_20260627.json" + + +def _run_validator(queue_file: Path) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [ + sys.executable, + "scripts/dasha_oracle_evidence_validator.py", + "--queue-file", + str(queue_file), + ], + cwd=ROOT, + text=True, + capture_output=True, + timeout=60, + check=False, + ) + + +def _queue_from_packet(tmp_path: Path, packet: dict) -> Path: + queue = { + "tasks": [ + { + "task_id": "collect_template_steve_jobs_dasha_lahiri", + "case_id": "template_steve_jobs_dasha_lahiri", + "status": packet.get("status", "draft"), + "target_fields": ["target.vimshottari_start_date", "target.shadbala_components"], + "evidence_packet": packet, + } + ] + } + queue_file = tmp_path / "queue.json" + queue_file.write_text(json.dumps(queue, ensure_ascii=False, indent=2), encoding="utf-8") + return queue_file + + +def test_dasha_validator_accepts_dasha_only_external_pyjhora_packet(tmp_path: Path) -> None: + packet = json.loads(PYJHORA_PACKET.read_text(encoding="utf-8")) + queue_file = _queue_from_packet(tmp_path, packet) + + completed = _run_validator(queue_file) + + assert completed.returncode == 0, completed.stderr or completed.stdout + report = json.loads(completed.stdout) + assert report["scope"] == "dasha_external_oracle_evidence_validation" + assert report["summary"]["total_dasha_packets"] == 1 + assert report["summary"]["valid_dasha_packets"] == 1 + assert report["summary"]["ready_for_dasha_calibration"] == 1 + assert report["summary"]["all_dasha_packets_external_verified"] is True + assert report["packets"][0]["valid"] is True + assert report["packets"][0]["problems"] == [] + + +def test_dasha_validator_rejects_local_engine_dasha_artifact(tmp_path: Path) -> None: + packet = json.loads(PYJHORA_PACKET.read_text(encoding="utf-8")) + packet["metadata"]["tool_name"] = "local engine" + packet["metadata"]["operator_note"] = "Generated from scripts/jyotish_engine.py" + queue_file = _queue_from_packet(tmp_path, packet) + + completed = _run_validator(queue_file) + + assert completed.returncode == 0, completed.stderr or completed.stdout + report = json.loads(completed.stdout) + assert report["summary"]["valid_dasha_packets"] == 0 + assert report["summary"]["ready_for_dasha_calibration"] == 0 + assert report["packets"][0]["valid"] is False + assert "local_engine_artifact_rejected" in report["packets"][0]["problems"] + + +def test_dasha_validator_rejects_missing_dasha_date(tmp_path: Path) -> None: + packet = json.loads(PYJHORA_PACKET.read_text(encoding="utf-8")) + packet["target_placeholders"]["target.vimshottari_start_date"] = "" + queue_file = _queue_from_packet(tmp_path, packet) + + completed = _run_validator(queue_file) + + assert completed.returncode == 0, completed.stderr or completed.stdout + report = json.loads(completed.stdout) + assert report["summary"]["valid_dasha_packets"] == 0 + assert "placeholder_unfilled:target.vimshottari_start_date" in report["packets"][0]["problems"] diff --git a/tests/test_oracle_closure_master_dashboard.py b/tests/test_oracle_closure_master_dashboard.py index 93f6181d..7ce2803c 100644 --- a/tests/test_oracle_closure_master_dashboard.py +++ b/tests/test_oracle_closure_master_dashboard.py @@ -39,13 +39,14 @@ def test_oracle_closure_master_dashboard_aggregates_all_hard_fronts() -> None: 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"]["external_verified_tasks"] == 1 + assert report["summary"]["open_tasks"] == 11 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"]["dasha"]["external_verified_tasks"] == 1 + assert report["fronts"]["dasha"]["first_priority"]["case_id"] == "template_user_REDACTED_YEAR_moon_longitude_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["fronts"]["dasha"]["first_priority"]["missing_groups"]["metadata"]["count"] == 5 @@ -69,7 +70,7 @@ def test_oracle_closure_master_dashboard_markdown_can_be_written(tmp_path: Path) 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_user_REDACTED_YEAR_moon_longitude_lahiri" in markdown assert "template_redacted_place_shadbala_raman" in markdown assert "template_steve_jobs_varshaphala_1984_lahiri" in markdown assert "manual entries" in markdown diff --git a/tests/test_public_benchmark_dashboard.py b/tests/test_public_benchmark_dashboard.py index 761d7b6a..340f3598 100644 --- a/tests/test_public_benchmark_dashboard.py +++ b/tests/test_public_benchmark_dashboard.py @@ -42,8 +42,10 @@ def test_public_benchmark_dashboard_outputs_stable_json_summary() -> None: assert report["oracle_readiness"]["valid_packets"] == 0 assert report["oracle_readiness"]["ready_for_calibration"] == 0 assert report["oracle_readiness"]["production_tuning_allowed"] is False + assert report["dasha_oracle_readiness"]["valid_dasha_packets"] == 1 + assert report["dasha_oracle_readiness"]["total_dasha_packets"] == 3 assert report["boundary_audit"]["production_tuning_recommended"] is False - assert "Dasha/Shadbala" in report["global_first_gap"] + assert "Dasha-only external oracle readiness is 1/3" in report["global_first_gap"] assert report["public_claim"]["can_claim_global_first"] is False assert report["public_claim"]["reason"]