Cap finance confidence on incomplete Shadbala components
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# Shadbala Component Confidence Cap v1
|
||||
|
||||
Date: 2026-06-28
|
||||
|
||||
## Scope
|
||||
|
||||
This pass connects Shadbala quality into the finance strict adjudicator.
|
||||
|
||||
Before this change, `shadbala.planets` acted mostly as a presence gate. A planet with only `total_rupa` could satisfy the route even when the six classical components were missing.
|
||||
|
||||
## Required Components
|
||||
|
||||
The v1 audit requires each listed planet to expose all six components:
|
||||
|
||||
- `sthana`
|
||||
- `dig`
|
||||
- `kala`
|
||||
- `chesta`
|
||||
- `naisargika`
|
||||
- `drik`
|
||||
|
||||
Accepted layouts:
|
||||
|
||||
- `planet.components.sthana`
|
||||
- direct `planet.sthana`
|
||||
|
||||
## Contract
|
||||
|
||||
`present_evidence.shadbala_component_audit`:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "complete | incomplete | blocked",
|
||||
"source": "shadbala.planets",
|
||||
"required_components": ["sthana", "dig", "kala", "chesta", "naisargika", "drik"],
|
||||
"missing": {
|
||||
"Venus": ["sthana", "dig"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Adjudication Boundary
|
||||
|
||||
- `complete`: no confidence penalty.
|
||||
- `incomplete` or `blocked`: `confidence_cap = "low"` and `secondary_context += ["shadbala_component_gap"]`.
|
||||
|
||||
This does not claim Shadbala absolute calibration is complete. It only prevents a partial Shadbala packet from supporting high-confidence finance timing.
|
||||
|
||||
## Anti-Overclaim Rule
|
||||
|
||||
This v1 pass does not:
|
||||
|
||||
- compare Rupa values against JHora/PyJHora absolute truth
|
||||
- score individual components
|
||||
- change `dominant_label` or `payout_label`
|
||||
- affect career or relationship routes
|
||||
|
||||
External oracle closure is still required before claiming mature Shadbala absolute accuracy.
|
||||
|
||||
+36
-1
@@ -142,6 +142,7 @@ _NAKSHATRA_LORDS = [
|
||||
]
|
||||
_WEALTH_HOUSES = {2, 5, 9, 10, 11}
|
||||
_NAKSHATRA_SPAN = 360.0 / 27.0
|
||||
_SHADBALA_REQUIRED_COMPONENTS = ["sthana", "dig", "kala", "chesta", "naisargika", "drik"]
|
||||
|
||||
|
||||
def _normalize_longitude(value: Any) -> Optional[float]:
|
||||
@@ -540,6 +541,34 @@ def _derive_ashtakavarga_finance_support(house_scores: Any) -> Dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def _derive_shadbala_component_audit(planets: Any) -> Dict[str, Any]:
|
||||
audit = {
|
||||
"status": "blocked",
|
||||
"source": "shadbala.planets",
|
||||
"required_components": _SHADBALA_REQUIRED_COMPONENTS,
|
||||
"missing": {},
|
||||
}
|
||||
if not isinstance(planets, dict) or not planets:
|
||||
return audit
|
||||
|
||||
missing: Dict[str, List[str]] = {}
|
||||
for planet, pdata in planets.items():
|
||||
if not isinstance(pdata, dict):
|
||||
missing[str(planet)] = list(_SHADBALA_REQUIRED_COMPONENTS)
|
||||
continue
|
||||
components = pdata.get("components") if isinstance(pdata.get("components"), dict) else pdata
|
||||
planet_missing = [
|
||||
component for component in _SHADBALA_REQUIRED_COMPONENTS
|
||||
if components.get(component) in (None, "", [], {})
|
||||
]
|
||||
if planet_missing:
|
||||
missing[str(planet)] = planet_missing
|
||||
|
||||
audit["missing"] = missing
|
||||
audit["status"] = "complete" if not missing else "incomplete"
|
||||
return audit
|
||||
|
||||
|
||||
def _sign_to_index(sign: str) -> Optional[int]:
|
||||
try:
|
||||
return _SIGNS.index(sign)
|
||||
@@ -901,6 +930,9 @@ def _derive_event_judgement(route: str, present: Dict[str, Any], missing: List[s
|
||||
secondary_context.append("gains_wishes")
|
||||
if isinstance(avayogi_risk, dict) and avayogi_risk.get("risk_level") == "moderate":
|
||||
secondary_context.append("avayogi_active")
|
||||
shadbala_component_audit = present.get("shadbala_component_audit") or {}
|
||||
if shadbala_component_audit.get("status") in {"blocked", "incomplete"}:
|
||||
secondary_context.append("shadbala_component_gap")
|
||||
if ashtakavarga_finance.get("level") == "supportive":
|
||||
secondary_context.append("ashtakavarga_wealth_support")
|
||||
elif ashtakavarga_finance.get("level") == "obstructive":
|
||||
@@ -1076,13 +1108,14 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An
|
||||
"wealth_promise_strength": _derive_wealth_promise_strength(modules),
|
||||
"avayogi_risk": avayogi_risk,
|
||||
}
|
||||
present["shadbala_component_audit"] = _derive_shadbala_component_audit(present["shadbala"])
|
||||
present["ashtakavarga_finance_support"] = _derive_ashtakavarga_finance_support(
|
||||
present["ashtakavarga_house_scores"]
|
||||
)
|
||||
present["external_activation"] = _derive_external_activation_support(modules, "wealth")
|
||||
present["dignity_guardrail"] = _derive_dignity_guardrail(route, present)
|
||||
missing = [key for key, value in present.items() if key not in {
|
||||
"chart", "external_activation", "dignity_guardrail", "gains_convergence", "career_convergence", "avayogi_risk", "ashtakavarga_finance_support"
|
||||
"chart", "external_activation", "dignity_guardrail", "gains_convergence", "career_convergence", "avayogi_risk", "ashtakavarga_finance_support", "shadbala_component_audit"
|
||||
} and value in (None, {}, [], "")]
|
||||
convergence_hits: List[Dict[str, Any]] = [
|
||||
item for item in [
|
||||
@@ -1097,6 +1130,8 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An
|
||||
confidence_cap = "low"
|
||||
elif present["dignity_guardrail"].get("status") == "conflict":
|
||||
confidence_cap = "low"
|
||||
elif present["shadbala_component_audit"].get("status") in {"blocked", "incomplete"}:
|
||||
confidence_cap = "low"
|
||||
elif any(hit.get("convergence_level") in {"L4", "L5"} for hit in convergence_hits):
|
||||
confidence_cap = "medium-high"
|
||||
elif convergence_hits:
|
||||
|
||||
@@ -228,6 +228,92 @@ def test_collect_strict_evidence_finance_folds_wealth_ashtakavarga_support() ->
|
||||
assert "ashtakavarga_wealth_support" in strict["event_judgement"]["secondary_context"]
|
||||
|
||||
|
||||
def test_collect_strict_evidence_finance_caps_confidence_when_shadbala_components_missing() -> None:
|
||||
result = {
|
||||
"modules": {
|
||||
"varga_full": {"D2_Hora": {"summary": "ok"}, "D10_Dasamsa": {"summary": "ok"}},
|
||||
"shadbala": {"planets": {"Venus": {"total_rupa": 8.2}}},
|
||||
"ashtakavarga": {"house_scores": {"2": 33, "11": 35}},
|
||||
"dasha": {"current_dasha": {"mahadasha": "Venus", "antardasha": "Mercury"}},
|
||||
"narayana_dasha": {"current_dasha": {"sign": "Taurus", "lord": "Venus"}},
|
||||
"dasa_convergence": {
|
||||
"domain_activations": {
|
||||
"wealth_family": {"convergence_level": "L4", "probability": "70-85%"},
|
||||
"gains_wishes": {"convergence_level": "L4", "probability": "70-85%"},
|
||||
"career_status": {"convergence_level": "L4", "probability": "70-85%"},
|
||||
}
|
||||
},
|
||||
"yogas_doshas": {
|
||||
"dhana_yogas": {
|
||||
"yogas": [{"type": "Dhana Yoga", "strength": "strong"}],
|
||||
"summary": "Dhana Yoga检测:共1个格局",
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
strict = _collect_strict_evidence("finance", result)
|
||||
|
||||
assert strict["present_evidence"]["shadbala_component_audit"] == {
|
||||
"status": "incomplete",
|
||||
"source": "shadbala.planets",
|
||||
"required_components": ["sthana", "dig", "kala", "chesta", "naisargika", "drik"],
|
||||
"missing": {"Venus": ["sthana", "dig", "kala", "chesta", "naisargika", "drik"]},
|
||||
}
|
||||
assert strict["confidence_cap"] == "low"
|
||||
assert "shadbala_component_gap" in strict["event_judgement"]["secondary_context"]
|
||||
|
||||
|
||||
def test_collect_strict_evidence_finance_accepts_complete_shadbala_components() -> None:
|
||||
result = {
|
||||
"modules": {
|
||||
"varga_full": {"D2_Hora": {"summary": "ok"}, "D10_Dasamsa": {"summary": "ok"}},
|
||||
"shadbala": {
|
||||
"planets": {
|
||||
"Venus": {
|
||||
"components": {
|
||||
"sthana": 1.2,
|
||||
"dig": 0.8,
|
||||
"kala": 1.1,
|
||||
"chesta": 0.9,
|
||||
"naisargika": 0.7,
|
||||
"drik": 0.4,
|
||||
},
|
||||
"total_rupa": 5.1,
|
||||
}
|
||||
}
|
||||
},
|
||||
"ashtakavarga": {"house_scores": {"2": 33, "11": 35}},
|
||||
"dasha": {"current_dasha": {"mahadasha": "Venus", "antardasha": "Mercury"}},
|
||||
"narayana_dasha": {"current_dasha": {"sign": "Taurus", "lord": "Venus"}},
|
||||
"dasa_convergence": {
|
||||
"domain_activations": {
|
||||
"wealth_family": {"convergence_level": "L4", "probability": "70-85%"},
|
||||
"gains_wishes": {"convergence_level": "L4", "probability": "70-85%"},
|
||||
"career_status": {"convergence_level": "L4", "probability": "70-85%"},
|
||||
}
|
||||
},
|
||||
"yogas_doshas": {
|
||||
"dhana_yogas": {
|
||||
"yogas": [{"type": "Dhana Yoga", "strength": "strong"}],
|
||||
"summary": "Dhana Yoga检测:共1个格局",
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
strict = _collect_strict_evidence("finance", result)
|
||||
|
||||
assert strict["present_evidence"]["shadbala_component_audit"] == {
|
||||
"status": "complete",
|
||||
"source": "shadbala.planets",
|
||||
"required_components": ["sthana", "dig", "kala", "chesta", "naisargika", "drik"],
|
||||
"missing": {},
|
||||
}
|
||||
assert strict["confidence_cap"] == "medium-high"
|
||||
assert "shadbala_component_gap" not in strict["event_judgement"]["secondary_context"]
|
||||
|
||||
|
||||
def test_collect_strict_evidence_finance_flags_low_wealth_ashtakavarga_friction() -> None:
|
||||
result = {
|
||||
"modules": {
|
||||
|
||||
Reference in New Issue
Block a user