Enforce interpretation source content contracts

This commit is contained in:
732642856
2026-07-02 15:09:22 +08:00
parent 79c6ab7414
commit a3d2e0acf9
9 changed files with 500 additions and 1 deletions
+11
View File
@@ -313,6 +313,7 @@ function buildChartContext(cd, guidedTopicContext = null) {
const primaryRoute = officialSnapshot.strict_workflow_primary_route || Object.keys(strictContracts)[0] || '';
const topReaderContract = primaryRoute ? (strictContracts[primaryRoute] || {}) : {};
const adjudicationStages = topReaderContract.adjudication_stages || {};
const predictionBoundaryContract = topReaderContract.prediction_boundary_contract || cd.ai_prompt_pack.evidence_snapshot.prediction_boundary_contract || {};
const multiReferenceSummary = topReaderContract.multi_reference_reading_summary || {};
const techniqueAuditSummary = topReaderContract.technique_audit_summary || {};
const runtimePlannerBoundary = runtimePlanner && typeof runtimePlanner === 'object' && Object.keys(runtimePlanner).length
@@ -341,6 +342,14 @@ function buildChartContext(cd, guidedTopicContext = null) {
`main_conflicts=${(topReaderContract.main_conflicts || []).map(item => item?.type).filter(Boolean).join('/') || 'none'}`,
].join('\n')
: '';
const predictionBoundary = predictionBoundaryContract && typeof predictionBoundaryContract === 'object' && Object.keys(predictionBoundaryContract).length
? [
'【Prediction Boundary Contract】',
`source_refs=${(predictionBoundaryContract.source_refs || []).join(' / ') || '-'}`,
`promise=${predictionBoundaryContract.promise?.status || adjudicationStages.promise?.status || 'missing'} · activation=${predictionBoundaryContract.activation?.status || adjudicationStages.activation?.status || 'missing'} · manifestation=${predictionBoundaryContract.manifestation?.status || adjudicationStages.manifestation?.status || 'missing'} · label=${predictionBoundaryContract.label?.value || topReaderContract.dominant_label || '-'}`,
`mevg=${predictionBoundaryContract.confidence_boundary?.mevg_status || 'blocked'} · real_case=${predictionBoundaryContract.confidence_boundary?.real_case_calibration_status || 'blocked'} · policy=${predictionBoundaryContract.confidence_boundary?.unverified_claim_policy || 'downgrade_or_block'}`,
].join('\n')
: '';
const vedastroBoundary = vedastroOverview && typeof vedastroOverview === 'object'
? [
'【VedAstro Overview Boundary】',
@@ -370,6 +379,8 @@ function buildChartContext(cd, guidedTopicContext = null) {
'',
topReaderBoundary,
'',
predictionBoundary,
'',
guidedTopicBoundary,
'',
vedastroBoundary,
+139 -1
View File
@@ -128,6 +128,37 @@ CORE_RULE_SOURCE_REFS = [
"references/transit-multi-reference-guide.md",
]
PROMOTE_BATCH2_TOPIC_SOURCE_REFS = [
"references/vimshottari_dasha_guide.md",
"references/pratyantar-calculation-guide.md",
"references/divisional-chart-deep-reading.md",
"references/shadbala-complete-methodology.md",
"references/ashtakavarga-complete-system.md",
"references/tajika-yoga-complete-guide.md",
"references/jaimini-complete-system.md",
"references/kp-astrology-complete-system.md",
"references/argala-complete-guide.md",
"references/badhaka-obstacle-planet-guide.md",
"references/condition-dasha-complete.md",
]
REFERENCE_ONLY_CONFLICT_SOURCE_REFS = [
"references/dasa-convergence-methodology.md",
"references/multi-dasha-convergence-protocol.md",
"references/yoga-strength-scoring-system.md",
]
BLOCKED_NON_RUNTIME_SOURCE_REFS = [
"references/varga-system-quick-reference.md",
"references/yoga-list-chinese.md",
"references/analysis-full-reading-v4.0.md",
"references/analysis-full-reading-v1.8-review.md",
"references/audit-skill-full-test-2026-05-04.md",
"references/feature-gap-matrix-2026.md",
"references/kp-practical-event-timing.md",
"references/consultation-case-library.md",
]
def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str, Any]:
primary_truth = [
@@ -166,6 +197,8 @@ def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str,
"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,
*PROMOTE_BATCH2_TOPIC_SOURCE_REFS,
*REFERENCE_ONLY_CONFLICT_SOURCE_REFS,
*frontend_interpretation,
*qa_governance,
*reader_validation,
@@ -223,6 +256,28 @@ def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str,
"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.",
},
"promote_batch2_topic_sources": {
"status": "available",
"promotion_status": "reference_layer_candidate",
"promotion_batch": "priority1_batch1_remaining_promote_11",
"source_refs": _existing_paths(PROMOTE_BATCH2_TOPIC_SOURCE_REFS),
"missing_refs": [path for path in PROMOTE_BATCH2_TOPIC_SOURCE_REFS if not _repo_relative_exists(path)],
"boundary": "Topic-specific promoted references; visible as supporting layers, not all-at-once primary truth.",
},
"reference_only_conflict_sources": {
"status": "available",
"promotion_status": "reference_only",
"source_refs": _existing_paths(REFERENCE_ONLY_CONFLICT_SOURCE_REFS),
"missing_refs": [path for path in REFERENCE_ONLY_CONFLICT_SOURCE_REFS if not _repo_relative_exists(path)],
"boundary": "Useful conflict/reference material; must not outrank primary rule sources or tested contracts.",
},
"blocked_non_runtime_sources": {
"status": "blocked",
"promotion_status": "not_truth_source",
"source_refs": _existing_paths(BLOCKED_NON_RUNTIME_SOURCE_REFS),
"missing_refs": [path for path in BLOCKED_NON_RUNTIME_SOURCE_REFS if not _repo_relative_exists(path)],
"boundary": "Duplicate, obsolete, or quarantined files; never expose through runtime source_refs.",
},
"quarantined_drafts": {
"status": "quarantined",
"promotion_status": "not_truth_source",
@@ -233,8 +288,10 @@ def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str,
}
missing_refs = [path for layer in layers.values() for path in layer["missing_refs"]]
quarantined_refs = set(layers["quarantined_drafts"]["source_refs"])
blocked_non_runtime_refs = set(layers["blocked_non_runtime_sources"]["source_refs"])
promoted_quarantined = sorted(quarantined_refs.intersection(source_refs))
status = "used" if not missing_refs and not promoted_quarantined else "partial"
promoted_blocked_non_runtime = sorted(blocked_non_runtime_refs.intersection(source_refs))
status = "used" if not missing_refs and not promoted_quarantined and not promoted_blocked_non_runtime else "partial"
return {
"status": status,
"source": "repo_interpretation_source_inventory_v1",
@@ -243,11 +300,14 @@ def _build_interpretation_source_inventory(source_refs: List[str]) -> Dict[str,
"primary_truth_count": len(layers["primary_truth"]["source_refs"]),
"reference_layer_count": len(_existing_paths(reference_layer)),
"quarantined_draft_count": len(layers["quarantined_drafts"]["source_refs"]),
"blocked_non_runtime_count": len(layers["blocked_non_runtime_sources"]["source_refs"]),
"missing_ref_count": len(missing_refs),
"promoted_quarantined_count": len(promoted_quarantined),
"promoted_blocked_non_runtime_count": len(promoted_blocked_non_runtime),
},
"missing_refs": missing_refs,
"promoted_quarantined_refs": promoted_quarantined,
"promoted_blocked_non_runtime_refs": promoted_blocked_non_runtime,
"boundary": "Inventory is explicit and conservative; local drafts are indexed but not treated as truth sources.",
}
@@ -267,6 +327,9 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]:
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
promote_batch2_paths = PROMOTE_BATCH2_TOPIC_SOURCE_REFS
reference_only_paths = REFERENCE_ONLY_CONFLICT_SOURCE_REFS
blocked_non_runtime_paths = BLOCKED_NON_RUNTIME_SOURCE_REFS
frontend_interpretation_paths = [
"jyotish-app/interpretation.js",
"jyotish-app/analysis-deep.js",
@@ -308,6 +371,8 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]:
mevg_path,
real_case_checklist_path,
*core_rule_paths,
*promote_batch2_paths,
*reference_only_paths,
*frontend_interpretation_paths,
*planet_house_paths,
qa_rules_path,
@@ -337,6 +402,8 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]:
"mevg_mandatory_external_verification",
"real_case_quality_checklist",
"priority1_batch1_core_rule_sources",
"priority1_batch1_promote_topic_sources",
"reference_only_conflict_sources",
"qa_governance_rules",
"reader_validation_rules",
"frontend_interpretation_layer",
@@ -354,6 +421,25 @@ def _existing_interpretation_source_pack() -> Dict[str, Any]:
"promotion_batch": "priority1_batch1_core5",
"boundary": "Audit-promoted core references; use as visible rule sources with conflict arbitration.",
},
"promote_batch2_topic_layer": {
"status": "available" if all(_repo_relative_exists(path) for path in promote_batch2_paths) else "partial",
"source_refs": promote_batch2_paths,
"promotion_status": "reference_layer_candidate",
"promotion_batch": "priority1_batch1_remaining_promote_11",
"boundary": "Topic-specific promoted references; wire by domain and do not flatten into primary truth.",
},
"reference_only_conflict_layer": {
"status": "available" if all(_repo_relative_exists(path) for path in reference_only_paths) else "partial",
"source_refs": reference_only_paths,
"promotion_status": "reference_only",
"boundary": "Reference-only sources can explain conflicts but cannot override primary rule sources.",
},
"blocked_non_runtime_layer": {
"status": "blocked",
"source_refs": blocked_non_runtime_paths,
"promotion_status": "not_truth_source",
"boundary": "Duplicate, obsolete, and quarantined files are deliberately excluded from runtime source_refs.",
},
"frontend_interpretation_layer": {
"status": "available" if all(_repo_relative_exists(path) for path in frontend_interpretation_paths) else "partial",
"source_refs": frontend_interpretation_paths,
@@ -2553,6 +2639,16 @@ def _build_technique_audit_summary(route: str, strict: Dict[str, Any]) -> Dict[s
if isinstance(interpretation_source_pack.get("core_rule_source_layer"), dict)
else []
),
"promote_batch2_source_refs": (
interpretation_source_pack.get("promote_batch2_topic_layer", {}).get("source_refs")
if isinstance(interpretation_source_pack.get("promote_batch2_topic_layer"), dict)
else []
),
"reference_only_source_refs": (
interpretation_source_pack.get("reference_only_conflict_layer", {}).get("source_refs")
if isinstance(interpretation_source_pack.get("reference_only_conflict_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"
@@ -2646,6 +2742,47 @@ def _build_adjudication_stages(route: str, present: Dict[str, Any], event_judgem
}
def _build_prediction_boundary_contract(route: str, strict: Dict[str, Any]) -> Dict[str, Any]:
stages = strict.get("adjudication_stages") if isinstance(strict.get("adjudication_stages"), dict) else {}
audit = strict.get("technique_audit_summary") if isinstance(strict.get("technique_audit_summary"), dict) else {}
mevg = audit.get("mevg_global_web_evidence") if isinstance(audit.get("mevg_global_web_evidence"), dict) else {}
real_case = audit.get("real_case_calibration") if isinstance(audit.get("real_case_calibration"), dict) else {}
interpretation_source_pack = (
audit.get("interpretation_source_pack")
if isinstance(audit.get("interpretation_source_pack"), dict)
else {}
)
return {
"route": route,
"status": "used",
"source_refs": interpretation_source_pack.get("core_rule_source_refs") or CORE_RULE_SOURCE_REFS,
"event_judgment_skeleton": {
"status": "used",
"required_sections": ["promise", "activation", "manifestation", "label"],
"source_ref": "references/event_judgment_skeleton.md",
},
"promise": stages.get("promise") or {},
"activation": stages.get("activation") or {},
"manifestation": stages.get("manifestation") or {},
"label": stages.get("label") or {},
"confidence_boundary": {
"status": "used",
"source_ref": "references/prediction-boundary-protocol.md",
"confidence_cap": strict.get("confidence_cap"),
"blocked": bool(strict.get("blocked")),
"mevg_status": mevg.get("status") or "blocked",
"real_case_calibration_status": real_case.get("status") or "blocked",
"unverified_claim_policy": "downgrade_or_block",
"precision_policy": "timing_window_not_guaranteed_event_form",
},
"modifier_rule_sources": {
"dignity": "references/planetary-dignity-complete-reference.md",
"planetary_conditions": "references/retrograde-combustion-war-guide.md",
"transit": "references/transit-multi-reference-guide.md",
},
}
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),
@@ -2671,6 +2808,7 @@ def _attach_top_reader_contract(route: str, strict: Dict[str, Any]) -> Dict[str,
event_judgement = {}
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["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)
+9
View File
@@ -768,3 +768,12 @@
- `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、真实案例校准和领域分盘/大运证据。
## 2026-07-02T15:42:00+08:00 - 核心 5 内容级调用与第二批资料层闭环
- 核心 5 不再只是可见:career / relationship / finance strict workflow 现在生成 `prediction_boundary_contract`,强制绑定 `promise -> activation -> manifestation -> label`、MEVG blocked、Real Case Calibration blocked 与核心 5 source refs。
- 第二批 promote 11 个专题源头已接成 `promote_batch2_topic_layer`Vimshottari、Pratyantar、分盘深读、Shadbala、Ashtakavarga、Tajika、Jaimini、KP、Argala、Badhaka、Condition Dasha。
- `reference-only` 3 个源头已接成 `reference_only_conflict_layer`,只允许作为冲突/参考材料:`dasa-convergence-methodology``multi-dasha-convergence-protocol``yoga-strength-scoring-system`
- 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 3AI Chat 上下文新增 `【Prediction Boundary Contract】` 段落。
- 真实 full-reading 回归确认:REDACTED_DATE REDACTED_TIME REDACTED_PLACE矿区样例中 relationship / career / finance 三条 strict contract 均带 prediction boundary,且 MEVG 与真实案例校准仍为 blocked。
+66
View File
@@ -3901,6 +3901,8 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'不要仅凭单一配置下结论;核心判断至少交叉 D1、D9、Dasha、Shadbala/Ashtakavarga 或 Transit 中的两个证据层。',
'必须显式标注置信度和边界:Dasha/PDF 起点差异、Shadbala 外部绝对值 oracle 尚未完成时,不得声称已经完全校准。',
'VedAstro 官方全量快照是第一原始证据层;若该层 blocked,必须把本地结果标记为 fallback。',
'必须按 promise → activation → manifestation → label 输出;每个判断都要说明属于承诺、激活、落地形式还是标签层。',
'未完成 MEVG / Real Case Calibration 时必须降级或标 blocked,不得把内部一致性写成已验证结论。',
]
oracle_progress = {
'scope': 'external_oracle_evidence_validation',
@@ -3938,6 +3940,53 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'shadbala_ranking': top_strength,
},
'functional_benefic_malefic': functional_layer,
'interpretation_source_pack': {
'status': 'fallback_prompt_pack_only',
'source': 'api_chart_prompt_pack_fallback',
'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',
],
'promote_batch2_source_refs': [
'references/vimshottari_dasha_guide.md',
'references/pratyantar-calculation-guide.md',
'references/divisional-chart-deep-reading.md',
'references/shadbala-complete-methodology.md',
'references/ashtakavarga-complete-system.md',
'references/tajika-yoga-complete-guide.md',
'references/jaimini-complete-system.md',
'references/kp-astrology-complete-system.md',
'references/argala-complete-guide.md',
'references/badhaka-obstacle-planet-guide.md',
'references/condition-dasha-complete.md',
],
'reference_only_source_refs': [
'references/dasa-convergence-methodology.md',
'references/multi-dasha-convergence-protocol.md',
'references/yoga-strength-scoring-system.md',
],
},
'prediction_boundary_contract': {
'status': 'fallback_prompt_pack_only',
'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',
],
'event_judgment_skeleton': {
'required_sections': ['promise', 'activation', 'manifestation', 'label'],
},
'confidence_boundary': {
'mevg_status': 'blocked',
'real_case_calibration_status': 'blocked',
'unverified_claim_policy': 'downgrade_or_block',
},
},
'vedastro_official_full_snapshot': vedastro_official_full_snapshot,
'vedastro_overview': vedastro_overview,
'guided_topics': guided_topics,
@@ -3952,7 +4001,24 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'references/ai-reading-workflow-prompt.md',
'references/comprehensive-reading-workflow.md',
'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',
'references/vimshottari_dasha_guide.md',
'references/pratyantar-calculation-guide.md',
'references/divisional-chart-deep-reading.md',
'references/shadbala-complete-methodology.md',
'references/ashtakavarga-complete-system.md',
'references/tajika-yoga-complete-guide.md',
'references/jaimini-complete-system.md',
'references/kp-astrology-complete-system.md',
'references/argala-complete-guide.md',
'references/badhaka-obstacle-planet-guide.md',
'references/condition-dasha-complete.md',
'references/dasa-convergence-methodology.md',
'references/multi-dasha-convergence-protocol.md',
'references/yoga-strength-scoring-system.md',
'references/shadbala-interpretation-methodology.md',
'references/navamsa-d9-interpretation-template.md',
],
+44
View File
@@ -1432,6 +1432,7 @@ def _compact_strict_workflow_contract(strict):
'conflicts': strict.get('conflicts') or [],
'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 {},
'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 {},
@@ -1558,6 +1559,21 @@ def _build_ai_prompt_pack(report):
vedastro_official_full_snapshot = _build_vedastro_official_full_snapshot_payload(modules)
strict_workflow_contracts = _extract_strict_workflow_contracts(modules)
strict_workflow_primary_route, primary_strict_contract = _preferred_strict_workflow_contract(strict_workflow_contracts)
primary_prediction_boundary_contract = (
primary_strict_contract.get('prediction_boundary_contract')
if isinstance(primary_strict_contract, dict)
else {}
)
primary_audit = (
primary_strict_contract.get('technique_audit_summary')
if isinstance(primary_strict_contract, dict)
else {}
)
interpretation_source_audit = (
primary_audit.get('interpretation_source_pack')
if isinstance(primary_audit, dict) and isinstance(primary_audit.get('interpretation_source_pack'), dict)
else {}
)
guided_topics = modules.get('guided_topics') if isinstance(modules.get('guided_topics'), list) else build_guided_topics(report)
capability_evidence_pool = build_capability_evidence_pool_summary()
@@ -1630,6 +1646,15 @@ def _build_ai_prompt_pack(report):
},
'oracle_progress': oracle_progress,
'functional_benefic_malefic': functional_layer,
'interpretation_source_pack': {
'status': interpretation_source_audit.get('status') or 'blocked',
'source': interpretation_source_audit.get('source') or 'repo_existing_interpretation_sources',
'core_rule_source_refs': interpretation_source_audit.get('core_rule_source_refs') or [],
'promote_batch2_source_refs': interpretation_source_audit.get('promote_batch2_source_refs') or [],
'reference_only_source_refs': interpretation_source_audit.get('reference_only_source_refs') or [],
'missing_refs': interpretation_source_audit.get('missing_refs') or [],
},
'prediction_boundary_contract': primary_prediction_boundary_contract or {},
'strict_workflow_primary_route': strict_workflow_primary_route,
'strict_workflow_routes_available': list(strict_workflow_contracts.keys()),
'strict_workflow_contracts': strict_workflow_contracts,
@@ -1660,6 +1685,8 @@ def _build_ai_prompt_pack(report):
"若 evidence_snapshot.vedastro_overview.status 为 ok,请把它作为用户可见外部概览证据明确写出,但不要把 overview-only 结果误当作长周期精扫结论。",
"VedAstro 官方全量快照是第一原始证据层;若 evidence_snapshot.vedastro_official_full_snapshot.status 不是 ok/partial,必须说明官方全量资料 blocked,并把本地结果标记为 fallback。",
"若 evidence_snapshot.capability_evidence_pool 存在,请把 89 项视为后台备选证据池;不要把所有能力条目平铺成结论,也不要让 audit_only/alias 条目影响占星判断。",
"必须按 promise → activation → manifestation → label 输出;每个判断都要说明属于承诺、激活、落地形式还是标签层。",
"未完成 MEVG / Real Case Calibration 时必须降级或标 blocked,不得把内部一致性写成已验证结论。",
]
return {
@@ -1672,7 +1699,24 @@ def _build_ai_prompt_pack(report):
'references/ai-reading-workflow-prompt.md',
'references/comprehensive-reading-workflow.md',
'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',
'references/vimshottari_dasha_guide.md',
'references/pratyantar-calculation-guide.md',
'references/divisional-chart-deep-reading.md',
'references/shadbala-complete-methodology.md',
'references/ashtakavarga-complete-system.md',
'references/tajika-yoga-complete-guide.md',
'references/jaimini-complete-system.md',
'references/kp-astrology-complete-system.md',
'references/argala-complete-guide.md',
'references/badhaka-obstacle-planet-guide.md',
'references/condition-dasha-complete.md',
'references/dasa-convergence-methodology.md',
'references/multi-dasha-convergence-protocol.md',
'references/yoga-strength-scoring-system.md',
'references/shadbala-interpretation-methodology.md',
'references/navamsa-d9-interpretation-template.md',
'references/interpretation_template_registry.json',
+19
View File
@@ -286,6 +286,24 @@ def test_full_reading_reports_ayanamsa_metadata_and_ai_prompt_pack() -> None:
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)
interpretation_source_pack = prompt_pack["evidence_snapshot"]["interpretation_source_pack"]
assert interpretation_source_pack["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",
]
assert "references/vimshottari_dasha_guide.md" in interpretation_source_pack["promote_batch2_source_refs"]
assert "references/yoga-strength-scoring-system.md" in interpretation_source_pack["reference_only_source_refs"]
prediction_boundary = prompt_pack["evidence_snapshot"]["prediction_boundary_contract"]
assert prediction_boundary["confidence_boundary"]["unverified_claim_policy"] == "downgrade_or_block"
assert prediction_boundary["event_judgment_skeleton"]["required_sections"] == [
"promise",
"activation",
"manifestation",
"label",
]
functional_rows = [row for row in audit_table if row["technique"] == "Functional Benefic/Malefic"]
assert functional_rows
assert functional_rows[0]["status"] == "used"
@@ -359,6 +377,7 @@ def test_full_reading_reports_ayanamsa_metadata_and_ai_prompt_pack() -> None:
assert "finance" in vedastro_official_snapshot["strict_workflow_contracts"]
career_contract = vedastro_official_snapshot["strict_workflow_contracts"]["career"]
assert "adjudication_stages" in career_contract
assert "prediction_boundary_contract" in career_contract
assert "multi_reference_reading_summary" in career_contract
assert "modifier_frame" in career_contract["multi_reference_reading_summary"]
assert vedastro_official_snapshot["strict_workflow_primary_route"] in {"relationship", "career", "finance", None}
+3
View File
@@ -332,6 +332,9 @@ def test_frontend_consumes_top_reader_contract_in_prompt_pack_and_ai_chat() -> N
assert "Top-reader adjudication" in main
assert "multi_reference_reading_summary" in ai_chat
assert "adjudication_stages" in ai_chat
assert "prediction_boundary_contract" in ai_chat
assert "【Prediction Boundary Contract】" in ai_chat
assert "unverified_claim_policy" in ai_chat
assert "technique_audit_summary" in ai_chat
assert "【Top Reader Contract】" in ai_chat
assert ".ai-prompt-pack-contract-card" in style
@@ -51,6 +51,14 @@ def test_interpretation_source_inventory_gate_reports_layered_source_pack() -> N
"references/retrograde-combustion-war-guide.md",
"references/transit-multi-reference-guide.md",
]
assert layers["promote_batch2_topic_sources"]["promotion_batch"] == "priority1_batch1_remaining_promote_11"
assert "references/vimshottari_dasha_guide.md" in layers["promote_batch2_topic_sources"]["source_refs"]
assert "references/condition-dasha-complete.md" in layers["promote_batch2_topic_sources"]["source_refs"]
assert layers["reference_only_conflict_sources"]["promotion_status"] == "reference_only"
assert "references/multi-dasha-convergence-protocol.md" in layers["reference_only_conflict_sources"]["source_refs"]
assert layers["blocked_non_runtime_sources"]["promotion_status"] == "not_truth_source"
assert "references/kp-practical-event-timing.md" in layers["blocked_non_runtime_sources"]["source_refs"]
assert report["summary"]["blocked_non_runtime_count"] >= 8
draft_refs = layers["quarantined_drafts"]["source_refs"]
source_refs = set(report["runtime_source_refs"])
@@ -0,0 +1,201 @@
#!/usr/bin/env python3
"""Regression tests for source-pack content contracts beyond visibility."""
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]
CORE5 = [
"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",
]
PROMOTE_BATCH2 = [
"references/vimshottari_dasha_guide.md",
"references/pratyantar-calculation-guide.md",
"references/divisional-chart-deep-reading.md",
"references/shadbala-complete-methodology.md",
"references/ashtakavarga-complete-system.md",
"references/tajika-yoga-complete-guide.md",
"references/jaimini-complete-system.md",
"references/kp-astrology-complete-system.md",
"references/argala-complete-guide.md",
"references/badhaka-obstacle-planet-guide.md",
"references/condition-dasha-complete.md",
]
REFERENCE_ONLY = [
"references/dasa-convergence-methodology.md",
"references/multi-dasha-convergence-protocol.md",
"references/yoga-strength-scoring-system.md",
]
NON_RUNTIME = [
"references/varga-system-quick-reference.md",
"references/yoga-list-chinese.md",
"references/analysis-full-reading-v4.0.md",
"references/analysis-full-reading-v1.8-review.md",
"references/audit-skill-full-test-2026-05-04.md",
"references/feature-gap-matrix-2026.md",
"references/kp-practical-event-timing.md",
"references/consultation-case-library.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 _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_core5_sources_drive_prediction_boundary_contract_for_all_strict_routes() -> None:
for route in ["career", "relationship", "finance"]:
strict = _collect_strict_evidence(route, _base_modules())
contract = strict["prediction_boundary_contract"]
assert contract["source_refs"] == CORE5
assert contract["event_judgment_skeleton"]["required_sections"] == [
"promise",
"activation",
"manifestation",
"label",
]
assert contract["promise"]["status"] == strict["adjudication_stages"]["promise"]["status"]
assert contract["activation"]["status"] == strict["adjudication_stages"]["activation"]["status"]
assert contract["manifestation"]["status"] == strict["adjudication_stages"]["manifestation"]["status"]
assert contract["confidence_boundary"]["mevg_status"] == "blocked"
assert contract["confidence_boundary"]["real_case_calibration_status"] == "blocked"
assert contract["confidence_boundary"]["unverified_claim_policy"] == "downgrade_or_block"
def test_batch2_and_reference_only_layers_are_wired_without_polluting_truth_sources() -> None:
source_pack = _existing_interpretation_source_pack()
assert source_pack["promote_batch2_topic_layer"]["status"] == "available"
assert source_pack["promote_batch2_topic_layer"]["source_refs"] == PROMOTE_BATCH2
assert source_pack["reference_only_conflict_layer"]["status"] == "available"
assert source_pack["reference_only_conflict_layer"]["source_refs"] == REFERENCE_ONLY
assert source_pack["reference_only_conflict_layer"]["promotion_status"] == "reference_only"
runtime_refs = set(source_pack["source_refs"])
for path in PROMOTE_BATCH2 + REFERENCE_ONLY:
assert path in runtime_refs
for path in NON_RUNTIME:
assert path not in runtime_refs
inventory = source_pack["interpretation_source_inventory"]
assert inventory["layers"]["promote_batch2_topic_sources"]["source_refs"] == PROMOTE_BATCH2
assert inventory["layers"]["reference_only_conflict_sources"]["source_refs"] == REFERENCE_ONLY
assert inventory["summary"]["blocked_non_runtime_count"] >= len(NON_RUNTIME)
def test_prompt_pack_and_real_reading_regression_expose_content_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",
)
prompt_pack = result["ai_prompt_pack"]
snapshot = prompt_pack["evidence_snapshot"]
assert snapshot["prediction_boundary_contract"]["source_refs"] == CORE5
assert snapshot["interpretation_source_pack"]["core_rule_source_refs"] == CORE5
assert snapshot["interpretation_source_pack"]["promote_batch2_source_refs"] == PROMOTE_BATCH2
assert snapshot["interpretation_source_pack"]["reference_only_source_refs"] == REFERENCE_ONLY
assert "必须按 promise → activation → manifestation → label 输出" in prompt_pack["prompt_zh"]
assert "未完成 MEVG / Real Case Calibration 时必须降级或标 blocked" in prompt_pack["prompt_zh"]
docs = prompt_pack["retrieval_plan"]["local_reference_docs"]
for path in CORE5 + PROMOTE_BATCH2 + REFERENCE_ONLY:
assert path in docs
for path in NON_RUNTIME:
assert path not in docs
for route in ["career", "relationship", "finance"]:
contract = snapshot["strict_workflow_contracts"][route]
assert contract["prediction_boundary_contract"]["source_refs"] == CORE5
audit = contract["technique_audit_summary"]
assert audit["mevg_global_web_evidence"]["status"] == "blocked"
assert audit["real_case_calibration"]["status"] == "blocked"
assert audit["interpretation_source_pack"]["core_rule_source_refs"] == CORE5