From 73d89586cae3924a6aa7ca1ecbeeb1754df4c9d3 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Sun, 28 Jun 2026 15:34:17 +0800 Subject: [PATCH] Extend Shadbala component cap to core routes --- ...ala_component_cap_all_routes_2026_06_28.md | 61 +++++++++++++++++++ mcp_server.py | 18 +++++- tests/test_mcp_strict_workflow_career.py | 49 +++++++++++++++ .../test_mcp_strict_workflow_relationship.py | 49 +++++++++++++++ 4 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 docs/research/shadbala_component_cap_all_routes_2026_06_28.md diff --git a/docs/research/shadbala_component_cap_all_routes_2026_06_28.md b/docs/research/shadbala_component_cap_all_routes_2026_06_28.md new file mode 100644 index 00000000..7c0d8477 --- /dev/null +++ b/docs/research/shadbala_component_cap_all_routes_2026_06_28.md @@ -0,0 +1,61 @@ +# Shadbala Component Cap Across Core Routes + +Date: 2026-06-28 + +## Scope + +This pass extends the Shadbala six-component completeness cap beyond finance into the three core strict adjudication routes: + +- career +- relationship +- finance + +## Route Boundary + +Finance still requires `shadbala.planets`. + +Career and relationship do not make Shadbala a hard route requirement in v1. Instead: + +- if Shadbala is absent, the existing route continues unchanged; +- if Shadbala is present, its six-component completeness is audited; +- incomplete Shadbala lowers `confidence_cap` to `low`. + +This prevents a partial strength packet from inflating high-rigor readings while preserving backward compatibility for career and relationship routes. + +## Required Components + +- `sthana` +- `dig` +- `kala` +- `chesta` +- `naisargika` +- `drik` + +Accepted layouts: + +- `planet.components.` +- direct `planet.` + +## Adjudication Effect + +When the component audit is `blocked` or `incomplete`: + +- `confidence_cap = "low"` +- `secondary_context += ["shadbala_component_gap"]` + +When complete: + +- no confidence penalty +- no gap context + +## Anti-Overclaim Rule + +This is not Shadbala absolute calibration. It only enforces component completeness. + +Still open: + +- absolute Rupa comparison against JHora/PyJHora/VedAstro +- six-component value tolerance tests +- route-specific Shadbala planet selection and score weighting +- public benchmark history for Shadbala drift + diff --git a/mcp_server.py b/mcp_server.py index 912c98ca..6467dd44 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -734,6 +734,9 @@ def _derive_event_judgement(route: str, present: Dict[str, Any], missing: List[s secondary_context.append("amk_active") if present.get("karakamsha"): secondary_context.append("karakamsha_context") + 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 argala_support.get("level") == "supportive": secondary_context.append("argala_support") elif argala_support.get("level") == "obstructive": @@ -810,6 +813,9 @@ def _derive_event_judgement(route: str, present: Dict[str, Any], missing: List[s secondary_context.append("jaimini_support") if present.get("upapada_lagna"): secondary_context.append("ul_support") + 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 argala_support.get("level") == "supportive": secondary_context.append("argala_support") elif argala_support.get("level") == "obstructive": @@ -996,15 +1002,19 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An "narayana_current": _safe_get(modules, "narayana_dasha", "current_dasha"), "career_convergence": domain_activations.get("career_status"), } + present["shadbala"] = _safe_get(modules, "shadbala", "planets") + present["shadbala_component_audit"] = _derive_shadbala_component_audit(present["shadbala"]) if present["shadbala"] else None present["argala_support"] = _derive_argala_support(modules, 10) present["external_activation"] = _derive_external_activation_support(modules, "career") missing = [key for key, value in present.items() if key not in { - "external_activation", "argala_support" + "external_activation", "argala_support", "shadbala", "shadbala_component_audit" } and value in (None, {}, [], "")] convergence = present["career_convergence"] or {} confidence_cap = "medium" if missing: confidence_cap = "low" + elif (present.get("shadbala_component_audit") or {}).get("status") in {"blocked", "incomplete"}: + confidence_cap = "low" elif convergence.get("convergence_level") in {"L4", "L5"}: confidence_cap = "medium-high" elif convergence.get("convergence_level") == "L3": @@ -1046,6 +1056,8 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An "narayana_current": _safe_get(modules, "narayana_dasha", "current_dasha"), "marriage_convergence": domain_activations.get("marriage_partnership"), } + present["shadbala"] = _safe_get(modules, "shadbala", "planets") + present["shadbala_component_audit"] = _derive_shadbala_component_audit(present["shadbala"]) if present["shadbala"] else None present["jaimini_timing_support"] = _safe_get(modules, "jaimini", "marriage_timing_support") present["jaimini_marriage_support"] = _derive_jaimini_marriage_support(present) present["argala_support"] = _derive_argala_support(modules, 7) @@ -1053,7 +1065,7 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An 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", "jaimini_marriage_support", "jaimini_timing_support", "argala_support"} + if key not in {"chart", "external_activation", "dignity_guardrail", "jaimini_marriage_support", "jaimini_timing_support", "argala_support", "shadbala", "shadbala_component_audit"} and value in (None, {}, [], "") ] convergence = present["marriage_convergence"] or {} @@ -1062,6 +1074,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.get("shadbala_component_audit") or {}).get("status") in {"blocked", "incomplete"}: + confidence_cap = "low" elif convergence.get("convergence_level") in {"L4", "L5"}: confidence_cap = "medium-high" elif convergence.get("convergence_level") == "L3": diff --git a/tests/test_mcp_strict_workflow_career.py b/tests/test_mcp_strict_workflow_career.py index 2cf3497c..718667a4 100644 --- a/tests/test_mcp_strict_workflow_career.py +++ b/tests/test_mcp_strict_workflow_career.py @@ -94,3 +94,52 @@ def test_career_argala_bridge_uses_tenth_house_as_modifier_only() -> None: } assert strict["event_judgement"]["dominant_label"] == "career_status" assert "argala_support" in strict["event_judgement"]["secondary_context"] + + +def test_career_caps_confidence_when_provided_shadbala_components_are_incomplete() -> None: + result = _base_career_result() + result["modules"]["dasa_convergence"]["domain_activations"]["career_status"] = { + "convergence_level": "L4", + "probability": "70-85%", + } + result["modules"]["shadbala"] = {"planets": {"Mercury": {"total_rupa": 7.5}}} + + strict = _collect_strict_evidence("career", result) + + assert strict["present_evidence"]["shadbala_component_audit"] == { + "status": "incomplete", + "source": "shadbala.planets", + "required_components": ["sthana", "dig", "kala", "chesta", "naisargika", "drik"], + "missing": {"Mercury": ["sthana", "dig", "kala", "chesta", "naisargika", "drik"]}, + } + assert strict["confidence_cap"] == "low" + assert "shadbala_component_gap" in strict["event_judgement"]["secondary_context"] + + +def test_career_accepts_complete_shadbala_components_without_cap_penalty() -> None: + result = _base_career_result() + result["modules"]["dasa_convergence"]["domain_activations"]["career_status"] = { + "convergence_level": "L4", + "probability": "70-85%", + } + result["modules"]["shadbala"] = { + "planets": { + "Mercury": { + "components": { + "sthana": 1.0, + "dig": 0.8, + "kala": 1.2, + "chesta": 0.7, + "naisargika": 0.5, + "drik": 0.3, + }, + "total_rupa": 4.5, + } + } + } + + strict = _collect_strict_evidence("career", result) + + assert strict["present_evidence"]["shadbala_component_audit"]["status"] == "complete" + assert strict["confidence_cap"] == "medium-high" + assert "shadbala_component_gap" not in strict["event_judgement"]["secondary_context"] diff --git a/tests/test_mcp_strict_workflow_relationship.py b/tests/test_mcp_strict_workflow_relationship.py index 9fdb623a..79eae684 100644 --- a/tests/test_mcp_strict_workflow_relationship.py +++ b/tests/test_mcp_strict_workflow_relationship.py @@ -149,3 +149,52 @@ def test_relationship_dignity_guardrail_uses_relevant_planets_only() -> None: assert strict["present_evidence"]["dignity_guardrail"]["score_delta"] == 5 assert "dignity_supportive_recovery" in strict["event_judgement"]["secondary_context"] + + +def test_relationship_caps_confidence_when_provided_shadbala_components_are_incomplete() -> None: + result = _base_relationship_result() + result["modules"]["dasa_convergence"]["domain_activations"]["marriage_partnership"] = { + "convergence_level": "L4", + "probability": "70-85%", + } + result["modules"]["shadbala"] = {"planets": {"Venus": {"total_rupa": 8.2}}} + + strict = _collect_strict_evidence("relationship", 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_relationship_accepts_complete_shadbala_components_without_cap_penalty() -> None: + result = _base_relationship_result() + result["modules"]["dasa_convergence"]["domain_activations"]["marriage_partnership"] = { + "convergence_level": "L4", + "probability": "70-85%", + } + result["modules"]["shadbala"] = { + "planets": { + "Venus": { + "components": { + "sthana": 1.0, + "dig": 0.8, + "kala": 1.2, + "chesta": 0.7, + "naisargika": 0.5, + "drik": 0.3, + }, + "total_rupa": 4.5, + } + } + } + + strict = _collect_strict_evidence("relationship", result) + + assert strict["present_evidence"]["shadbala_component_audit"]["status"] == "complete" + assert strict["confidence_cap"] == "medium-high" + assert "shadbala_component_gap" not in strict["event_judgement"]["secondary_context"]