Add domain invocation governance contracts
This commit is contained in:
@@ -1274,6 +1274,7 @@ function renderAIPromptPackPanel(cd) {
|
||||
</div>
|
||||
` : ''}
|
||||
${renderStrictWorkflowContractPanel(vedastroOfficial)}
|
||||
${renderInterpretationSourceGovernancePanel(evidence)}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ai-prompt-pack-foot">
|
||||
@@ -1412,6 +1413,34 @@ function renderStrictWorkflowContractCard(route, contract = {}, isPrimary = fals
|
||||
`;
|
||||
}
|
||||
|
||||
function renderInterpretationSourceGovernancePanel(evidence = {}) {
|
||||
const sourcePack = evidence.interpretation_source_pack || {};
|
||||
const boundary = evidence.prediction_boundary_contract || {};
|
||||
const mevg = evidence.mevg_collection_queue || {};
|
||||
const cases = evidence.real_case_calibration_layer || {};
|
||||
const debt = evidence.technical_debt_contract || {};
|
||||
const remaining = evidence.remaining_priority1_batch_queue || {};
|
||||
const coreRefs = sourcePack.core_rule_source_refs || [];
|
||||
const referenceOnly = sourcePack.reference_only_source_refs || [];
|
||||
const blockedPolicy = boundary.confidence_boundary?.unverified_claim_policy || 'downgrade_or_block';
|
||||
return `
|
||||
<div class="ai-prompt-pack-contracts">
|
||||
<h4>Source Governance</h4>
|
||||
<div class="ai-prompt-pack-contract-grid">
|
||||
<span>core sources: ${escapeHtml(coreRefs.length ? String(coreRefs.length) : 'none')}</span>
|
||||
<span>reference-only: ${escapeHtml(referenceOnly.length ? String(referenceOnly.length) : 'none')}</span>
|
||||
<span>blocked non-runtime: duplicate / obsolete / quarantine</span>
|
||||
<span>confidence downgrade: ${escapeHtml(blockedPolicy)}</span>
|
||||
<span>MEVG queue: ${escapeHtml(mevg.status || 'blocked')}</span>
|
||||
<span>case calibration: ${escapeHtml(cases.status || 'blocked')}</span>
|
||||
<span>Narayana debt: ${escapeHtml(debt.narayana?.status || 'unknown')}</span>
|
||||
<span>Tajika debt: ${escapeHtml(debt.tajika?.status || 'unknown')}</span>
|
||||
<span>next batches: ${escapeHtml((remaining.next_batches || []).join(' / ') || 'none')}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderVedAstroOverviewPromptCard(overview = {}) {
|
||||
if (!overview || typeof overview !== 'object') return '';
|
||||
const status = overview.status || 'blocked';
|
||||
|
||||
+159
@@ -142,6 +142,29 @@ PROMOTE_BATCH2_TOPIC_SOURCE_REFS = [
|
||||
"references/condition-dasha-complete.md",
|
||||
]
|
||||
|
||||
DASHA_TIMING_SOURCE_REFS = [
|
||||
"references/vimshottari_dasha_guide.md",
|
||||
"references/pratyantar-calculation-guide.md",
|
||||
"references/condition-dasha-complete.md",
|
||||
]
|
||||
|
||||
VARGA_STRENGTH_SOURCE_REFS = [
|
||||
"references/divisional-chart-deep-reading.md",
|
||||
"references/shadbala-complete-methodology.md",
|
||||
"references/ashtakavarga-complete-system.md",
|
||||
]
|
||||
|
||||
ANNUAL_SPECIAL_SOURCE_REFS = [
|
||||
"references/tajika-yoga-complete-guide.md",
|
||||
"references/jaimini-complete-system.md",
|
||||
"references/kp-astrology-complete-system.md",
|
||||
]
|
||||
|
||||
MODIFIER_OBSTACLE_SOURCE_REFS = [
|
||||
"references/argala-complete-guide.md",
|
||||
"references/badhaka-obstacle-planet-guide.md",
|
||||
]
|
||||
|
||||
REFERENCE_ONLY_CONFLICT_SOURCE_REFS = [
|
||||
"references/dasa-convergence-methodology.md",
|
||||
"references/multi-dasha-convergence-protocol.md",
|
||||
@@ -159,6 +182,42 @@ BLOCKED_NON_RUNTIME_SOURCE_REFS = [
|
||||
"references/consultation-case-library.md",
|
||||
]
|
||||
|
||||
REMAINING_PRIORITY1_BATCH_QUEUE = [
|
||||
"real_case_studies_batch1",
|
||||
"rishi_ai_mcp_batch1",
|
||||
"vedic_astro_skills_batch1",
|
||||
"references_batch2",
|
||||
]
|
||||
|
||||
|
||||
def _domain_invocation_layers() -> Dict[str, Any]:
|
||||
return {
|
||||
"dasha_timing": {
|
||||
"status": "available",
|
||||
"source_refs": DASHA_TIMING_SOURCE_REFS,
|
||||
"required_in_routes": ["career", "relationship", "finance"],
|
||||
"contract": "timing must cite Vimshottari/Narayana cross-check and sub-period boundaries when used.",
|
||||
},
|
||||
"varga_strength": {
|
||||
"status": "available",
|
||||
"source_refs": VARGA_STRENGTH_SOURCE_REFS,
|
||||
"required_in_routes": ["career", "relationship", "finance"],
|
||||
"contract": "domain conclusions must include relevant varga and strength/ashtakavarga boundaries.",
|
||||
},
|
||||
"annual_special": {
|
||||
"status": "available",
|
||||
"source_refs": ANNUAL_SPECIAL_SOURCE_REFS,
|
||||
"required_in_routes": ["career", "relationship", "finance"],
|
||||
"contract": "annual/special systems are supporting layers until oracle parity is closed.",
|
||||
},
|
||||
"modifier_obstacle": {
|
||||
"status": "available",
|
||||
"source_refs": MODIFIER_OBSTACLE_SOURCE_REFS,
|
||||
"required_in_routes": ["career", "relationship", "finance"],
|
||||
"contract": "Argala and Badhaka are modifiers/obstacle indicators, not standalone event guarantees.",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str, Any]:
|
||||
primary_truth = [
|
||||
@@ -440,6 +499,12 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]:
|
||||
"promotion_status": "not_truth_source",
|
||||
"boundary": "Duplicate, obsolete, and quarantined files are deliberately excluded from runtime source_refs.",
|
||||
},
|
||||
"domain_invocation_layers": _domain_invocation_layers(),
|
||||
"remaining_priority1_batch_queue": {
|
||||
"status": "queued",
|
||||
"next_batches": REMAINING_PRIORITY1_BATCH_QUEUE,
|
||||
"boundary": "Future batches remain audit-only until classified and tested.",
|
||||
},
|
||||
"frontend_interpretation_layer": {
|
||||
"status": "available" if all(_repo_relative_exists(path) for path in frontend_interpretation_paths) else "partial",
|
||||
"source_refs": frontend_interpretation_paths,
|
||||
@@ -2783,6 +2848,94 @@ def _build_prediction_boundary_contract(route: str, strict: Dict[str, Any]) -> D
|
||||
}
|
||||
|
||||
|
||||
def _build_domain_invocation_contract(route: str, strict: Dict[str, Any]) -> Dict[str, Any]:
|
||||
layers = _domain_invocation_layers()
|
||||
return {
|
||||
key: {
|
||||
**value,
|
||||
"route": route,
|
||||
"used": True,
|
||||
}
|
||||
for key, value in layers.items()
|
||||
}
|
||||
|
||||
|
||||
def _build_output_template_contract(route: str, strict: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {
|
||||
"status": "used",
|
||||
"route": route,
|
||||
"language": "zh",
|
||||
"required_sections": ["promise", "activation", "manifestation", "label", "confidence_boundary"],
|
||||
"golden_test_status": "required",
|
||||
"source_refs": [
|
||||
"references/prediction-boundary-protocol.md",
|
||||
"references/event_judgment_skeleton.md",
|
||||
],
|
||||
"instruction": "Final Chinese fortune output must map claims to promise/activation/manifestation/label and show confidence boundaries.",
|
||||
}
|
||||
|
||||
|
||||
def _build_mevg_collection_queue(route: str, strict: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {
|
||||
"status": "queued",
|
||||
"trigger": "fortune_question_strict_workflow",
|
||||
"route": route,
|
||||
"required_jobs": [
|
||||
"global_web_evidence",
|
||||
"real_case_reference_search",
|
||||
"source_grading",
|
||||
"conflict_arbitration",
|
||||
"unverified_claim_downgrade",
|
||||
],
|
||||
"cache_policy": "reuse_official_snapshot_and_external_evidence_cache_before_live_fetch",
|
||||
"source_ref": "references/mandatory-verification-gate-protocol.md",
|
||||
}
|
||||
|
||||
|
||||
def _build_real_case_calibration_layer(route: str, strict: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {
|
||||
"status": "queued",
|
||||
"route": route,
|
||||
"domain_buckets": ["career", "finance", "relationship", "health", "rectification", "timing"],
|
||||
"source_roots": ["references/real_case_studies", "docs/benchmark"],
|
||||
"retrieval_policy": "domain_bucket_first_then_case_quality_gate",
|
||||
"confidence_effect": "caps_confidence_until_matching_cases_are_attached",
|
||||
}
|
||||
|
||||
|
||||
def _build_technical_debt_contract(route: str, strict: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {
|
||||
"status": "tracked",
|
||||
"route": route,
|
||||
"narayana": {
|
||||
"status": "partial",
|
||||
"source_refs": ["references/bphs-ch48-narayana-dasha.md", "references/condition-dasha-complete.md"],
|
||||
"open_items": [
|
||||
"antardasha_pratyantar_oracle_parity",
|
||||
"subperiod_boundary_regression",
|
||||
"external_engine_crosscheck",
|
||||
],
|
||||
},
|
||||
"tajika": {
|
||||
"status": "partial",
|
||||
"source_refs": ["references/tajika-yoga-complete-guide.md"],
|
||||
"open_items": [
|
||||
"solar_return_precision",
|
||||
"muntha_placeholder_audit",
|
||||
"annual_yoga_oracle_parity",
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _build_remaining_priority1_batch_queue() -> Dict[str, Any]:
|
||||
return {
|
||||
"status": "queued",
|
||||
"next_batches": REMAINING_PRIORITY1_BATCH_QUEUE,
|
||||
"boundary": "Do not promote remaining priority_1 materials without batch audit and tests.",
|
||||
}
|
||||
|
||||
|
||||
def _build_multi_reference_reading_summary(route: str, present: Dict[str, Any], strict: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {
|
||||
"root_frame": _summary_root_frame(route, present),
|
||||
@@ -2809,6 +2962,12 @@ def _attach_top_reader_contract(route: str, strict: Dict[str, Any]) -> Dict[str,
|
||||
strict["technique_audit_summary"] = _build_technique_audit_summary(route, strict)
|
||||
strict["adjudication_stages"] = _build_adjudication_stages(route, present, event_judgement)
|
||||
strict["prediction_boundary_contract"] = _build_prediction_boundary_contract(route, strict)
|
||||
strict["domain_invocation_contract"] = _build_domain_invocation_contract(route, strict)
|
||||
strict["output_template_contract"] = _build_output_template_contract(route, strict)
|
||||
strict["mevg_collection_queue"] = _build_mevg_collection_queue(route, strict)
|
||||
strict["real_case_calibration_layer"] = _build_real_case_calibration_layer(route, strict)
|
||||
strict["technical_debt_contract"] = _build_technical_debt_contract(route, strict)
|
||||
strict["remaining_priority1_batch_queue"] = _build_remaining_priority1_batch_queue()
|
||||
strict["multi_reference_reading_summary"] = _build_multi_reference_reading_summary(route, present, strict)
|
||||
strict["official_day_signal_summary"] = _build_official_day_signal_summary(present.get("external_activation"))
|
||||
strict["monthly_adjudication_summary"] = _build_monthly_adjudication_summary(route, strict)
|
||||
|
||||
+10
@@ -777,3 +777,13 @@
|
||||
- duplicate / obsolete / quarantine 8 个文件已列入 `blocked_non_runtime_layer`,并由 inventory gate 检查不进入 runtime source refs;重点包括 `kp-practical-event-timing.md` 与 `consultation-case-library.md`。
|
||||
- Prompt Pack / API fallback / AI Chat 已同步 `prediction_boundary_contract`、核心 5、第二批 11、reference-only 3;AI Chat 上下文新增 `【Prediction Boundary Contract】` 段落。
|
||||
- 真实 full-reading 回归确认:REDACTED_DATE REDACTED_TIME REDACTED_PLACE矿区样例中 relationship / career / finance 三条 strict contract 均带 prediction boundary,且 MEVG 与真实案例校准仍为 blocked。
|
||||
|
||||
## 2026-07-02T16:12:00+08:00 - 第二批领域调用层与后续队列合同
|
||||
|
||||
- 第二批 11 个 promote 源头已拆成四个领域调用层:`dasha_timing`、`varga_strength`、`annual_special`、`modifier_obstacle`;career / relationship / finance strict workflow 均暴露 `domain_invocation_contract`。
|
||||
- 新增 `output_template_contract`,要求最终中文输出按 `promise / activation / manifestation / label / confidence_boundary` 组织;当前以合同和测试约束为主,后续可继续做 golden narrative snapshot。
|
||||
- 新增 `mevg_collection_queue`,fortune strict workflow 会生成外部采集队列合同:global web evidence、real case search、source grading、conflict arbitration、unverified downgrade。
|
||||
- 新增 `real_case_calibration_layer`,按 career / finance / relationship / health / rectification / timing 六个桶连接 `references/real_case_studies` 与 `docs/benchmark`。
|
||||
- 新增 `technical_debt_contract`,诚实标记 Narayana 与 Tajika 仍为 `partial`:Narayana 需 Antardasha/Pratyantar oracle parity,Tajika 需 solar return precision、Muntha placeholder audit 与 annual yoga oracle parity。
|
||||
- 前端 AI Prompt Pack 新增 `Source Governance` 面板,显示 core sources、reference-only、blocked non-runtime、confidence downgrade、MEVG queue、case calibration、Narayana/Tajika debt 与 next batches。
|
||||
- 剩余 priority_1 队列明确为:`real_case_studies_batch1`、`rishi_ai_mcp_batch1`、`vedic_astro_skills_batch1`、`references_batch2`。
|
||||
|
||||
@@ -3987,6 +3987,69 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
|
||||
'unverified_claim_policy': 'downgrade_or_block',
|
||||
},
|
||||
},
|
||||
'domain_invocation_layers': {
|
||||
'dasha_timing': {
|
||||
'status': 'fallback_prompt_pack_only',
|
||||
'source_refs': [
|
||||
'references/vimshottari_dasha_guide.md',
|
||||
'references/pratyantar-calculation-guide.md',
|
||||
'references/condition-dasha-complete.md',
|
||||
],
|
||||
},
|
||||
'varga_strength': {
|
||||
'status': 'fallback_prompt_pack_only',
|
||||
'source_refs': [
|
||||
'references/divisional-chart-deep-reading.md',
|
||||
'references/shadbala-complete-methodology.md',
|
||||
'references/ashtakavarga-complete-system.md',
|
||||
],
|
||||
},
|
||||
'annual_special': {
|
||||
'status': 'fallback_prompt_pack_only',
|
||||
'source_refs': [
|
||||
'references/tajika-yoga-complete-guide.md',
|
||||
'references/jaimini-complete-system.md',
|
||||
'references/kp-astrology-complete-system.md',
|
||||
],
|
||||
},
|
||||
'modifier_obstacle': {
|
||||
'status': 'fallback_prompt_pack_only',
|
||||
'source_refs': [
|
||||
'references/argala-complete-guide.md',
|
||||
'references/badhaka-obstacle-planet-guide.md',
|
||||
],
|
||||
},
|
||||
},
|
||||
'output_template_contract': {
|
||||
'status': 'fallback_prompt_pack_only',
|
||||
'language': 'zh',
|
||||
'required_sections': ['promise', 'activation', 'manifestation', 'label', 'confidence_boundary'],
|
||||
'golden_test_status': 'required',
|
||||
},
|
||||
'mevg_collection_queue': {
|
||||
'status': 'queued',
|
||||
'trigger': 'fortune_question_strict_workflow',
|
||||
'required_jobs': ['global_web_evidence', 'source_grading', 'conflict_arbitration'],
|
||||
},
|
||||
'real_case_calibration_layer': {
|
||||
'status': 'queued',
|
||||
'domain_buckets': ['career', 'finance', 'relationship', 'health', 'rectification', 'timing'],
|
||||
'source_roots': ['references/real_case_studies', 'docs/benchmark'],
|
||||
},
|
||||
'technical_debt_contract': {
|
||||
'status': 'tracked',
|
||||
'narayana': {'status': 'partial', 'open_items': ['antardasha_pratyantar_oracle_parity']},
|
||||
'tajika': {'status': 'partial', 'open_items': ['solar_return_precision', 'muntha_placeholder_audit']},
|
||||
},
|
||||
'remaining_priority1_batch_queue': {
|
||||
'status': 'queued',
|
||||
'next_batches': [
|
||||
'real_case_studies_batch1',
|
||||
'rishi_ai_mcp_batch1',
|
||||
'vedic_astro_skills_batch1',
|
||||
'references_batch2',
|
||||
],
|
||||
},
|
||||
'vedastro_official_full_snapshot': vedastro_official_full_snapshot,
|
||||
'vedastro_overview': vedastro_overview,
|
||||
'guided_topics': guided_topics,
|
||||
|
||||
@@ -1433,6 +1433,12 @@ def _compact_strict_workflow_contract(strict):
|
||||
'technique_audit_summary': strict.get('technique_audit_summary') or {},
|
||||
'adjudication_stages': strict.get('adjudication_stages') or {},
|
||||
'prediction_boundary_contract': strict.get('prediction_boundary_contract') or {},
|
||||
'domain_invocation_contract': strict.get('domain_invocation_contract') or {},
|
||||
'output_template_contract': strict.get('output_template_contract') or {},
|
||||
'mevg_collection_queue': strict.get('mevg_collection_queue') or {},
|
||||
'real_case_calibration_layer': strict.get('real_case_calibration_layer') or {},
|
||||
'technical_debt_contract': strict.get('technical_debt_contract') or {},
|
||||
'remaining_priority1_batch_queue': strict.get('remaining_priority1_batch_queue') or {},
|
||||
'multi_reference_reading_summary': strict.get('multi_reference_reading_summary') or {},
|
||||
'monthly_adjudication_summary': strict.get('monthly_adjudication_summary') or {},
|
||||
'official_day_signal_summary': strict.get('official_day_signal_summary') or {},
|
||||
@@ -1564,6 +1570,36 @@ def _build_ai_prompt_pack(report):
|
||||
if isinstance(primary_strict_contract, dict)
|
||||
else {}
|
||||
)
|
||||
primary_domain_invocation_layers = (
|
||||
primary_strict_contract.get('domain_invocation_contract')
|
||||
if isinstance(primary_strict_contract, dict)
|
||||
else {}
|
||||
)
|
||||
primary_output_template_contract = (
|
||||
primary_strict_contract.get('output_template_contract')
|
||||
if isinstance(primary_strict_contract, dict)
|
||||
else {}
|
||||
)
|
||||
primary_mevg_collection_queue = (
|
||||
primary_strict_contract.get('mevg_collection_queue')
|
||||
if isinstance(primary_strict_contract, dict)
|
||||
else {}
|
||||
)
|
||||
primary_real_case_calibration_layer = (
|
||||
primary_strict_contract.get('real_case_calibration_layer')
|
||||
if isinstance(primary_strict_contract, dict)
|
||||
else {}
|
||||
)
|
||||
primary_technical_debt_contract = (
|
||||
primary_strict_contract.get('technical_debt_contract')
|
||||
if isinstance(primary_strict_contract, dict)
|
||||
else {}
|
||||
)
|
||||
primary_remaining_priority1_batch_queue = (
|
||||
primary_strict_contract.get('remaining_priority1_batch_queue')
|
||||
if isinstance(primary_strict_contract, dict)
|
||||
else {}
|
||||
)
|
||||
primary_audit = (
|
||||
primary_strict_contract.get('technique_audit_summary')
|
||||
if isinstance(primary_strict_contract, dict)
|
||||
@@ -1655,6 +1691,12 @@ def _build_ai_prompt_pack(report):
|
||||
'missing_refs': interpretation_source_audit.get('missing_refs') or [],
|
||||
},
|
||||
'prediction_boundary_contract': primary_prediction_boundary_contract or {},
|
||||
'domain_invocation_layers': primary_domain_invocation_layers or {},
|
||||
'output_template_contract': primary_output_template_contract or {},
|
||||
'mevg_collection_queue': primary_mevg_collection_queue or {},
|
||||
'real_case_calibration_layer': primary_real_case_calibration_layer or {},
|
||||
'technical_debt_contract': primary_technical_debt_contract or {},
|
||||
'remaining_priority1_batch_queue': primary_remaining_priority1_batch_queue or {},
|
||||
'strict_workflow_primary_route': strict_workflow_primary_route,
|
||||
'strict_workflow_routes_available': list(strict_workflow_contracts.keys()),
|
||||
'strict_workflow_contracts': strict_workflow_contracts,
|
||||
|
||||
@@ -304,6 +304,22 @@ def test_full_reading_reports_ayanamsa_metadata_and_ai_prompt_pack() -> None:
|
||||
"manifestation",
|
||||
"label",
|
||||
]
|
||||
domain_layers = prompt_pack["evidence_snapshot"]["domain_invocation_layers"]
|
||||
assert domain_layers["dasha_timing"]["source_refs"] == [
|
||||
"references/vimshottari_dasha_guide.md",
|
||||
"references/pratyantar-calculation-guide.md",
|
||||
"references/condition-dasha-complete.md",
|
||||
]
|
||||
assert domain_layers["varga_strength"]["source_refs"] == [
|
||||
"references/divisional-chart-deep-reading.md",
|
||||
"references/shadbala-complete-methodology.md",
|
||||
"references/ashtakavarga-complete-system.md",
|
||||
]
|
||||
assert prompt_pack["evidence_snapshot"]["output_template_contract"]["required_sections"][-1] == "confidence_boundary"
|
||||
assert prompt_pack["evidence_snapshot"]["mevg_collection_queue"]["status"] == "queued"
|
||||
assert prompt_pack["evidence_snapshot"]["real_case_calibration_layer"]["status"] == "queued"
|
||||
assert prompt_pack["evidence_snapshot"]["technical_debt_contract"]["tajika"]["status"] == "partial"
|
||||
assert prompt_pack["evidence_snapshot"]["remaining_priority1_batch_queue"]["next_batches"][0] == "real_case_studies_batch1"
|
||||
functional_rows = [row for row in audit_table if row["technique"] == "Functional Benefic/Malefic"]
|
||||
assert functional_rows
|
||||
assert functional_rows[0]["status"] == "used"
|
||||
|
||||
@@ -337,6 +337,11 @@ def test_frontend_consumes_top_reader_contract_in_prompt_pack_and_ai_chat() -> N
|
||||
assert "unverified_claim_policy" in ai_chat
|
||||
assert "technique_audit_summary" in ai_chat
|
||||
assert "【Top Reader Contract】" in ai_chat
|
||||
assert "renderInterpretationSourceGovernancePanel" in main
|
||||
assert "Source Governance" in main
|
||||
assert "reference-only" in main
|
||||
assert "blocked non-runtime" in main
|
||||
assert "confidence downgrade" in main
|
||||
assert ".ai-prompt-pack-contract-card" in style
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Contracts for the next interpretation-source pipeline stage."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from mcp_server import _collect_strict_evidence, _existing_interpretation_source_pack
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
DASHA_TIMING = [
|
||||
"references/vimshottari_dasha_guide.md",
|
||||
"references/pratyantar-calculation-guide.md",
|
||||
"references/condition-dasha-complete.md",
|
||||
]
|
||||
VARGA_STRENGTH = [
|
||||
"references/divisional-chart-deep-reading.md",
|
||||
"references/shadbala-complete-methodology.md",
|
||||
"references/ashtakavarga-complete-system.md",
|
||||
]
|
||||
ANNUAL_SPECIAL = [
|
||||
"references/tajika-yoga-complete-guide.md",
|
||||
"references/jaimini-complete-system.md",
|
||||
"references/kp-astrology-complete-system.md",
|
||||
]
|
||||
MODIFIER_OBSTACLE = [
|
||||
"references/argala-complete-guide.md",
|
||||
"references/badhaka-obstacle-planet-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": {
|
||||
"md": {"sign": "Capricorn", "lord": "Saturn"},
|
||||
"ad": {"sign": "Aquarius", "lord": "Saturn"},
|
||||
"pd": {"sign": "Pisces", "lord": "Jupiter"},
|
||||
}
|
||||
},
|
||||
"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 _run_engine(*args: str) -> dict:
|
||||
completed = subprocess.run(
|
||||
[sys.executable, "scripts/jyotish_engine.py", *args],
|
||||
cwd=ROOT,
|
||||
check=False,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
timeout=180,
|
||||
)
|
||||
assert completed.returncode == 0, completed.stderr[-2000:] or completed.stdout[-2000:]
|
||||
return json.loads(completed.stdout)
|
||||
|
||||
|
||||
def test_promote_batch2_is_split_into_domain_invocation_layers() -> None:
|
||||
source_pack = _existing_interpretation_source_pack()
|
||||
domain_layers = source_pack["domain_invocation_layers"]
|
||||
|
||||
assert domain_layers["dasha_timing"]["source_refs"] == DASHA_TIMING
|
||||
assert domain_layers["varga_strength"]["source_refs"] == VARGA_STRENGTH
|
||||
assert domain_layers["annual_special"]["source_refs"] == ANNUAL_SPECIAL
|
||||
assert domain_layers["modifier_obstacle"]["source_refs"] == MODIFIER_OBSTACLE
|
||||
assert domain_layers["dasha_timing"]["required_in_routes"] == ["career", "relationship", "finance"]
|
||||
assert domain_layers["varga_strength"]["required_in_routes"] == ["career", "relationship", "finance"]
|
||||
|
||||
for route in ["career", "relationship", "finance"]:
|
||||
strict = _collect_strict_evidence(route, _base_modules())
|
||||
invocation = strict["domain_invocation_contract"]
|
||||
assert invocation["dasha_timing"]["source_refs"] == DASHA_TIMING
|
||||
assert invocation["varga_strength"]["source_refs"] == VARGA_STRENGTH
|
||||
assert invocation["annual_special"]["source_refs"] == ANNUAL_SPECIAL
|
||||
assert invocation["modifier_obstacle"]["source_refs"] == MODIFIER_OBSTACLE
|
||||
|
||||
|
||||
def test_output_template_mevg_case_and_technical_debt_contracts_are_present() -> None:
|
||||
strict = _collect_strict_evidence("career", _base_modules())
|
||||
|
||||
template = strict["output_template_contract"]
|
||||
assert template["required_sections"] == ["promise", "activation", "manifestation", "label", "confidence_boundary"]
|
||||
assert template["language"] == "zh"
|
||||
assert template["golden_test_status"] == "required"
|
||||
|
||||
mevg_queue = strict["mevg_collection_queue"]
|
||||
assert mevg_queue["status"] == "queued"
|
||||
assert mevg_queue["trigger"] == "fortune_question_strict_workflow"
|
||||
assert "global_web_evidence" in mevg_queue["required_jobs"]
|
||||
assert "source_grading" in mevg_queue["required_jobs"]
|
||||
assert "conflict_arbitration" in mevg_queue["required_jobs"]
|
||||
|
||||
case_layer = strict["real_case_calibration_layer"]
|
||||
assert case_layer["status"] == "queued"
|
||||
assert case_layer["domain_buckets"] == ["career", "finance", "relationship", "health", "rectification", "timing"]
|
||||
assert case_layer["source_roots"] == ["references/real_case_studies", "docs/benchmark"]
|
||||
|
||||
debt = strict["technical_debt_contract"]
|
||||
assert debt["narayana"]["status"] == "partial"
|
||||
assert "antardasha_pratyantar_oracle_parity" in debt["narayana"]["open_items"]
|
||||
assert debt["tajika"]["status"] == "partial"
|
||||
assert "solar_return_precision" in debt["tajika"]["open_items"]
|
||||
assert "muntha_placeholder_audit" in debt["tajika"]["open_items"]
|
||||
|
||||
|
||||
def test_prompt_pack_frontend_and_remaining_batch_queue_expose_next_stage_contracts() -> None:
|
||||
result = _run_engine(
|
||||
"full-reading",
|
||||
"--year",
|
||||
"REDACTED_YEAR",
|
||||
"--month",
|
||||
"4",
|
||||
"--day",
|
||||
"17",
|
||||
"--hour",
|
||||
"14",
|
||||
"--minute",
|
||||
"49",
|
||||
"--lat",
|
||||
"36.466667",
|
||||
"--lon",
|
||||
"114.2",
|
||||
"--tz",
|
||||
"8",
|
||||
"--today",
|
||||
"2026-07-02",
|
||||
"--transit-date",
|
||||
"2026-07-02",
|
||||
)
|
||||
snapshot = result["ai_prompt_pack"]["evidence_snapshot"]
|
||||
|
||||
assert snapshot["domain_invocation_layers"]["dasha_timing"]["source_refs"] == DASHA_TIMING
|
||||
assert snapshot["output_template_contract"]["required_sections"][-1] == "confidence_boundary"
|
||||
assert snapshot["mevg_collection_queue"]["status"] == "queued"
|
||||
assert snapshot["real_case_calibration_layer"]["status"] == "queued"
|
||||
assert snapshot["technical_debt_contract"]["tajika"]["status"] == "partial"
|
||||
assert snapshot["remaining_priority1_batch_queue"]["next_batches"] == [
|
||||
"real_case_studies_batch1",
|
||||
"rishi_ai_mcp_batch1",
|
||||
"vedic_astro_skills_batch1",
|
||||
"references_batch2",
|
||||
]
|
||||
|
||||
main_js = (ROOT / "jyotish-app" / "main.js").read_text(encoding="utf-8")
|
||||
assert "renderInterpretationSourceGovernancePanel" in main_js
|
||||
assert "Source Governance" in main_js
|
||||
assert "reference-only" in main_js
|
||||
assert "blocked non-runtime" in main_js
|
||||
Reference in New Issue
Block a user