diff --git a/findings.md b/findings.md index 264c6390..6ef21450 100644 --- a/findings.md +++ b/findings.md @@ -202,3 +202,14 @@ - 2026-06-30 轻量映射误判修复:`Dashamamsha` 等分盘名称曾因包含 `dasha` 字符串被误归入 timing。当前已改为按方法词元识别 `Dasa/Dasha` timing 方法,真实轻扫显示 `AllPlanetDashamamshaSign` 归入 `career/marriage/wealth`,不再进入 `timing`。 - 2026-06-30 VedAstro 动态能力选择器结论:系统现在不只知道 641 项目录和主题归类,还会按用户主题生成 `dynamic_selection` 与 `official_report_references`。每个主题会列出自动可用能力、需要额外资料能力、blocked 能力和 `vedastro::` 引用 ID,供网页、Skill、MCP 和 Codex prompt pack 指向同一份官方证据层。 - 2026-06-30 报告引用边界:`official_report_references` 是证据引用层,不等于每个引用都已执行成功。`execution_policy != auto` 或 `status != ok` 的能力只能作为“需要补资料/当前阻断”的报告说明,不得包装成已用于最终断语的数据。 + +## 2026-07-02 解释资料层调用链审计前置结论 + +- 用户要求在补“调用链显式接入 + 测试”前,先地毯式检查当前项目、历史工作区、技能副本、资料库、Downloads/Desktop 和云端 Git refs,确认是否因不同应用/窗口遗漏资料碎片。 +- 当前主仓内已经存在截图所示“行星落十二宫”前端资料层:`jyotish-app/planet-house-details-a.js`、`planet-house-details-b.js`、`planet-house-details-c.js`;与 `.workbuddy/skills/jyotish-vedic-astrology` 旧副本 SHA256 完全一致。 +- 当前主仓内已有文章级解释模板注册表:`references/interpretation_template_registry.json`,`scripts/validate_interpretation_templates.py --format json` 返回 `valid=true`、`template_count=11`、`problem_count=0`。 +- 当前主仓内已有 P1-P12 与宫位框架资料层:`references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/p1_p12.md` 与 `house_framework.md`;它们包含宫主身份、凶宫主大运禁止美化、Dasha 事件模板、VRY 孤立性、SAV/BAV 交叉等严格解读规则。 +- 当前主仓内已有 Raman/BPHS 层:`references/raman-house-judgment-methodology.md`、`references/bphs-ch48-narayana-dasha.md`、`references/yoga_rules.json`、`scripts/validate_bphs_invariants.py`;更完整书籍 PDF 位于资料库路径 `/Users/wuyongnaren/文件仓库/中外🔮占星/国外占星/印度占星书/`。 +- `python3 scripts/audit_capabilities.py --mode validate` 通过,显示 `technique_count=89`、`problem_count=0`;`python3 scripts/audit_fragments.py --strict` 通过,显示当前仓 `candidate_count=0`、`untracked_count=0`。 +- 云端 HTTPS refs 已确认:本地 `codex/release-hygiene-ci@767a5c6` 与远端 `refs/heads/codex/release-hygiene-ci@767a5c6` 对齐。 +- 根因不是“项目没有资料”,而是现有测试多守文档/注册表存在性,没有守 `mcp_server.py::_collect_strict_evidence`、AI prompt pack 和用户可见 strict contract 必须显式携带这些资料层。下一步应只补显式调用链与测试,不重写规则体系。 diff --git a/mcp_server.py b/mcp_server.py index f2176fd3..fd46eb91 100644 --- a/mcp_server.py +++ b/mcp_server.py @@ -32,6 +32,7 @@ import subprocess import asyncio from copy import deepcopy from datetime import datetime, timedelta +from functools import lru_cache from typing import Dict, Any, Optional, List # Add scripts dir to path so imports work @@ -105,6 +106,102 @@ def _audit_status() -> Dict[str, Any]: return {"valid": False, "raw": result.stdout} +def _repo_relative_exists(path: str) -> bool: + return os.path.exists(os.path.join(SCRIPT_DIR, path)) + + +def _load_json_file(path: str) -> Dict[str, Any]: + with open(os.path.join(SCRIPT_DIR, path), "r", encoding="utf-8") as handle: + data = json.load(handle) + return data if isinstance(data, dict) else {} + + +@lru_cache(maxsize=1) +def _existing_interpretation_source_pack() -> Dict[str, Any]: + """Return the existing repo interpretation/source layers as an explicit evidence pack.""" + template_path = "references/interpretation_template_registry.json" + p1_p12_path = "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/p1_p12.md" + house_framework_path = "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/house_framework.md" + raman_path = "references/raman-house-judgment-methodology.md" + 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" + planet_house_paths = [ + "jyotish-app/planet-house-details-a.js", + "jyotish-app/planet-house-details-b.js", + "jyotish-app/planet-house-details-c.js", + ] + + template_ids: List[str] = [] + template_count = 0 + try: + registry = _load_json_file(template_path) + templates = registry.get("templates") if isinstance(registry.get("templates"), dict) else {} + template_ids = sorted(templates.keys()) + template_count = len(template_ids) + except Exception: + template_ids = [] + template_count = 0 + + source_refs = [ + template_path, + p1_p12_path, + house_framework_path, + raman_path, + bphs_narayana_path, + mevg_path, + real_case_checklist_path, + *planet_house_paths, + ] + missing_refs = [path for path in source_refs if not _repo_relative_exists(path)] + return { + "status": "used" if not missing_refs else "partial", + "source": "repo_existing_interpretation_sources", + "source_refs": source_refs, + "missing_refs": missing_refs, + "template_registry": { + "path": template_path, + "template_count": template_count, + "template_ids": template_ids, + }, + "frameworks": [ + "p1_p12", + "house_framework", + "raman_functional_house_judgment", + "bphs_narayana_dasha", + "mevg_mandatory_external_verification", + "real_case_quality_checklist", + ], + "bphs_raman_layer": { + "status": "available" if _repo_relative_exists(raman_path) and _repo_relative_exists(bphs_narayana_path) else "partial", + "source_refs": [raman_path, bphs_narayana_path], + }, + "frontend_planet_house_details": { + "status": "available" if all(_repo_relative_exists(path) for path in planet_house_paths) else "partial", + "coverage": "9_planets_x_12_houses", + "planet_count": 9, + "house_count": 12, + "source_refs": planet_house_paths, + }, + "mevg_gate": { + "status": "blocked", + "required": True, + "source_ref": mevg_path, + "effect_on_confidence": "blocks_or_downgrades_interpretive_claims_until_completed", + }, + "real_case_calibration": { + "status": "blocked", + "required": True, + "source_ref": real_case_checklist_path, + "effect_on_confidence": "caps_confidence_without_matching_cases", + }, + "boundary": ( + "This pack exposes existing local interpretation sources. It does not replace live MEVG web " + "collection, real-case calibration, chart calculation, or oracle closure." + ), + } + + def _execute_mcp_consultation_workflow( *, question: str, @@ -2222,6 +2319,15 @@ def _build_technique_audit_summary(route: str, strict: Dict[str, Any]) -> Dict[s varga_keys = _route_varga_gate_keys(route) functional_layer = present.get("functional_benefic_malefic") + interpretation_source_pack = present.get("interpretation_source_pack") + if not isinstance(interpretation_source_pack, dict): + interpretation_source_pack = {} + mevg_gate = interpretation_source_pack.get("mevg_gate") if isinstance(interpretation_source_pack.get("mevg_gate"), dict) else {} + real_case_calibration = ( + interpretation_source_pack.get("real_case_calibration") + if isinstance(interpretation_source_pack.get("real_case_calibration"), dict) + else {} + ) return { "functional_benefic_malefic": { "gate": "hard", @@ -2233,6 +2339,37 @@ def _build_technique_audit_summary(route: str, strict: Dict[str, Any]) -> Dict[s else "Functional benefic/malefic layer unavailable." ), }, + "interpretation_source_pack": { + "gate": "hard", + "used": bool(interpretation_source_pack.get("status") in {"used", "partial"}), + "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 [], + "missing_refs": interpretation_source_pack.get("missing_refs") or [], + "effect_on_confidence": ( + "uses existing BPHS/Raman/frontend/template source layers; missing refs lower confidence" + ), + }, + "mevg_global_web_evidence": { + "gate": "hard", + "required": True, + "status": mevg_gate.get("status") or "blocked", + "source_ref": mevg_gate.get("source_ref") or "references/mandatory-verification-gate-protocol.md", + "effect_on_confidence": ( + mevg_gate.get("effect_on_confidence") + or "blocks_or_downgrades_interpretive_claims_until_completed" + ), + }, + "real_case_calibration": { + "gate": "hard", + "required": True, + "status": real_case_calibration.get("status") or "blocked", + "source_ref": real_case_calibration.get("source_ref") or "references/real-reading-quality-checklist.md", + "effect_on_confidence": ( + real_case_calibration.get("effect_on_confidence") + or "caps_confidence_without_matching_cases" + ), + }, "relevant_vargas": { "gate": "hard", "required_keys": varga_keys, @@ -2523,8 +2660,9 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An present["chart"] = _safe_get(modules, "chart") present["dignity_guardrail"] = _derive_dignity_guardrail(route, present) present["functional_benefic_malefic"] = _derive_functional_benefic_malefic(modules) + present["interpretation_source_pack"] = _existing_interpretation_source_pack() missing = [key for key, value in present.items() if key not in { - "chart", "external_activation", "external_technique_evidence", "vedastro_official_snapshot", "source_priority", "dignity_guardrail", "argala_support", "shadbala", "shadbala_component_audit", "kakshya_career_support", "functional_benefic_malefic" + "chart", "external_activation", "external_technique_evidence", "vedastro_official_snapshot", "source_priority", "dignity_guardrail", "argala_support", "shadbala", "shadbala_component_audit", "kakshya_career_support", "functional_benefic_malefic", "interpretation_source_pack" } and value in (None, {}, [], "")] convergence = present["career_convergence"] or {} confidence_cap = "medium" @@ -2605,9 +2743,10 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An present["source_priority"] = modules.get("source_priority") if isinstance(modules.get("source_priority"), dict) else {} present["dignity_guardrail"] = _derive_dignity_guardrail(route, present) present["functional_benefic_malefic"] = _derive_functional_benefic_malefic(modules) + present["interpretation_source_pack"] = _existing_interpretation_source_pack() missing = [ key for key, value in present.items() - if key not in {"chart", "external_activation", "external_technique_evidence", "vedastro_official_snapshot", "source_priority", "dignity_guardrail", "jaimini_marriage_support", "jaimini_timing_support", "synastry_relationship_support", "argala_support", "shadbala", "shadbala_component_audit", "functional_benefic_malefic"} + if key not in {"chart", "external_activation", "external_technique_evidence", "vedastro_official_snapshot", "source_priority", "dignity_guardrail", "jaimini_marriage_support", "jaimini_timing_support", "synastry_relationship_support", "argala_support", "shadbala", "shadbala_component_audit", "functional_benefic_malefic", "interpretation_source_pack"} and value in (None, {}, [], "") ] convergence = present["marriage_convergence"] or {} @@ -2699,8 +2838,9 @@ def _collect_strict_evidence(route: str, result: Dict[str, Any]) -> Dict[str, An present["source_priority"] = modules.get("source_priority") if isinstance(modules.get("source_priority"), dict) else {} present["dignity_guardrail"] = _derive_dignity_guardrail(route, present) present["functional_benefic_malefic"] = _derive_functional_benefic_malefic(modules) + present["interpretation_source_pack"] = _existing_interpretation_source_pack() missing = [key for key, value in present.items() if key not in { - "chart", "external_activation", "external_technique_evidence", "vedastro_official_snapshot", "source_priority", "dignity_guardrail", "gains_convergence", "career_convergence", "avayogi_risk", "ashtakavarga_finance_support", "shadbala_component_audit", "asc_sign", "pav_finance_support", "sodhita_finance_support", "kakshya_finance_support", "functional_benefic_malefic" + "chart", "external_activation", "external_technique_evidence", "vedastro_official_snapshot", "source_priority", "dignity_guardrail", "gains_convergence", "career_convergence", "avayogi_risk", "ashtakavarga_finance_support", "shadbala_component_audit", "asc_sign", "pav_finance_support", "sodhita_finance_support", "kakshya_finance_support", "functional_benefic_malefic", "interpretation_source_pack" } and value in (None, {}, [], "")] convergence_hits: List[Dict[str, Any]] = [ item for item in [ diff --git a/progress.md b/progress.md index 6d582e76..62a9bec4 100644 --- a/progress.md +++ b/progress.md @@ -724,3 +724,17 @@ - 新增治理守门:`tests/test_research_governance_docs.py` 检查第四批 pack 的关键锚点,`tests/test_preflight_fragment_scan.py` 检查第四批 5 份草稿不再出现在 high-value unpromoted pool。 - TDD 红灯确认:第四批 pack 缺失时治理测试失败,preflight 仍列出第四批草稿;补齐后两条测试通过。 - `python3 scripts/preflight_fragment_scan.py` 当前显示 `high_value_unpromoted_count=16`,已从第三批后的 `21` 下降 5 项;剩余主要是 skill/cloud sync 草稿和 Gemini recovery-only VedAstro artifacts。 + +## 2026-07-02T11:26:34+08:00 - 解释资料层调用链审计启动 + +- 按用户要求,在任何实现前先做只读地毯式探索:读取 `AGENTS.md`、`SKILL.md`、`task_plan.md`、`findings.md`、`progress.md`、strict router、MEVG、event skeleton、解释模板注册表、P1-P12、house framework 与现有 strict workflow 代码。 +- 当前主仓验证:`validate_interpretation_templates.py --format json` 通过;`audit_capabilities.py --mode validate` 通过;`audit_fragments.py --strict` 通过。 +- 跨目录验证:当前主仓和 `.workbuddy/skills/jyotish-vedic-astrology` 的 `planet-house-details-a/b/c.js` SHA256 一致;资料库中存在 BPHS/Raman PDF;云端 HTTPS refs 显示本地与远端 `codex/release-hygiene-ci` HEAD 对齐。 +- 根因假设冻结:资料和规则本来存在,但 strict workflow / prompt pack 缺少“解释资料源包 + MEVG/真实案例门控行”的显式 evidence contract 与红灯测试;下一步按 TDD 只补调用链和测试。 + +## 2026-07-02T11:31:43+08:00 - 解释资料层显式调用链接入 + +- TDD 红灯:新增 career/relationship/finance 三条 strict workflow 测试,均因 `present_evidence.interpretation_source_pack` 缺失失败;新增 CLI prompt pack 检索文档断言,因未列出解释资料层失败。 +- 最小实现:`mcp_server.py` 新增 `_existing_interpretation_source_pack()`,把现有 `interpretation_template_registry`、P1-P12、house framework、Raman/BPHS、MEVG、真实案例 checklist、前端 planet-house-details 作为只读 evidence pack 挂入 career/relationship/finance strict workflow;`technique_audit_summary` 新增 `interpretation_source_pack`、`mevg_global_web_evidence`、`real_case_calibration` 三行。 +- Prompt pack:`scripts/jyotish_engine.py` 的 `technique_audit_table` 新增 `Interpretation Source Pack`、`MEVG / Global Web Evidence`、`Real Case Calibration`;`retrieval_plan.local_reference_docs` 显式列出对应本地资料路径。 +- 红绿验证:5 条新增/修改聚焦测试通过;随后 `tests/test_mcp_strict_workflow_career.py tests/test_mcp_strict_workflow_relationship.py tests/test_mcp_strict_workflow_finance.py tests/test_mcp_strict_workflow_functional_layer.py -q` 通过,合计 86 项;`validate_interpretation_templates.py --format json` 仍为 `valid=true`、`template_count=11`。 diff --git a/scripts/jyotish_engine.py b/scripts/jyotish_engine.py index a672a405..53461aca 100644 --- a/scripts/jyotish_engine.py +++ b/scripts/jyotish_engine.py @@ -951,6 +951,28 @@ def _build_technique_audit_table(functional_layer, oracle_progress, modules): f"production_tuning_allowed={oracle_progress.get('production_tuning_allowed', False)}。" ), }, + { + 'technique': 'Interpretation Source Pack', + 'status': 'used', + 'source': 'repo_existing_interpretation_sources', + 'note': ( + '已显式索引 interpretation_template_registry、P1-P12、house_framework、' + 'Raman/BPHS 与前端 planet-house-details;这些资料只作为本地解释源,' + '不替代 MEVG 外部采集和真实案例校正。' + ), + }, + { + 'technique': 'MEVG / Global Web Evidence', + 'status': 'blocked', + 'source': 'references/mandatory-verification-gate-protocol.md', + 'note': '所有星盘运势/推运解释必须执行全球/全网外部资料采集;未执行时解释声明需降级。', + }, + { + 'technique': 'Real Case Calibration', + 'status': 'blocked', + 'source': 'references/real-reading-quality-checklist.md', + 'note': '所有星盘运势/推运解释必须参考真实案例或公开 benchmark;无匹配案例时置信度封顶。', + }, ] rows.append({ @@ -1653,6 +1675,15 @@ def _build_ai_prompt_pack(report): 'references/dasa-convergence-methodology.md', 'references/shadbala-interpretation-methodology.md', 'references/navamsa-d9-interpretation-template.md', + 'references/interpretation_template_registry.json', + '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', + 'references/raman-house-judgment-methodology.md', + 'references/mandatory-verification-gate-protocol.md', + 'references/real-reading-quality-checklist.md', + 'jyotish-app/planet-house-details-a.js', + 'jyotish-app/planet-house-details-b.js', + 'jyotish-app/planet-house-details-c.js', ], 'retrieval_tags': [ 'no_single_factor_conclusion', @@ -1660,6 +1691,9 @@ def _build_ai_prompt_pack(report): 'oracle_boundary_visible', 'external_oracle_evidence_validation', 'confidence_labeled_reading', + 'interpretation_source_pack', + 'mevg_global_web_evidence_required', + 'real_case_calibration_required', ], }, } diff --git a/tests/test_cli_smoke.py b/tests/test_cli_smoke.py index 50abafc9..d455980f 100644 --- a/tests/test_cli_smoke.py +++ b/tests/test_cli_smoke.py @@ -266,6 +266,10 @@ def test_full_reading_reports_ayanamsa_metadata_and_ai_prompt_pack() -> None: assert "Raman" in prompt_pack["prompt_zh"] assert "不要仅凭单一配置下结论" in prompt_pack["prompt_zh"] assert "references/ai-reading-workflow-prompt.md" in prompt_pack["retrieval_plan"]["local_reference_docs"] + assert "references/interpretation_template_registry.json" in prompt_pack["retrieval_plan"]["local_reference_docs"] + assert "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/p1_p12.md" in prompt_pack["retrieval_plan"]["local_reference_docs"] + assert "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/house_framework.md" in prompt_pack["retrieval_plan"]["local_reference_docs"] + assert "references/mandatory-verification-gate-protocol.md" in prompt_pack["retrieval_plan"]["local_reference_docs"] assert prompt_pack["evidence_snapshot"]["ayanamsa"]["name"] == "raman" assert prompt_pack["evidence_snapshot"]["core"]["ascendant"]["sign"] == result["chart"]["ascendant"]["sign"] timing = prompt_pack["evidence_snapshot"]["timing"] @@ -279,6 +283,9 @@ def test_full_reading_reports_ayanamsa_metadata_and_ai_prompt_pack() -> None: assert isinstance(functional["functional_malefics"], list) audit_table = prompt_pack["evidence_snapshot"]["technique_audit_table"] assert isinstance(audit_table, list) + assert any(row["technique"] == "MEVG / Global Web Evidence" for row in audit_table) + assert any(row["technique"] == "Real Case Calibration" for row in audit_table) + assert any(row["technique"] == "Interpretation Source Pack" for row in audit_table) functional_rows = [row for row in audit_table if row["technique"] == "Functional Benefic/Malefic"] assert functional_rows assert functional_rows[0]["status"] == "used" @@ -437,6 +444,9 @@ def test_full_reading_prompt_pack_carries_compact_technique_audit_summary() -> N career = result["ai_prompt_pack"]["evidence_snapshot"]["strict_workflow_contracts"]["career"] assert "technique_audit_summary" in career assert career["technique_audit_summary"]["functional_benefic_malefic"]["gate"] == "hard" + assert career["technique_audit_summary"]["interpretation_source_pack"]["used"] is True + assert career["technique_audit_summary"]["mevg_global_web_evidence"]["status"] == "blocked" + assert career["technique_audit_summary"]["real_case_calibration"]["status"] == "blocked" assert "audit_gate_frame" in career["multi_reference_reading_summary"] diff --git a/tests/test_mcp_strict_workflow_career.py b/tests/test_mcp_strict_workflow_career.py index c088804b..ddd7aaf6 100644 --- a/tests/test_mcp_strict_workflow_career.py +++ b/tests/test_mcp_strict_workflow_career.py @@ -72,6 +72,26 @@ def test_career_collects_a10_amk_karakamsha_as_strict_evidence() -> None: ] +def test_career_strict_contract_attaches_existing_interpretation_source_pack() -> None: + strict = _collect_strict_evidence("career", _base_career_result()) + + source_pack = strict["present_evidence"]["interpretation_source_pack"] + assert source_pack["status"] == "used" + assert "references/interpretation_template_registry.json" in source_pack["source_refs"] + assert "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/p1_p12.md" in source_pack["source_refs"] + assert "references/open_source_sources/vedic-astro-skills/codex/skills/vedic-core/resources/house_framework.md" in source_pack["source_refs"] + assert "references/raman-house-judgment-methodology.md" in source_pack["source_refs"] + assert "jyotish-app/planet-house-details-a.js" in source_pack["source_refs"] + assert source_pack["template_registry"]["template_count"] >= 11 + assert source_pack["frontend_planet_house_details"]["planet_count"] == 9 + assert source_pack["frontend_planet_house_details"]["house_count"] == 12 + + audit = strict["technique_audit_summary"] + assert audit["interpretation_source_pack"]["used"] is True + assert audit["mevg_global_web_evidence"]["status"] == "blocked" + assert audit["real_case_calibration"]["status"] == "blocked" + + def test_career_blocks_label_when_d10_is_missing_but_preserves_jaimini_context() -> None: result = _base_career_result() del result["modules"]["varga_full"]["D10_Dasamsa"] diff --git a/tests/test_mcp_strict_workflow_finance.py b/tests/test_mcp_strict_workflow_finance.py index f33f18ae..a467bdbe 100644 --- a/tests/test_mcp_strict_workflow_finance.py +++ b/tests/test_mcp_strict_workflow_finance.py @@ -34,6 +34,22 @@ def test_finance_public_wealth_label_requires_at_least_moderate_window() -> None assert judgement["secondary_context"] == [] +def test_finance_strict_contract_attaches_existing_interpretation_source_pack() -> None: + strict = _collect_strict_evidence("finance", {"modules": {}}) + + source_pack = strict["present_evidence"]["interpretation_source_pack"] + assert source_pack["status"] == "used" + assert "lakshmi_dhana_activation_chain" in source_pack["template_registry"]["template_ids"] + assert "yogi_asc_tight_orb_wealth" in source_pack["template_registry"]["template_ids"] + assert source_pack["bphs_raman_layer"]["status"] == "available" + assert source_pack["frontend_planet_house_details"]["coverage"] == "9_planets_x_12_houses" + + audit = strict["technique_audit_summary"] + assert audit["interpretation_source_pack"]["used"] is True + assert audit["mevg_global_web_evidence"]["effect_on_confidence"] == "blocks_or_downgrades_interpretive_claims_until_completed" + assert audit["real_case_calibration"]["effect_on_confidence"] == "caps_confidence_without_matching_cases" + + def test_finance_public_wealth_label_can_lift_visible_wealth_cases() -> None: judgement = _derive_event_judgement( "finance", diff --git a/tests/test_mcp_strict_workflow_relationship.py b/tests/test_mcp_strict_workflow_relationship.py index 3fb5c94c..bd9ba09e 100644 --- a/tests/test_mcp_strict_workflow_relationship.py +++ b/tests/test_mcp_strict_workflow_relationship.py @@ -62,6 +62,23 @@ def test_relationship_jaimini_bridge_lifts_legal_marriage_label() -> None: ] +def test_relationship_strict_contract_attaches_existing_interpretation_source_pack() -> None: + strict = _collect_strict_evidence("relationship", _base_relationship_result()) + + source_pack = strict["present_evidence"]["interpretation_source_pack"] + assert source_pack["status"] == "used" + assert "darakaraka_ul_spouse_depth" in source_pack["template_registry"]["template_ids"] + assert "rtn_high_order_d9" in source_pack["template_registry"]["template_ids"] + assert "p1_p12" in source_pack["frameworks"] + assert "house_framework" in source_pack["frameworks"] + assert "raman_functional_house_judgment" in source_pack["frameworks"] + + audit = strict["technique_audit_summary"] + assert audit["interpretation_source_pack"]["source"] == "repo_existing_interpretation_sources" + assert audit["mevg_global_web_evidence"]["required"] is True + assert audit["real_case_calibration"]["required"] is True + + def test_relationship_jaimini_bridge_stays_context_only_when_d9_missing() -> None: result = _base_relationship_result() del result["modules"]["varga_full"]["D9_Navamsa"]