diff --git a/mcp_server.py b/mcp_server.py index 4773d624..ca7e0298 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -120,6 +120,15 @@ def _existing_paths(paths: List[str]) -> List[str]: return [path for path in paths if _repo_relative_exists(path)] +CORE_RULE_SOURCE_REFS = [ + "references/prediction-boundary-protocol.md", + "references/event_judgment_skeleton.md", + "references/planetary-dignity-complete-reference.md", + "references/retrograde-combustion-war-guide.md", + "references/transit-multi-reference-guide.md", +] + + def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str, Any]: primary_truth = [ "references/interpretation_template_registry.json", @@ -156,6 +165,7 @@ def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str, reference_layer = [ "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/p1_p12.md", "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/house_framework.md", + *CORE_RULE_SOURCE_REFS, *frontend_interpretation, *qa_governance, *reader_validation, @@ -205,6 +215,14 @@ def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str, "source_refs": _existing_paths(saham_rules), "missing_refs": [path for path in saham_rules if not _repo_relative_exists(path)], }, + "core_rule_sources": { + "status": "available", + "promotion_status": "primary_truth_candidate", + "promotion_batch": "priority1_batch1_core5", + "source_refs": _existing_paths(CORE_RULE_SOURCE_REFS), + "missing_refs": [path for path in CORE_RULE_SOURCE_REFS if not _repo_relative_exists(path)], + "boundary": "First promoted core references; visible to strict workflows but still subject to conflict arbitration.", + }, "quarantined_drafts": { "status": "quarantined", "promotion_status": "not_truth_source", @@ -248,6 +266,7 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]: bphs_narayana_path = "references/bphs-ch48-narayana-dasha.md" mevg_path = "references/mandatory-verification-gate-protocol.md" real_case_checklist_path = "references/real-reading-quality-checklist.md" + core_rule_paths = CORE_RULE_SOURCE_REFS frontend_interpretation_paths = [ "jyotish-app/interpretation.js", "jyotish-app/analysis-deep.js", @@ -288,6 +307,7 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]: bphs_narayana_path, mevg_path, real_case_checklist_path, + *core_rule_paths, *frontend_interpretation_paths, *planet_house_paths, qa_rules_path, @@ -316,6 +336,7 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]: "bphs_narayana_dasha", "mevg_mandatory_external_verification", "real_case_quality_checklist", + "priority1_batch1_core_rule_sources", "qa_governance_rules", "reader_validation_rules", "frontend_interpretation_layer", @@ -326,6 +347,13 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]: "status": "available" if _repo_relative_exists(raman_path) and _repo_relative_exists(bphs_narayana_path) else "partial", "source_refs": [raman_path, bphs_narayana_path], }, + "core_rule_source_layer": { + "status": "available" if all(_repo_relative_exists(path) for path in core_rule_paths) else "partial", + "source_refs": core_rule_paths, + "promotion_status": "primary_truth_candidate", + "promotion_batch": "priority1_batch1_core5", + "boundary": "Audit-promoted core references; use as visible rule sources with conflict arbitration.", + }, "frontend_interpretation_layer": { "status": "available" if all(_repo_relative_exists(path) for path in frontend_interpretation_paths) else "partial", "source_refs": frontend_interpretation_paths, @@ -2520,6 +2548,11 @@ def _build_technique_audit_summary(route: str, strict: Dict[str, Any]) -> Dict[s "status": interpretation_source_pack.get("status") or "blocked", "source": interpretation_source_pack.get("source") or "repo_existing_interpretation_sources", "source_refs": interpretation_source_pack.get("source_refs") or [], + "core_rule_source_refs": ( + interpretation_source_pack.get("core_rule_source_layer", {}).get("source_refs") + if isinstance(interpretation_source_pack.get("core_rule_source_layer"), dict) + else [] + ), "missing_refs": interpretation_source_pack.get("missing_refs") or [], "effect_on_confidence": ( "uses existing BPHS/Raman/frontend/template source layers; missing refs lower confidence" diff --git a/progress.md b/progress.md index 4565c218..eea9e1c8 100644 --- a/progress.md +++ b/progress.md @@ -760,3 +760,11 @@ - 新增人读审计说明:`docs/research/interpretation_source_priority1_batch1_promotion_audit_2026_07_02.md`。 - 当前处置:`promote=16`、`reference-only=6`、`obsolete=3`、`duplicate=3`、`quarantine=2`。 - 明确边界:本批只做 audit-only 分级,不直接接入 runtime source pack;后续升格仍需调用链、冲突仲裁、可见性测试。 + +## 2026-07-02T15:05:00+08:00 - priority_1 promote 核心 5 源头调用链接入 + +- 将第一批 promote 中的 5 个全局核心源头显式接入 `_existing_interpretation_source_pack()`:`prediction-boundary-protocol`、`event_judgment_skeleton`、`planetary-dignity-complete-reference`、`retrograde-combustion-war-guide`、`transit-multi-reference-guide`。 +- 新增 `core_rule_source_layer` 与 inventory `core_rule_sources` 层,标记为 `priority1_batch1_core5` / `primary_truth_candidate`。 +- `technique_audit_summary.interpretation_source_pack` 现在直接暴露 `core_rule_source_refs`,career / relationship / finance strict workflow 都能看到同一组核心源头。 +- 新增 `tests/test_interpretation_source_core5_strict_visibility.py`;同时加固 `tests/test_interpretation_source_inventory_gate.py` 对核心层的断言。 +- 边界仍保留:核心 5 已进入调用链可见性层,但具体解释仍需冲突仲裁、MEVG、真实案例校准和领域分盘/大运证据。 diff --git a/tests/test_interpretation_source_core5_strict_visibility.py b/tests/test_interpretation_source_core5_strict_visibility.py new file mode 100644 index 00000000..8f3d162e --- /dev/null +++ b/tests/test_interpretation_source_core5_strict_visibility.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +"""Strict workflow visibility tests for the first core promoted references.""" + +from __future__ import annotations + +from mcp_server import _collect_strict_evidence, _existing_interpretation_source_pack + + +CORE5_SOURCE_REFS = [ + "references/prediction-boundary-protocol.md", + "references/event_judgment_skeleton.md", + "references/planetary-dignity-complete-reference.md", + "references/retrograde-combustion-war-guide.md", + "references/transit-multi-reference-guide.md", +] + + +def _base_modules() -> dict: + return { + "modules": { + "chart": { + "ascendant": {"sign": "Leo"}, + "planets": { + "Sun": {"status": "中性(Neutral)"}, + "Moon": {"status": "中性(Neutral)"}, + "Mercury": {"status": "中性(Neutral)"}, + "Venus": {"status": "中性(Neutral)"}, + "Jupiter": {"status": "中性(Neutral)"}, + "Saturn": {"status": "中性(Neutral)"}, + }, + }, + "varga_full": { + "D10_Dasamsa": {"summary": "career varga present"}, + "D9_Navamsha": {"summary": "relationship varga present"}, + "D2_Hora": {"summary": "wealth varga present"}, + "D11_Rudramsha": {"summary": "gains varga present"}, + }, + "special_lagnas": { + "A10_Karma_Pada": {"sign": "Capricorn", "lord": "Saturn"}, + "Upapada_Lagna": {"sign": "Libra", "lord": "Venus"}, + }, + "jaimini": { + "karakas": { + "Amatyakaraka": {"planet": "Mercury"}, + "Atmakaraka": {"planet": "Sun"}, + "Darakaraka": {"planet": "Venus"}, + }, + "karakamsha": {"karakamsha_sign": "Leo", "karakamsha_lord": "Sun"}, + }, + "dasha": {"current_dasha": {"mahadasha": "Mercury", "antardasha": "Sun"}}, + "narayana_dasha": {"current_dasha": {"sign": "Capricorn", "lord": "Saturn"}}, + "dasa_convergence": { + "domain_activations": { + "career_status": {"convergence_level": "L2", "probability": "35-50%"}, + "marriage_relationship": {"convergence_level": "L2", "probability": "35-50%"}, + "wealth_income": {"convergence_level": "L2", "probability": "35-50%"}, + } + }, + } + } + + +def test_core5_sources_are_wired_into_interpretation_source_pack() -> None: + source_pack = _existing_interpretation_source_pack() + + assert source_pack["core_rule_source_layer"]["status"] == "available" + assert source_pack["core_rule_source_layer"]["promotion_batch"] == "priority1_batch1_core5" + assert source_pack["core_rule_source_layer"]["source_refs"] == CORE5_SOURCE_REFS + for path in CORE5_SOURCE_REFS: + assert path in source_pack["source_refs"] + + inventory = source_pack["interpretation_source_inventory"] + assert inventory["layers"]["core_rule_sources"]["source_refs"] == CORE5_SOURCE_REFS + assert inventory["layers"]["core_rule_sources"]["promotion_status"] == "primary_truth_candidate" + + +def test_core5_sources_are_visible_to_all_strict_fortune_workflows() -> None: + for route in ["career", "relationship", "finance"]: + strict = _collect_strict_evidence(route, _base_modules()) + source_pack = strict["present_evidence"]["interpretation_source_pack"] + audit = strict["technique_audit_summary"]["interpretation_source_pack"] + + assert source_pack["core_rule_source_layer"]["source_refs"] == CORE5_SOURCE_REFS + assert audit["core_rule_source_refs"] == CORE5_SOURCE_REFS + assert audit["used"] is True + for path in CORE5_SOURCE_REFS: + assert path in audit["source_refs"] diff --git a/tests/test_interpretation_source_inventory_gate.py b/tests/test_interpretation_source_inventory_gate.py index 08dd8e0a..c4ccdf9e 100644 --- a/tests/test_interpretation_source_inventory_gate.py +++ b/tests/test_interpretation_source_inventory_gate.py @@ -43,6 +43,14 @@ def test_interpretation_source_inventory_gate_reports_layered_source_pack() -> N assert "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-reader/resources/validation_rules.md" in layers["reader_validation"]["source_refs"] assert "references/yoga_rules.json" in layers["yoga_rules"]["source_refs"] assert "references/saham_rules.json" in layers["saham_rules"]["source_refs"] + assert layers["core_rule_sources"]["promotion_batch"] == "priority1_batch1_core5" + assert layers["core_rule_sources"]["source_refs"] == [ + "references/prediction-boundary-protocol.md", + "references/event_judgment_skeleton.md", + "references/planetary-dignity-complete-reference.md", + "references/retrograde-combustion-war-guide.md", + "references/transit-multi-reference-guide.md", + ] draft_refs = layers["quarantined_drafts"]["source_refs"] source_refs = set(report["runtime_source_refs"])