diff --git a/docs/research/whole_project_fragment_sweep_and_vedastro_ledger_link_2026_06_28.md b/docs/research/whole_project_fragment_sweep_and_vedastro_ledger_link_2026_06_28.md new file mode 100644 index 00000000..119efcab --- /dev/null +++ b/docs/research/whole_project_fragment_sweep_and_vedastro_ledger_link_2026_06_28.md @@ -0,0 +1,49 @@ +# Whole Project Fragment Sweep And VedAstro Ledger Link - 2026-06-28 + +## Sweep Result + +The current `SKILL.md` and `AGENTS.md` match the installed WorkBuddy skill copy: + +- `/Users/wuyongnaren/Documents/印度占星/SKILL.md` +- `/Users/wuyongnaren/.workbuddy/skills/jyotish-vedic-astrology/SKILL.md` +- `/Users/wuyongnaren/Documents/印度占星/AGENTS.md` +- `/Users/wuyongnaren/.workbuddy/skills/jyotish-vedic-astrology/AGENTS.md` + +No instruction-layer skill drift was found. + +The WorkBuddy `scripts/jyotish_engine.py` and `scripts/jyotish_api_server.py` +are older distribution copies and must not be reverse-copied over the current +repository source. + +## Implemented Link + +VedAstro range-scan output can now enter local strict workflows as external +activation context: + +- relationship domain reads `modules.external_activation.evidence_ledger` + entries where `domain == "marriage"`. +- finance domain reads `modules.external_activation.evidence_ledger` entries + where `domain == "wealth"`. +- only `vedastro_service_adapter_candidate` range-scan events are accepted. +- a score of `70+` maps to `level = "moderate"`. +- moderate support adds `external_activation_support` to `secondary_context`. + +## Boundary + +- external activation does not directly lift `dominant_label`. +- external activation does not change `payout_label`. +- external activation does not bypass D9/UL, D2/D10, dual dasha, or existing + convergence gates. +- cross-domain events are ignored. + +## Verification + +- `python3 -m pytest tests/test_mcp_strict_workflow_relationship.py tests/test_mcp_strict_workflow_finance.py tests/test_vedastro_service_adapter_executor.py -q` +- Result: `31 passed` + +## Next Work + +1. Add a domain-specific allowlist for VedAstro event IDs and tags. +2. Add real endpoint field mapping once a stable VedAstro endpoint is configured. +3. Add a benchmark fixture that feeds VedAstro ledger candidates into + relationship and finance case audits. diff --git a/mcp_server.py b/mcp_server.py index a304b4b3..fc2a7f38 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -411,6 +411,43 @@ def _derive_jaimini_marriage_support(present: Dict[str, Any]) -> Dict[str, Any]: } +def _derive_external_activation_support(modules: Dict[str, Any], domain: str) -> Dict[str, Any]: + ledger = _safe_get(modules, "external_activation", "evidence_ledger") + if not isinstance(ledger, list): + return { + "level": "none", + "source": None, + "signals": [], + "events": [], + } + + events: List[Dict[str, Any]] = [] + for event in ledger: + if not isinstance(event, dict): + continue + if event.get("operation") != "range_scan": + continue + if event.get("domain") != domain: + continue + if event.get("source") != "vedastro_service_adapter_candidate": + continue + events.append(event) + + if not events: + level = "none" + elif any((event.get("score") or 0) >= 70 for event in events): + level = "moderate" + else: + level = "weak" + + return { + "level": level, + "source": "vedastro_service_adapter_candidate" if events else None, + "signals": ["vedastro_range_scan"] if events else [], + "events": events, + } + + def _derive_event_judgement(route: str, present: Dict[str, Any], missing: List[str]) -> Dict[str, Any]: if route == "relationship": score = 0 @@ -453,6 +490,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") + external_activation = present.get("external_activation") or {} + if external_activation.get("level") == "moderate": + secondary_context.append("external_activation_support") hard_gate_missing = any( key in missing for key in ( @@ -563,6 +603,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") + external_activation = present.get("external_activation") or {} + if external_activation.get("level") == "moderate": + secondary_context.append("external_activation_support") return { "event_family": "finance", "score": score, @@ -616,9 +659,10 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An } present["jaimini_timing_support"] = _safe_get(modules, "jaimini", "marriage_timing_support") present["jaimini_marriage_support"] = _derive_jaimini_marriage_support(present) + present["external_activation"] = _derive_external_activation_support(modules, "marriage") missing = [ key for key, value in present.items() - if key not in {"chart", "jaimini_marriage_support", "jaimini_timing_support"} + if key not in {"chart", "external_activation", "jaimini_marriage_support", "jaimini_timing_support"} and value in (None, {}, [], "") ] convergence = present["marriage_convergence"] or {} @@ -671,8 +715,9 @@ 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["external_activation"] = _derive_external_activation_support(modules, "wealth") missing = [key for key, value in present.items() if key not in { - "chart", "gains_convergence", "career_convergence", "avayogi_risk" + "chart", "external_activation", "gains_convergence", "career_convergence", "avayogi_risk" } and value in (None, {}, [], "")] convergence_hits: List[Dict[str, Any]] = [ item for item in [ diff --git a/tests/test_mcp_strict_workflow_finance.py b/tests/test_mcp_strict_workflow_finance.py index 40e01315..bab495b9 100644 --- a/tests/test_mcp_strict_workflow_finance.py +++ b/tests/test_mcp_strict_workflow_finance.py @@ -224,6 +224,75 @@ def test_collect_strict_evidence_finance_combines_dhana_and_lakshmi_hooks() -> N } +def test_collect_strict_evidence_finance_collects_vedastro_range_scan_as_external_activation_context() -> None: + result = { + "modules": { + "varga_full": {"D2_Hora": {"summary": "ok"}, "D10_Dasamsa": {"summary": "ok"}}, + "shadbala": {"planets": {"Venus": {"total_rupa": 8.2}}}, + "ashtakavarga": {"house_scores": {"2": 31, "11": 36}}, + "dasha": {"current_dasha": {"mahadasha": "Venus", "antardasha": "Mercury"}}, + "narayana_dasha": {"current_dasha": {"sign": "Taurus", "lord": "Venus"}}, + "dasa_convergence": { + "domain_activations": { + "wealth_family": {"convergence_level": "L1", "probability": "+15-20%"}, + "gains_wishes": {"convergence_level": "L1", "probability": "+15-20%"}, + "career_status": {"convergence_level": "L1", "probability": "+15-20%"}, + } + }, + "external_activation": { + "evidence_ledger": [ + { + "source": "vedastro_service_adapter_candidate", + "operation": "range_scan", + "domain": "wealth", + "event_id": "jupiter_2h_11h_window", + "score": 76, + } + ] + }, + } + } + + strict = _collect_strict_evidence("finance", result) + + assert strict["present_evidence"]["external_activation"]["level"] == "moderate" + assert strict["present_evidence"]["external_activation"]["source"] == "vedastro_service_adapter_candidate" + assert "external_activation_support" in strict["event_judgement"]["secondary_context"] + + +def test_collect_strict_evidence_finance_ignores_non_matching_external_activation_domains() -> None: + result = { + "modules": { + "varga_full": {"D2_Hora": {"summary": "ok"}, "D10_Dasamsa": {"summary": "ok"}}, + "shadbala": {"planets": {"Venus": {"total_rupa": 8.2}}}, + "ashtakavarga": {"house_scores": {"2": 31, "11": 36}}, + "dasha": {"current_dasha": {"mahadasha": "Venus", "antardasha": "Mercury"}}, + "narayana_dasha": {"current_dasha": {"sign": "Taurus", "lord": "Venus"}}, + "dasa_convergence": { + "domain_activations": { + "wealth_family": {"convergence_level": "L1", "probability": "+15-20%"}, + } + }, + "external_activation": { + "evidence_ledger": [ + { + "source": "vedastro_service_adapter_candidate", + "operation": "range_scan", + "domain": "marriage", + "event_id": "relationship_window", + "score": 95, + } + ] + }, + } + } + + strict = _collect_strict_evidence("finance", result) + + assert strict["present_evidence"]["external_activation"]["level"] == "none" + assert "external_activation_support" not in strict["event_judgement"]["secondary_context"] + + def test_derive_yogi_wealth_support_detects_strong_native_hook() -> None: modules = { "chart": { diff --git a/tests/test_mcp_strict_workflow_relationship.py b/tests/test_mcp_strict_workflow_relationship.py index fc1cd763..6421525b 100644 --- a/tests/test_mcp_strict_workflow_relationship.py +++ b/tests/test_mcp_strict_workflow_relationship.py @@ -60,3 +60,24 @@ def test_relationship_jaimini_bridge_stays_context_only_when_d9_missing() -> Non "jaimini_support", "ul_support", ] + + +def test_relationship_collects_vedastro_range_scan_as_external_activation_context() -> None: + result = _base_relationship_result() + result["modules"]["external_activation"] = { + "evidence_ledger": [ + { + "source": "vedastro_service_adapter_candidate", + "operation": "range_scan", + "domain": "marriage", + "event_id": "jupiter_7h_window", + "score": 72, + } + ] + } + + strict = _collect_strict_evidence("relationship", result) + + assert strict["present_evidence"]["external_activation"]["level"] == "moderate" + assert strict["present_evidence"]["external_activation"]["source"] == "vedastro_service_adapter_candidate" + assert "external_activation_support" in strict["event_judgement"]["secondary_context"]