diff --git a/README.md b/README.md index 721cce75..399feb7f 100644 --- a/README.md +++ b/README.md @@ -147,12 +147,13 @@ python3 scripts/oracle_collection_queue.py \ 如需让真人或 Antigravity AI 副手直接填写证据包,可一次性导出每个 case 的 draft JSON: ```bash -python3 scripts/oracle_collection_queue.py \ +python3 scripts/prepare_oracle_capture_packets.py \ --oracle-file references/oracle/dasha_shadbala_oracle_cases.json \ - --write-packet-dir references/oracle/artifacts/pending_packets \ - --format json + --output-dir references/oracle/artifacts/pending_packets ``` +该命令会生成 `capture_manifest.json`、`OPERATOR_NEXT_STEPS.md` 和 5 个 `external_*.json`,并在输出中确认 draft 队列仍是 `valid_packets: 0` / `ready_for_calibration: 0`。 + 填完某个 `external_*.json` 后,必须把 `status` 改为 `external_verified`,补齐 metadata、具体 `source_artifact` 文件路径以及所有 `target_placeholders`。再把该包合并回 oracle 文件: ```bash diff --git a/references/oracle/artifacts/pending_packets/OPERATOR_NEXT_STEPS.md b/references/oracle/artifacts/pending_packets/OPERATOR_NEXT_STEPS.md new file mode 100644 index 00000000..7bec2c45 --- /dev/null +++ b/references/oracle/artifacts/pending_packets/OPERATOR_NEXT_STEPS.md @@ -0,0 +1,37 @@ +# External Oracle Capture Next Steps + +First priority packet: + +`external_template_steve_jobs_dasha_lahiri.json` + +## Fill The Packet + +1. Open JHora, PyJHora, VedAstro, or another documented external source. +2. Use the exact birth data, ayanamsa, node mode, timezone, and settings in the packet. +3. Save a redacted screenshot or stdout snippet under `references/oracle/artifacts/`. +4. Fill all metadata fields and all `target_placeholders`. +5. Set `status` to `external_verified` only after the artifact and target values are filled. + +不得把本仓库本地输出当作 external oracle。 + +## Apply The Packet + +```bash +python3 scripts/oracle_collection_queue.py \ + --oracle-file references/oracle/dasha_shadbala_oracle_cases.json \ + --apply-packet /Users/wuyongnaren/Documents/印度占星/references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json \ + --format json +``` + +## Validate Again + +```bash +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 +``` + +Draft packets in `references/oracle/artifacts/pending_packets` must remain `valid_packets: 0` until real external evidence is filled. diff --git a/references/oracle/artifacts/pending_packets/capture_manifest.json b/references/oracle/artifacts/pending_packets/capture_manifest.json new file mode 100644 index 00000000..07ad2538 --- /dev/null +++ b/references/oracle/artifacts/pending_packets/capture_manifest.json @@ -0,0 +1,20 @@ +{ + "scope": "external_oracle_capture_packet_manifest", + "oracle_file": "references/oracle/dasha_shadbala_oracle_cases.json", + "packet_count": 5, + "packets": [ + "external_template_extreme_latitude_kp.json", + "external_template_redacted_place_shadbala_raman.json", + "external_template_historical_epoch_lahiri.json", + "external_template_steve_jobs_dasha_lahiri.json", + "external_template_user_REDACTED_YEAR_moon_longitude_lahiri.json" + ], + "first_priority_packet": "/Users/wuyongnaren/Documents/印度占星/references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json", + "validator_summary": { + "total_packets": 5, + "valid_packets": 0, + "ready_for_calibration": 0, + "all_packets_external_verified": false, + "production_tuning_allowed": false + } +} diff --git a/references/oracle/artifacts/pending_packets/external_template_extreme_latitude_kp.json b/references/oracle/artifacts/pending_packets/external_template_extreme_latitude_kp.json new file mode 100644 index 00000000..0e31495e --- /dev/null +++ b/references/oracle/artifacts/pending_packets/external_template_extreme_latitude_kp.json @@ -0,0 +1,115 @@ +{ + "capture_id": "external_template_extreme_latitude_kp", + "status": "draft", + "case_id": "template_extreme_latitude_kp", + "birth": { + "year": 2000, + "month": 6, + "day": 21, + "hour": 0, + "minute": 0, + "second": 0, + "lat": 65.0, + "lon": 15.0, + "tz": 1 + }, + "settings": { + "ayanamsa": "kp", + "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": "", + "tool_version_or_url": "", + "capture_date": "", + "source_artifact": "references/oracle/artifacts/", + "ayanamsa": "kp", + "node_mode": "true", + "timezone": 1, + "operator_note": "" + }, + "target_placeholders": { + "target.ascendant_longitude_deg": null, + "target.shadbala_components": { + "Sun": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Moon": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Mars": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Mercury": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Jupiter": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Venus": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Saturn": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + } + } + }, + "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" +} diff --git a/references/oracle/artifacts/pending_packets/external_template_historical_epoch_lahiri.json b/references/oracle/artifacts/pending_packets/external_template_historical_epoch_lahiri.json new file mode 100644 index 00000000..67d4444e --- /dev/null +++ b/references/oracle/artifacts/pending_packets/external_template_historical_epoch_lahiri.json @@ -0,0 +1,51 @@ +{ + "capture_id": "external_template_historical_epoch_lahiri", + "status": "draft", + "case_id": "template_historical_epoch_lahiri", + "birth": { + "year": 1800, + "month": 1, + "day": 1, + "hour": 12, + "minute": 0, + "second": 0, + "lat": 28.6139, + "lon": 77.209, + "tz": 5.5 + }, + "settings": { + "ayanamsa": "lahiri", + "node_mode": "mean" + }, + "required_metadata_fields": [ + "tool_name", + "tool_version_or_url", + "capture_date", + "source_artifact", + "ayanamsa", + "node_mode", + "timezone", + "operator_note" + ], + "metadata": { + "tool_name": "", + "tool_version_or_url": "", + "capture_date": "", + "source_artifact": "references/oracle/artifacts/", + "ayanamsa": "lahiri", + "node_mode": "mean", + "timezone": 5.5, + "operator_note": "" + }, + "target_placeholders": { + "target.sun_sidereal_longitude_deg": null, + "target.vimshottari_start_date": null + }, + "integrity_checks": { + "must_not_come_from_local_engine": true, + "requires_external_artifact": true, + "requires_status_external_verified_before_calibration": true, + "reject_global_shadbala_scaling": false + }, + "promotion_status_after_fill": "external_verified" +} diff --git a/references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json b/references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json new file mode 100644 index 00000000..82893e02 --- /dev/null +++ b/references/oracle/artifacts/pending_packets/external_template_steve_jobs_dasha_lahiri.json @@ -0,0 +1,115 @@ +{ + "capture_id": "external_template_steve_jobs_dasha_lahiri", + "status": "draft", + "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": "", + "tool_version_or_url": "", + "capture_date": "", + "source_artifact": "references/oracle/artifacts/", + "ayanamsa": "lahiri", + "node_mode": "true", + "timezone": -8, + "operator_note": "" + }, + "target_placeholders": { + "target.vimshottari_start_date": null, + "target.shadbala_components": { + "Sun": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Moon": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Mars": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Mercury": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Jupiter": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Venus": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + }, + "Saturn": { + "sthana": null, + "dig": null, + "kala": null, + "chesta": null, + "naisargika": null, + "drik": null, + "total_rupa": null + } + } + }, + "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" +} diff --git a/scripts/oracle_collection_queue.py b/scripts/oracle_collection_queue.py index 866fe986..411f5deb 100644 --- a/scripts/oracle_collection_queue.py +++ b/scripts/oracle_collection_queue.py @@ -103,6 +103,8 @@ REQUIRED_EVIDENCE_METADATA_FIELDS = [ "timezone", "operator_note", ] +SHADBALA_DRAFT_PLANETS = ["Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn"] +SHADBALA_DRAFT_COMPONENTS = ["sthana", "dig", "kala", "chesta", "naisargika", "drik", "total_rupa"] def _resolve_path(path: str) -> str: @@ -182,6 +184,13 @@ def _evidence_packet(case: dict[str, Any], target_fields: list[str]) -> dict[str field: _target_value(target, field) for field in target_fields } + if "target.shadbala_components" in target_placeholders and _is_blank_target( + target_placeholders["target.shadbala_components"] + ): + target_placeholders["target.shadbala_components"] = { + planet: {component: None for component in SHADBALA_DRAFT_COMPONENTS} + for planet in SHADBALA_DRAFT_PLANETS + } existing_placeholders = existing.get("target_placeholders", {}) if isinstance(existing_placeholders, dict): target_placeholders.update(existing_placeholders) @@ -217,6 +226,10 @@ def _evidence_packet(case: dict[str, Any], target_fields: list[str]) -> dict[str } +def _is_blank_target(value: Any) -> bool: + return value is None or value == "" or value == [] or value == {} + + def _task_from_template(case: dict[str, Any]) -> dict[str, Any]: case_id = case.get("id") or case.get("case_id") target = case.get("target", {}) diff --git a/scripts/prepare_oracle_capture_packets.py b/scripts/prepare_oracle_capture_packets.py new file mode 100644 index 00000000..57a66b78 --- /dev/null +++ b/scripts/prepare_oracle_capture_packets.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +"""Prepare fillable external-oracle evidence packets and operator notes.""" + +from __future__ import annotations + +import argparse +import json +import os +import sys +from pathlib import Path +from typing import Any + + +ROOT_DIR = Path(__file__).resolve().parents[1] +if str(ROOT_DIR / "scripts") not in sys.path: + sys.path.insert(0, str(ROOT_DIR / "scripts")) + +from oracle_collection_queue import build_queue, write_evidence_packets # noqa: E402 +from oracle_evidence_validator import build_report # noqa: E402 + + +FIRST_PRIORITY_CAPTURE_ID = "external_template_steve_jobs_dasha_lahiri" + + +def _resolve(path: str) -> Path: + candidate = Path(path) + if candidate.is_absolute(): + return candidate + return ROOT_DIR / candidate + + +def _load_json(path: str) -> dict[str, Any]: + with _resolve(path).open("r", encoding="utf-8") as fh: + return json.load(fh) + + +def _write_json(path: Path, value: dict[str, Any]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + with path.open("w", encoding="utf-8") as fh: + json.dump(value, fh, ensure_ascii=False, indent=2) + fh.write("\n") + + +def _write_next_steps(path: Path, oracle_file: str, output_dir: str, first_packet: str) -> None: + text = f"""# External Oracle Capture Next Steps + +First priority packet: + +`{os.path.basename(first_packet)}` + +## Fill The Packet + +1. Open JHora, PyJHora, VedAstro, or another documented external source. +2. Use the exact birth data, ayanamsa, node mode, timezone, and settings in the packet. +3. Save a redacted screenshot or stdout snippet under `references/oracle/artifacts/`. +4. Fill all metadata fields and all `target_placeholders`. +5. Set `status` to `external_verified` only after the artifact and target values are filled. + +不得把本仓库本地输出当作 external oracle。 + +## Apply The Packet + +```bash +python3 scripts/oracle_collection_queue.py \\ + --oracle-file {oracle_file} \\ + --apply-packet {first_packet} \\ + --format json +``` + +## Validate Again + +```bash +python3 scripts/oracle_collection_queue.py \\ + --oracle-file {oracle_file} \\ + --format json > /tmp/jyotish_oracle_queue_filled.json + +python3 scripts/oracle_evidence_validator.py \\ + --queue-file /tmp/jyotish_oracle_queue_filled.json +``` + +Draft packets in `{output_dir}` must remain `valid_packets: 0` until real external evidence is filled. +""" + path.write_text(text, encoding="utf-8") + + +def prepare_packets(oracle_file: str, output_dir: str) -> dict[str, Any]: + output_path = _resolve(output_dir) + output_path.mkdir(parents=True, exist_ok=True) + oracle = _load_json(oracle_file) + queue = build_queue(oracle) + packet_count = write_evidence_packets(queue, str(output_path)) + validator_report = build_report(queue) + + packets = sorted(path.name for path in output_path.glob("external_*.json")) + first_priority = output_path / f"{FIRST_PRIORITY_CAPTURE_ID}.json" + first_priority_path = first_priority if first_priority.exists() else output_path / packets[0] + + manifest = { + "scope": "external_oracle_capture_packet_manifest", + "oracle_file": oracle_file, + "packet_count": packet_count, + "packets": packets, + "first_priority_packet": str(first_priority_path), + "validator_summary": validator_report["summary"], + } + _write_json(output_path / "capture_manifest.json", manifest) + _write_next_steps(output_path / "OPERATOR_NEXT_STEPS.md", oracle_file, output_dir, str(first_priority_path)) + + return { + "scope": "external_oracle_capture_packet_preparation", + "oracle_file": oracle_file, + "output_dir": str(output_path), + "packet_count": packet_count, + "first_priority_packet": str(first_priority_path), + "validator_summary": validator_report["summary"], + "manifest": str(output_path / "capture_manifest.json"), + "operator_next_steps": str(output_path / "OPERATOR_NEXT_STEPS.md"), + } + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Prepare external oracle capture packets") + parser.add_argument("--oracle-file", required=True) + parser.add_argument("--output-dir", required=True) + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(argv) + print(json.dumps(prepare_packets(args.oracle_file, args.output_dir), ensure_ascii=False, indent=2)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/test_oracle_collection_queue.py b/tests/test_oracle_collection_queue.py index 6c41dea8..04492c44 100644 --- a/tests/test_oracle_collection_queue.py +++ b/tests/test_oracle_collection_queue.py @@ -118,6 +118,9 @@ def test_oracle_collection_queue_can_write_draft_evidence_packets(tmp_path: Path assert packet["metadata"]["source_artifact"] == "references/oracle/artifacts/" assert packet["metadata"]["tool_name"] == "" assert packet["target_placeholders"]["target.vimshottari_start_date"] is None + shadbala = packet["target_placeholders"]["target.shadbala_components"] + assert set(shadbala) == {"Sun", "Moon", "Mars", "Mercury", "Jupiter", "Venus", "Saturn"} + assert set(shadbala["Sun"]) == {"sthana", "dig", "kala", "chesta", "naisargika", "drik", "total_rupa"} assert packet["integrity_checks"]["must_not_come_from_local_engine"] is True diff --git a/tests/test_prepare_oracle_capture_packets.py b/tests/test_prepare_oracle_capture_packets.py new file mode 100644 index 00000000..80e315a3 --- /dev/null +++ b/tests/test_prepare_oracle_capture_packets.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +"""Tests for preparing first external oracle capture packets.""" + +from __future__ import annotations + +import json +import subprocess +import sys +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] + + +def test_prepare_oracle_capture_packets_writes_packets_manifest_and_next_steps(tmp_path: Path) -> None: + completed = subprocess.run( + [ + sys.executable, + "scripts/prepare_oracle_capture_packets.py", + "--oracle-file", + "references/oracle/dasha_shadbala_oracle_cases.json", + "--output-dir", + str(tmp_path), + ], + cwd=ROOT, + text=True, + capture_output=True, + timeout=30, + check=False, + ) + + assert completed.returncode == 0, completed.stderr or completed.stdout + report = json.loads(completed.stdout) + assert report["scope"] == "external_oracle_capture_packet_preparation" + assert report["packet_count"] == 5 + assert report["validator_summary"]["valid_packets"] == 0 + assert report["validator_summary"]["ready_for_calibration"] == 0 + assert report["first_priority_packet"].endswith("external_template_steve_jobs_dasha_lahiri.json") + + packet = tmp_path / "external_template_steve_jobs_dasha_lahiri.json" + manifest = tmp_path / "capture_manifest.json" + next_steps = tmp_path / "OPERATOR_NEXT_STEPS.md" + assert packet.exists() + assert manifest.exists() + assert next_steps.exists() + + packet_data = json.loads(packet.read_text(encoding="utf-8")) + assert packet_data["status"] == "draft" + assert packet_data["metadata"]["source_artifact"] == "references/oracle/artifacts/" + assert packet_data["target_placeholders"]["target.vimshottari_start_date"] is None + + manifest_data = json.loads(manifest.read_text(encoding="utf-8")) + assert manifest_data["scope"] == "external_oracle_capture_packet_manifest" + assert manifest_data["packet_count"] == 5 + assert packet.name in manifest_data["packets"] + + guide = next_steps.read_text(encoding="utf-8") + assert "external_template_steve_jobs_dasha_lahiri.json" in guide + assert "oracle_evidence_validator.py" in guide + assert "--apply-packet" in guide + assert "不得把本仓库本地输出当作 external oracle" in guide