Promote yoga benchmark and refresh oracle packet priority

This commit is contained in:
732642856
2026-06-28 17:51:34 +08:00
parent 7ba46213a6
commit 2582ccd6c0
10 changed files with 153 additions and 32 deletions
+10 -6
View File
@@ -4,9 +4,9 @@
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue)](https://www.python.org/)
[![Techniques](https://img.shields.io/badge/techniques-79-blueviolet)](references/technique_registry.json)
[![Covered](https://img.shields.io/badge/covered-70-green)](references/technique_registry.json)
[![Complete](https://img.shields.io/badge/complete-9-brightgreen)](references/technique_registry.json)
[![Techniques](https://img.shields.io/badge/techniques-89-blueviolet)](references/technique_registry.json)
[![Covered](https://img.shields.io/badge/covered-79-green)](references/technique_registry.json)
[![Complete](https://img.shields.io/badge/complete-10-brightgreen)](references/technique_registry.json)
[![Partial](https://img.shields.io/badge/partial-0-lightgrey)](references/technique_registry.json)
---
@@ -31,7 +31,7 @@
This is a **Vedic (Jyotish) astrology analysis system** designed for deep, auditable full-chart readings. It is NOT a simple ephemeris calculator — it is a multi-stage interpretive pipeline that:
1. **Computes** divisional charts (D1/D9/D10/...) via Swiss Ephemeris
2. **Runs** 79 registered techniques (Dashas, Yogas, Shadbala, Ashtakavarga, Transits...)
2. **Runs** 89 registered techniques (Dashas, Yogas, Shadbala, Ashtakavarga, Transits...)
3. **Routes** the analysis through strict workflow paths depending on question type (career / relationship / wealth / timing)
4. **Audits** every technique used — declaring what was called, what is complete/covered, and which limitations affect confidence
5. **Degrades gracefully** — limitations are labeled, not silently over-promising
@@ -45,7 +45,7 @@ This is a **Vedic (Jyotish) astrology analysis system** designed for deep, audit
| Technique Audit Table (confidence labeling) | ✅ | ❌ | ❌ | ❌ |
| Capability degradation (limits are explicit) | ✅ | ❌ | ❌ | ❌ |
| MEVG external verification gates | ✅ | ❌ | ❌ | ❌ |
| 79 techniques registered | ✅ | ✅ (50+) | ✅ (200+) | ✅ |
| 89 techniques registered | ✅ | ✅ (50+) | ✅ (200+) | ✅ |
| Traditional algorithm benchmarked | ✅ mixed depth | ✅ | ✅ | ✅ |
| Docker / MCP Server | ✅ | ❌ | ✅ | ❌ |
| English docs / PyPI package | ✅ in progress | ✅ | ✅ | ✅ |
@@ -442,7 +442,11 @@ The AI does NOT require the user to name techniques (e.g., "Chara Dasha"). It au
## Technique Coverage
Current count: **68 techniques** (58 covered, 10 complete, 0 partial, 0 missing)
Current registry count: **89 techniques** (79 covered, 10 complete, 0 partial, 0 missing).
The table below lists representative high-value entries. Treat
`references/technique_registry.json` as the source of truth for the full
machine-readable registry.
| Technique | Status | Notes |
|-----------|--------|-------|
+1
View File
@@ -7,6 +7,7 @@ This file is the small index for the current engineering fronts that still drive
- Before touching strict workflow or adjudicator logic, check:
- `/Users/wuyongnaren/Documents/印度占星/docs/research/high_value_fragment_source_map_2026_06_28.md`
- `/Users/wuyongnaren/Documents/印度占星/docs/research/worktree_fragment_triage_2026_06_28.md`
- `/Users/wuyongnaren/Documents/印度占星/docs/research/yoga_benchmark_case_promotion_audit_2026_06_28.md`
- Treat repo truth as authoritative.
- Treat `docs/research/local_drafts`, Gemini brain notes, Codex attachments, and WorkBuddy copies as candidate sources only.
@@ -56,8 +56,8 @@ Only promote this report later if a stable human-facing archive is needed.
- Disposition: useful boundary values were promoted into `/Users/wuyongnaren/Documents/印度占星/references/oracle/dasha_shadbala_oracle_cases.json` as `template_bv_raman_vimshottari_boundary_series`.
- Follow-up: collect source artifact metadata before promoting beyond `template_only`.
- `/Users/wuyongnaren/Documents/印度占星/tests/test_yoga_benchmark_cases.py`
- Current state: smoke-style test ending in `assert True`.
- Better path: replace with concrete yoga names and expected detections before promotion.
- Disposition: promoted into a real benchmark with concrete `rule_id` expectations and metadata contract checks.
- See `/Users/wuyongnaren/Documents/印度占星/docs/research/yoga_benchmark_case_promotion_audit_2026_06_28.md`.
### Superseded or Needs Review
@@ -0,0 +1,40 @@
# Yoga Benchmark Case Promotion Audit - 2026-06-28
## Scope
This pass converts the untracked `tests/test_yoga_benchmark_cases.py` scratch smoke test into an executable Yoga benchmark.
## Problem With The Old Fragment
The old file only verified that `detect_yogas_from_json()` returned a list and ended with `assert True`. It did not constrain any specific Yoga rule, category, strength, or metadata.
## Promoted Test Contract
The promoted test uses the same B.V. Raman-style static Aquarius chart but now asserts stable rule ids:
- `dharma_karmadhipati`
- `chandra_yoga_exalted`
- `shakti_yoga_9_10_lord`
- `bvr_016_vesi_precise`
- `budha_shukra_yoga`
- `kalatra_yoga_venus_kendra`
- `raja_yoga_5_10_lord`
- `raja_yoga_4_10_lord`
It also verifies that the metadata contract remains useful:
- `category`
- `strength`
- `source`
- human-readable `combination`
## Boundary
- This is a deterministic engine benchmark, not a life prediction.
- It does not claim B.V. Raman biography validation.
- It guards the data-driven Yoga engine and rule metadata against silent drift.
## Regression Coverage
- `/Users/wuyongnaren/Documents/印度占星/tests/test_yoga_benchmark_cases.py`
- `/Users/wuyongnaren/Documents/印度占星/tests/test_yoga_rules_integrity.py`
+2 -2
View File
@@ -132,7 +132,7 @@
"id": "covered_is_not_complete",
"wrong_pattern": "Using covered and complete as if they meant the same thing.",
"corrected_truth": "Covered means there is a stable entry or usable layer; complete requires mature workflow, tests, boundary text and, where needed, external oracle closure.",
"source_ref": "docs/research/current_skill_core_gap_rerank_2026_06_26.md"
"source_ref": "docs/research/local_drafts/2026-06/current_skill_core_gap_rerank_2026_06_26.md"
},
{
"id": "single_factor_reading_risk",
@@ -150,7 +150,7 @@
"id": "jaimini_kp_tajika_not_absent",
"wrong_pattern": "Describing Chara Dasha, KP/Prashna or Tajika/Sahams as absent.",
"corrected_truth": "These fronts have usable structures; the hard work is tail-difference closure, traditional workflow deepening and external sample validation.",
"source_ref": "docs/research/three_fronts_skill_depth_audit_2026_06_26.md"
"source_ref": "docs/research/local_drafts/2026-06/three_fronts_skill_depth_audit_2026_06_26.md"
}
],
"must_not_overclaim": [
+24 -8
View File
@@ -19,9 +19,6 @@ from oracle_collection_queue import build_queue, write_evidence_packets # noqa:
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():
@@ -41,6 +38,26 @@ def _write_json(path: Path, value: dict[str, Any]) -> None:
fh.write("\n")
def _first_priority_packet(queue: dict[str, Any], validator_report: dict[str, Any], output_path: Path) -> Path:
by_capture_id = {
packet.get("capture_id"): packet
for task in queue.get("tasks", [])
if isinstance((packet := task.get("evidence_packet", {})), dict)
}
for packet_result in validator_report.get("packets", []):
if packet_result.get("valid") is True:
continue
capture_id = packet_result.get("capture_id")
if not capture_id or capture_id not in by_capture_id:
continue
return output_path / f"{capture_id}.json"
packets = sorted(path for path in output_path.glob("external_*.json"))
if not packets:
return output_path / "external_oracle_packet.json"
return packets[0]
def _write_next_steps(path: Path, oracle_file: str, output_dir: str, first_packet: str) -> None:
text = f"""# External Oracle Capture Next Steps
@@ -53,8 +70,8 @@ First priority 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.
4. Fill missing metadata fields and missing `target_placeholders`.
5. Set or keep `status` as `external_verified` only after the artifact and target values are filled.
不得把本仓库本地输出当作 external oracle。
@@ -78,7 +95,7 @@ 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.
Packets in `{output_dir}` must not become valid until real external evidence is filled.
"""
path.write_text(text, encoding="utf-8")
@@ -92,8 +109,7 @@ def prepare_packets(oracle_file: str, output_dir: str) -> dict[str, Any]:
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]
first_priority_path = _first_priority_packet(queue, validator_report, output_path)
manifest = {
"scope": "external_oracle_capture_packet_manifest",
@@ -48,12 +48,12 @@ def test_oracle_closure_master_dashboard_aggregates_all_hard_fronts() -> None:
assert report["fronts"]["dasha"]["external_verified_tasks"] == 3
assert report["fronts"]["dasha"]["first_priority"] is None
assert report["fronts"]["shadbala"]["external_verified_tasks"] == 4
assert report["fronts"]["shadbala"]["first_priority"]["case_id"] == "template_redacted_place_shadbala_raman"
assert report["fronts"]["shadbala"]["open_tasks"] == 0
assert report["fronts"]["shadbala"]["first_priority"] is None
assert report["fronts"]["tajika_sahams"]["external_verified_tasks"] == 1
assert report["fronts"]["tajika_sahams"]["open_tasks"] == 4
assert report["fronts"]["tajika_sahams"]["first_priority"]["case_id"] == "template_einstein_varshaphala_1905_lahiri"
assert report["fronts"]["tajika_sahams"]["first_priority"]["missing_groups"]["target"]["count"] == 10
assert report["fronts"]["shadbala"]["first_priority"]["manual_fill_plan"]["manual_entry_count"] == 55
assert report["next_action_order"][0]["front"] == "tajika_sahams"
assert len(report["next_action_order"]) == 1
@@ -69,7 +69,7 @@ def test_oracle_closure_master_dashboard_markdown_can_be_written(tmp_path: Path)
assert "total_tasks: `12`" in markdown
assert "can_claim_global_oracle_closure: `false`" in markdown
assert "`dasha` | 3 | 3 | `complete`" in markdown
assert "template_redacted_place_shadbala_raman" in markdown
assert "`shadbala` | 4 | 4 | `complete`" in markdown
assert "template_einstein_varshaphala_1905_lahiri" in markdown
assert "manual entries" in markdown
assert "metadata missing" in markdown
+10 -10
View File
@@ -32,12 +32,12 @@ def test_prepare_oracle_capture_packets_writes_packets_manifest_and_next_steps(t
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")
assert report["packet_count"] == 6
assert report["validator_summary"]["valid_packets"] == 4
assert report["validator_summary"]["ready_for_calibration"] == 4
assert report["first_priority_packet"].endswith("external_template_historical_epoch_lahiri.json")
packet = tmp_path / "external_template_steve_jobs_dasha_lahiri.json"
packet = tmp_path / "external_template_historical_epoch_lahiri.json"
manifest = tmp_path / "capture_manifest.json"
next_steps = tmp_path / "OPERATOR_NEXT_STEPS.md"
assert packet.exists()
@@ -45,17 +45,17 @@ def test_prepare_oracle_capture_packets_writes_packets_manifest_and_next_steps(t
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
assert packet_data["status"] == "external_verified"
assert packet_data["metadata"]["source_artifact"].startswith("references/oracle/artifacts/")
assert packet_data["target_placeholders"]["target.sun_sidereal_longitude_deg"] 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 manifest_data["packet_count"] == 6
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 "external_template_historical_epoch_lahiri.json" in guide
assert "oracle_evidence_validator.py" in guide
assert "--apply-packet" in guide
assert "不得把本仓库本地输出当作 external oracle" in guide
+1 -1
View File
@@ -38,7 +38,7 @@ def test_public_benchmark_dashboard_outputs_stable_json_summary() -> None:
assert report["schema_version"] == 1
assert report["summary"]["technique_count"] >= 60
assert report["summary"]["capability_valid"] is True
assert report["oracle_readiness"]["total_packets"] == 5
assert report["oracle_readiness"]["total_packets"] == 6
assert report["oracle_readiness"]["valid_packets"] == 4
assert report["oracle_readiness"]["ready_for_calibration"] == 4
assert report["oracle_readiness"]["production_tuning_allowed"] is False
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""Executable Yoga benchmark cases recovered from older scratch tests."""
from __future__ import annotations
from scripts.yoga_engine import detect_yogas_from_json
RAMAN_STATIC_CHART = {
"ascendant": "Aquarius",
"planets": {
"Sun": {"sign": "Cancer", "house": 6, "degree": 23.0},
"Moon": {"sign": "Taurus", "house": 4, "degree": 23.5},
"Mars": {"sign": "Leo", "house": 7, "degree": 21.0},
"Mercury": {"sign": "Leo", "house": 7, "degree": 14.0},
"Jupiter": {"sign": "Scorpio", "house": 10, "degree": 13.0},
"Venus": {"sign": "Leo", "house": 7, "degree": 2.0},
"Saturn": {"sign": "Taurus", "house": 4, "degree": 10.0},
"Rahu": {"sign": "Pisces", "house": 2, "degree": 25.0},
"Ketu": {"sign": "Virgo", "house": 8, "degree": 25.0},
},
"context": {
"d9": {
"ascendant": "Aries",
}
},
}
def test_raman_static_chart_triggers_stable_yoga_rule_ids() -> None:
detected = detect_yogas_from_json(RAMAN_STATIC_CHART)
rule_ids = {row.get("rule_id") for row in detected}
assert len(detected) >= 50
assert {
"dharma_karmadhipati",
"chandra_yoga_exalted",
"shakti_yoga_9_10_lord",
"bvr_016_vesi_precise",
"budha_shukra_yoga",
"kalatra_yoga_venus_kendra",
"raja_yoga_5_10_lord",
"raja_yoga_4_10_lord",
}.issubset(rule_ids)
def test_raman_static_chart_preserves_yoga_metadata_contract() -> None:
detected = detect_yogas_from_json(RAMAN_STATIC_CHART)
by_rule_id = {row.get("rule_id"): row for row in detected}
dharma = by_rule_id["dharma_karmadhipati"]
assert dharma["category"] == "raja"
assert dharma["strength"] == ""
assert "9宫主金星Venus" in dharma["combination"]
assert "10宫主火星Mars" in dharma["combination"]
chandra = by_rule_id["chandra_yoga_exalted"]
assert chandra["category"] == "chandra"
assert chandra["strength"] == ""
assert chandra["source"] == "BPHS"