feat(skill): add sensitive point varga markers

This commit is contained in:
732642856
2026-06-26 22:24:58 +08:00
parent 8f56ad632b
commit 223b2d8aa2
4 changed files with 124 additions and 4 deletions
+4 -4
View File
@@ -4,8 +4,8 @@
[![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-77-blueviolet)](references/technique_registry.json)
[![Covered](https://img.shields.io/badge/covered-68-green)](references/technique_registry.json)
[![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)
[![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** 77 registered techniques (Dashas, Yogas, Shadbala, Ashtakavarga, Transits...)
2. **Runs** 79 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 | ✅ | ❌ | ❌ | ❌ |
| 77 techniques registered | ✅ | ✅ (50+) | ✅ (200+) | ✅ |
| 79 techniques registered | ✅ | ✅ (50+) | ✅ (200+) | ✅ |
| Traditional algorithm benchmarked | ✅ mixed depth | ✅ | ✅ | ✅ |
| Docker / MCP Server | ✅ | ❌ | ✅ | ❌ |
| English docs / PyPI package | ✅ in progress | ✅ | ✅ | ✅ |
+42
View File
@@ -554,6 +554,48 @@
"audit_label": "22nd Drekkana",
"missing_impact": "A classical danger-sensitive Drekkana trigger is absent, weakening accident and adversity screening."
},
"bhrigu_bindu": {
"name": "Bhrigu Bindu",
"domains": [
"sensitive_point",
"timing",
"destiny"
],
"status": "covered",
"knowledge_refs": [
"references/bhrigu-pada-dasha-marriage-counting.md",
"references/feature-gap-matrix-2026.md"
],
"commands": [
"scripts/varga.py"
],
"output_paths": [
"scripts.varga.calc_bhrigu_bindu"
],
"audit_label": "Bhrigu Bindu",
"missing_impact": "A commonly used Moon-Rahu destiny trigger is unavailable, weakening event-sensitive reading depth."
},
"sarpa_drekkana": {
"name": "Sarpa Drekkana",
"domains": [
"varga",
"toxicity",
"crisis"
],
"status": "covered",
"knowledge_refs": [
"references/translated-articles/3印度占星_preview.txt",
"references/feature-gap-matrix-2026.md"
],
"commands": [
"scripts/varga.py"
],
"output_paths": [
"scripts.varga.calc_sarpa_drekkana"
],
"audit_label": "Sarpa Drekkana",
"missing_impact": "A classical toxic-crisis Drekkana marker is absent, thinning advanced risk and temperament screening."
},
"bhava_chalit": {
"name": "Bhava Chalit",
"domains": [
+41
View File
@@ -126,6 +126,47 @@ def calc_22nd_drekkana(lagna_lon: float) -> Dict:
'lord': SIGN_LORDS.get(_sn(sign_idx), ''),
}
def calc_bhrigu_bindu(moon_lon: float, rahu_lon: float) -> Dict:
"""Compute Bhrigu Bindu as the midpoint on the Rahu->Moon forward arc."""
moon = moon_lon % 360
rahu = rahu_lon % 360
arc = (moon - rahu) % 360
longitude = (rahu + arc / 2.0) % 360
sign_idx = _si(longitude)
degree_in_sign = round(longitude - sign_idx * 30, 4)
return {
'longitude': round(longitude, 4),
'sign_idx': sign_idx,
'sign': _sn(sign_idx),
'degree_in_sign': degree_in_sign,
'arc_mode': 'forward_rahu_to_moon',
'lord': SIGN_LORDS.get(_sn(sign_idx), ''),
}
SARPA_DREKKANA_SIGNS = {'Cancer': 2, 'Scorpio': 1, 'Pisces': 3}
def calc_sarpa_drekkana(lon: float) -> Dict:
"""Classify Sarpa Drekkana using the classical water-sign sensitive drekkanas."""
base = calc_varga(lon, 3)
sign = _sn(_si(lon))
degree_in_sign = round((lon % 30), 4)
drekkana_number = int(degree_in_sign / 10) + 1
expected = SARPA_DREKKANA_SIGNS.get(sign)
return {
'longitude': round(lon % 360, 4),
'sign': sign,
'sign_idx': _si(lon),
'degree_in_sign': degree_in_sign,
'drekkana_number': drekkana_number,
'd3_sign': base['sign'],
'd3_sign_idx': base['sign_idx'],
'is_sarpa_drekkana': bool(expected == drekkana_number),
'definition': 'Cancer-2, Scorpio-1, Pisces-3',
}
def dignity(planet, sign_idx):
if planet in EXALT_SIGN and sign_idx==EXALT_SIGN[planet]: return 'Exalted'
if planet in DEBIL_SIGN and sign_idx==DEBIL_SIGN[planet]: return 'Debilitated'
+37
View File
@@ -7,8 +7,10 @@ from hypothesis import given
from hypothesis import strategies as st
from varga import (
SIGNS,
calc_bhrigu_bindu,
calc_22nd_drekkana,
calc_64th_navamsa,
calc_sarpa_drekkana,
calc_varga,
varga_map,
)
@@ -106,3 +108,38 @@ def test_22nd_drekkana_counts_forward_from_lagna_drekkana() -> None:
assert result["sign_idx"] == expected_sign_idx
assert result["sign"] == SIGNS[expected_sign_idx]
assert result["offset_from_lagna_drekkana"] == 22
def test_bhrigu_bindu_uses_rahu_to_moon_arc_midpoint() -> None:
result = calc_bhrigu_bindu(270.5, 160.2333333333)
assert result["longitude"] == 215.3667
assert result["sign"] == "Scorpio"
assert result["degree_in_sign"] == 5.3667
def test_bhrigu_bindu_handles_wraparound_across_zero_aries() -> None:
result = calc_bhrigu_bindu(10.0, 350.0)
assert result["longitude"] == 0.0
assert result["sign"] == "Aries"
assert result["degree_in_sign"] == 0.0
def test_sarpa_drekkana_detects_classical_sensitive_ranges() -> None:
cancer_second = calc_sarpa_drekkana(105.0)
scorpio_first = calc_sarpa_drekkana(215.0)
pisces_third = calc_sarpa_drekkana(355.0)
safe_aries = calc_sarpa_drekkana(15.0)
assert cancer_second["is_sarpa_drekkana"] is True
assert cancer_second["sign"] == "Cancer"
assert cancer_second["drekkana_number"] == 2
assert scorpio_first["is_sarpa_drekkana"] is True
assert scorpio_first["sign"] == "Scorpio"
assert scorpio_first["drekkana_number"] == 1
assert pisces_third["is_sarpa_drekkana"] is True
assert pisces_third["sign"] == "Pisces"
assert pisces_third["drekkana_number"] == 3
assert safe_aries["is_sarpa_drekkana"] is False