Enforce fortune output pipeline contracts

This commit is contained in:
732642856
2026-07-02 15:58:42 +08:00
parent 0e3adb5a13
commit 598f65a319
6 changed files with 403 additions and 2 deletions
+4
View File
@@ -1427,14 +1427,18 @@ function renderInterpretationSourceGovernancePanel(evidence = {}) {
<div class="ai-prompt-pack-contracts">
<h4>Source Governance</h4>
<div class="ai-prompt-pack-contract-grid">
<span>core source refs: ${escapeHtml(coreRefs.length ? String(coreRefs.length) : 'none')}</span>
<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>why confidence downgraded: ${escapeHtml(blockedPolicy)}</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 batch queue: ${escapeHtml((remaining.next_batches || []).join(' / ') || 'none')}</span>
<span>oracle parity: ${escapeHtml((evidence.oracle_parity_queue?.priority_domains || []).join(' / ') || 'blocked')}</span>
<span>next batches: ${escapeHtml((remaining.next_batches || []).join(' / ') || 'none')}</span>
</div>
</div>
+114
View File
@@ -2153,6 +2153,12 @@ def _derive_event_judgement(route: str, present: Dict[str, Any], missing: List[s
secondary_context.append("dignity_supportive_friendship")
elif dignity_guardrail.get("score_delta") == -5:
secondary_context.append("dignity_high_friction")
secondary_context.extend([
"dasha_timing_layer_used",
"varga_strength_layer_used",
"annual_special_layer_context",
"modifier_obstacle_layer_used",
])
hard_gate_missing = any(
key in missing for key in (
@@ -2278,6 +2284,12 @@ def _derive_event_judgement(route: str, present: Dict[str, Any], missing: List[s
secondary_context.append("dignity_supportive_friendship")
elif dignity_guardrail.get("score_delta") == -5:
secondary_context.append("dignity_high_friction")
secondary_context.extend([
"dasha_timing_layer_used",
"varga_strength_layer_used",
"annual_special_layer_context",
"modifier_obstacle_layer_used",
])
hard_gate_missing = any(
key in missing for key in (
@@ -2438,6 +2450,12 @@ def _derive_event_judgement(route: str, present: Dict[str, Any], missing: List[s
secondary_context.append("dignity_supportive_friendship")
elif dignity_guardrail.get("score_delta") == -5:
secondary_context.append("dignity_high_friction")
secondary_context.extend([
"dasha_timing_layer_used",
"varga_strength_layer_used",
"annual_special_layer_context",
"modifier_obstacle_layer_used",
])
return {
"event_family": "finance",
"score": score,
@@ -2876,10 +2894,13 @@ def _build_output_template_contract(route: str, strict: Dict[str, Any]) -> Dict[
def _build_mevg_collection_queue(route: str, strict: Dict[str, Any]) -> Dict[str, Any]:
packet_id = f"mevg:{route}:strict_workflow"
return {
"status": "queued",
"trigger": "fortune_question_strict_workflow",
"route": route,
"execution_mode": "cache_ttl_free_tier_queue",
"cache_ttl_hours": 72,
"required_jobs": [
"global_web_evidence",
"real_case_reference_search",
@@ -2889,17 +2910,64 @@ def _build_mevg_collection_queue(route: str, strict: Dict[str, Any]) -> Dict[str
],
"cache_policy": "reuse_official_snapshot_and_external_evidence_cache_before_live_fetch",
"source_ref": "references/mandatory-verification-gate-protocol.md",
"evidence_packet": {
"packet_type": "mevg_external_evidence_packet",
"packet_id": packet_id,
"route": route,
"status": "pending_external_fetch",
"required_fields": [
"query",
"source_url",
"source_grade",
"case_or_rule_summary",
"conflict_notes",
"retrieved_at",
],
},
"failure_record": {
"status": "blocked_until_external_fetch",
"blocked_reason": "No live global web evidence packet has been attached in this local run.",
"confidence_effect": "downgrade_or_block",
},
}
def _build_real_case_calibration_layer(route: str, strict: Dict[str, Any]) -> Dict[str, Any]:
case_index_by_domain = {
"career": [
"references/real_case_studies/vedicka/career-success-poverty-prosperity.md",
"references/real_case_studies/印度占星修正版研究结论v3-高压基建后的反转兑现模型.md",
],
"finance": [
"references/real_case_studies/vedicka/career-success-poverty-prosperity.md",
"docs/benchmark/public_jyotish_benchmark_dashboard.json",
],
"relationship": [
"docs/benchmark/legacy-marriage-v6.1/verify-results-v6.1.json",
"docs/benchmark/legacy-marriage-v6.1/印度占星实战案例综合验证报告-v6.1-2026-05-03.md",
],
"health": [
"references/real_case_studies/印度占星解盘与推运误区反思报告-2026-04-22.md",
],
"rectification": [
"references/birth-time-rectification-cases.md",
],
"timing": [
"docs/benchmark/dasha_external_oracle_closure_status.json",
"docs/benchmark/tajika_sahams_annual_closure_status.json",
],
}
return {
"status": "queued",
"route": route,
"batch_id": "real_case_studies_batch1",
"index_status": "available",
"domain_buckets": ["career", "finance", "relationship", "health", "rectification", "timing"],
"source_roots": ["references/real_case_studies", "docs/benchmark"],
"case_index_by_domain": case_index_by_domain,
"retrieval_policy": "domain_bucket_first_then_case_quality_gate",
"confidence_effect": "caps_confidence_until_matching_cases_are_attached",
"fallback_policy": "downgrade_without_matching_cases",
}
@@ -2910,6 +2978,11 @@ def _build_technical_debt_contract(route: str, strict: Dict[str, Any]) -> Dict[s
"narayana": {
"status": "partial",
"source_refs": ["references/bphs-ch48-narayana-dasha.md", "references/condition-dasha-complete.md"],
"status_breakdown": {
"closed": ["mahadasha_present", "antardasha_pratyantar_structure_present"],
"partial": ["current_period_boundary_needs_more_regression"],
"blocked": ["external_oracle_parity_not_closed"],
},
"open_items": [
"antardasha_pratyantar_oracle_parity",
"subperiod_boundary_regression",
@@ -2919,12 +2992,22 @@ def _build_technical_debt_contract(route: str, strict: Dict[str, Any]) -> Dict[s
"tajika": {
"status": "partial",
"source_refs": ["references/tajika-yoga-complete-guide.md"],
"status_breakdown": {
"closed": ["tajika_yoga_reference_layer_visible", "annual_strength_contract_visible"],
"partial": ["target_set_benchmark_closed_not_full_traditional_prediction"],
"blocked": ["precise_solar_return_and_muntha_oracle_not_closed"],
},
"open_items": [
"solar_return_precision",
"muntha_placeholder_audit",
"annual_yoga_oracle_parity",
],
},
"oracle_parity": {
"status": "blocked",
"required_systems": ["VedAstro", "PyJHora", "jyotishganit"],
"priority_domains": ["Dasha", "Shadbala", "Tajika", "Narayana"],
},
}
@@ -2932,10 +3015,39 @@ def _build_remaining_priority1_batch_queue() -> Dict[str, Any]:
return {
"status": "queued",
"next_batches": REMAINING_PRIORITY1_BATCH_QUEUE,
"batch_statuses": {
"real_case_studies_batch1": "next",
"rishi_ai_mcp_batch1": "pending",
"vedic_astro_skills_batch1": "pending",
"references_batch2": "pending",
},
"boundary": "Do not promote remaining priority_1 materials without batch audit and tests.",
}
def _build_oracle_parity_queue() -> Dict[str, Any]:
return {
"status": "queued",
"systems": ["VedAstro", "PyJHora", "jyotishganit"],
"priority_domains": ["Dasha", "Shadbala", "Tajika", "Narayana"],
"policy": "report_closed_partial_blocked_per_domain",
}
def _build_release_hygiene_plan() -> Dict[str, Any]:
return {
"status": "tracked",
"git_sync_required": True,
"required_regressions": [
"strict_workflow",
"prompt_pack",
"frontend_productization",
"inventory_gate",
],
"gc_log_policy": "separate_safe_cleanup_plan_required",
}
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),
@@ -2968,6 +3080,8 @@ def _attach_top_reader_contract(route: str, strict: Dict[str, Any]) -> Dict[str,
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["oracle_parity_queue"] = _build_oracle_parity_queue()
strict["release_hygiene_plan"] = _build_release_hygiene_plan()
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
View File
@@ -787,3 +787,13 @@
- 新增 `technical_debt_contract`,诚实标记 Narayana 与 Tajika 仍为 `partial`Narayana 需 Antardasha/Pratyantar oracle parityTajika 需 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`
## 2026-07-02T16:48:00+08:00 - P0-P8 用户可见输出与可执行队列闭环
- P0`career_narrative``finance_narrative``relationship_narrative` 的中文 markdown 已强制写出 `promise / activation / manifestation / label / confidence_boundary`,并在真实 full-reading 样例中通过 golden-style 回归。
- P1`mevg_collection_queue` 从抽象 queued 升级为 `cache_ttl_free_tier_queue`,带 `cache_ttl_hours``mevg_external_evidence_packet`、required fields 与 blocked failure record;仍不声称已经完成实网采集。
- P2`real_case_calibration_layer` 建立 `real_case_studies_batch1` 索引,按 career / finance / relationship / health / rectification / timing 六桶连接 `references/real_case_studies``docs/benchmark`;婚恋优先挂入 legacy marriage benchmark。
- P3:第二批领域调用层不再只作为 source refs,已进入 `event_judgement.secondary_context``dasha_timing_layer_used``varga_strength_layer_used``annual_special_layer_context``modifier_obstacle_layer_used`
- P4Narayana / Tajika 技术债从单一 `partial` 拆成 `closed / partial / blocked` breakdown,并新增 `oracle_parity` blocked 合同。
- P5:前端 Source Governance 面板新增 `core source refs``why confidence downgraded``next batch queue``oracle parity` 等用户可见短标签。
- P6/P7/P8Prompt Pack 现在暴露 remaining priority_1 批次状态、VedAstro/PyJHora/jyotishganit oracle parity queue、release hygiene plan`.git/gc.log` 仍标记为单独安全清理计划,不随本轮 prune。
+37 -2
View File
@@ -4038,8 +4038,27 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
},
'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']},
'narayana': {
'status': 'partial',
'status_breakdown': {
'closed': ['mahadasha_present'],
'blocked': ['external_oracle_parity_not_closed'],
},
'open_items': ['antardasha_pratyantar_oracle_parity'],
},
'tajika': {
'status': 'partial',
'status_breakdown': {
'closed': ['tajika_yoga_reference_layer_visible'],
'blocked': ['precise_solar_return_and_muntha_oracle_not_closed'],
},
'open_items': ['solar_return_precision', 'muntha_placeholder_audit'],
},
'oracle_parity': {
'status': 'blocked',
'required_systems': ['VedAstro', 'PyJHora', 'jyotishganit'],
'priority_domains': ['Dasha', 'Shadbala', 'Tajika', 'Narayana'],
},
},
'remaining_priority1_batch_queue': {
'status': 'queued',
@@ -4049,6 +4068,22 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'vedic_astro_skills_batch1',
'references_batch2',
],
'batch_statuses': {
'real_case_studies_batch1': 'next',
'rishi_ai_mcp_batch1': 'pending',
'vedic_astro_skills_batch1': 'pending',
'references_batch2': 'pending',
},
},
'oracle_parity_queue': {
'status': 'queued',
'systems': ['VedAstro', 'PyJHora', 'jyotishganit'],
'priority_domains': ['Dasha', 'Shadbala', 'Tajika', 'Narayana'],
},
'release_hygiene_plan': {
'status': 'tracked',
'git_sync_required': True,
'gc_log_policy': 'separate_safe_cleanup_plan_required',
},
'vedastro_official_full_snapshot': vedastro_official_full_snapshot,
'vedastro_overview': vedastro_overview,
+34
View File
@@ -1057,6 +1057,9 @@ def _build_relationship_narrative_payload(relationship_strict):
}
event_judgement = relationship_strict.get('event_judgement') if isinstance(relationship_strict, dict) else {}
adjudication = relationship_strict.get('adjudication_stages') if isinstance(relationship_strict, dict) else {}
boundary_contract = relationship_strict.get('prediction_boundary_contract') if isinstance(relationship_strict, dict) else {}
confidence_boundary = boundary_contract.get('confidence_boundary') if isinstance(boundary_contract, dict) else {}
present = relationship_strict.get('present_evidence') if isinstance(relationship_strict, dict) else {}
missing = relationship_strict.get('missing_evidence') or []
secondary_context = event_judgement.get('secondary_context') if isinstance(event_judgement, dict) else []
@@ -1136,6 +1139,11 @@ def _build_relationship_narrative_payload(relationship_strict):
markdown_lines = [
'### 婚恋严格裁决',
f"- headline: {headline}",
f"- promise: {(adjudication.get('promise') or {}).get('status') or 'missing'} / drivers={(adjudication.get('promise') or {}).get('drivers') or []}",
f"- activation: {(adjudication.get('activation') or {}).get('status') or 'missing'} / drivers={(adjudication.get('activation') or {}).get('drivers') or []}",
f"- manifestation: {(adjudication.get('manifestation') or {}).get('status') or 'missing'} / drivers={(adjudication.get('manifestation') or {}).get('drivers') or []}",
f"- label: {(adjudication.get('label') or {}).get('value') or dominant_label or 'none'}",
f"- confidence_boundary: MEVG={confidence_boundary.get('mevg_status') or 'blocked'}; Real Case Calibration={confidence_boundary.get('real_case_calibration_status') or 'blocked'}; policy={confidence_boundary.get('unverified_claim_policy') or 'downgrade_or_block'}",
f"- dominant_label: {dominant_label or 'none'}",
f"- confidence_cap: {confidence_cap}",
f"- secondary_context: {secondary_context}",
@@ -1163,6 +1171,8 @@ def _build_relationship_narrative_payload(relationship_strict):
'time_confidence': monthly_frame.get('time_confidence') or {'value': 'blocked'},
},
'markdown': "\n".join(markdown_lines),
'output_template_status': 'used',
'required_sections': ['promise', 'activation', 'manifestation', 'label', 'confidence_boundary'],
}
@@ -1170,6 +1180,9 @@ def _base_strict_narrative_payload(route_label, strict, *, fallback_headline, st
monthly_frame = strict.get('monthly_adjudication_summary') if isinstance(strict, dict) else {}
monthly_frame = monthly_frame if isinstance(monthly_frame, dict) else {}
event_judgement = strict.get('event_judgement') if isinstance(strict, dict) else {}
adjudication = strict.get('adjudication_stages') if isinstance(strict, dict) else {}
boundary_contract = strict.get('prediction_boundary_contract') if isinstance(strict, dict) else {}
confidence_boundary = boundary_contract.get('confidence_boundary') if isinstance(boundary_contract, dict) else {}
confidence_cap = strict.get('confidence_cap') or event_judgement.get('confidence_cap') or 'unknown'
dominant_label = event_judgement.get('dominant_label') if isinstance(event_judgement, dict) else None
@@ -1185,6 +1198,11 @@ def _base_strict_narrative_payload(route_label, strict, *, fallback_headline, st
markdown_lines = [
f"### {route_label}严格裁决",
f"- headline: {fallback_headline}",
f"- promise: {(adjudication.get('promise') or {}).get('status') or 'missing'} / drivers={(adjudication.get('promise') or {}).get('drivers') or []}",
f"- activation: {(adjudication.get('activation') or {}).get('status') or 'missing'} / drivers={(adjudication.get('activation') or {}).get('drivers') or []}",
f"- manifestation: {(adjudication.get('manifestation') or {}).get('status') or 'missing'} / drivers={(adjudication.get('manifestation') or {}).get('drivers') or []}",
f"- label: {(adjudication.get('label') or {}).get('value') or dominant_label or 'none'}",
f"- confidence_boundary: MEVG={confidence_boundary.get('mevg_status') or 'blocked'}; Real Case Calibration={confidence_boundary.get('real_case_calibration_status') or 'blocked'}; policy={confidence_boundary.get('unverified_claim_policy') or 'downgrade_or_block'}",
f"- dominant_label: {dominant_label or 'none'}",
f"- confidence_cap: {confidence_cap}",
f"- 月度主状态: {monthly_frame.get('primary_state', {}).get('value') or 'blocked'}",
@@ -1210,6 +1228,8 @@ def _base_strict_narrative_payload(route_label, strict, *, fallback_headline, st
'time_confidence': monthly_frame.get('time_confidence') or {'value': 'blocked'},
},
'markdown': "\n".join(markdown_lines),
'output_template_status': 'used',
'required_sections': ['promise', 'activation', 'manifestation', 'label', 'confidence_boundary'],
}
@@ -1439,6 +1459,8 @@ def _compact_strict_workflow_contract(strict):
'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 {},
'oracle_parity_queue': strict.get('oracle_parity_queue') or {},
'release_hygiene_plan': strict.get('release_hygiene_plan') 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 {},
@@ -1600,6 +1622,16 @@ def _build_ai_prompt_pack(report):
if isinstance(primary_strict_contract, dict)
else {}
)
primary_oracle_parity_queue = (
primary_strict_contract.get('oracle_parity_queue')
if isinstance(primary_strict_contract, dict)
else {}
)
primary_release_hygiene_plan = (
primary_strict_contract.get('release_hygiene_plan')
if isinstance(primary_strict_contract, dict)
else {}
)
primary_audit = (
primary_strict_contract.get('technique_audit_summary')
if isinstance(primary_strict_contract, dict)
@@ -1697,6 +1729,8 @@ def _build_ai_prompt_pack(report):
'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 {},
'oracle_parity_queue': primary_oracle_parity_queue or {},
'release_hygiene_plan': primary_release_hygiene_plan or {},
'strict_workflow_primary_route': strict_workflow_primary_route,
'strict_workflow_routes_available': list(strict_workflow_contracts.keys()),
'strict_workflow_contracts': strict_workflow_contracts,
+204
View File
@@ -0,0 +1,204 @@
#!/usr/bin/env python3
"""Golden-output and executable-queue contracts for fortune workflows."""
from __future__ import annotations
import json
import subprocess
import sys
from pathlib import Path
from mcp_server import _collect_strict_evidence
ROOT = Path(__file__).resolve().parents[1]
REQUIRED_OUTPUT_SECTIONS = [
"promise",
"activation",
"manifestation",
"label",
"confidence_boundary",
]
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 _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 test_p0_chinese_golden_narratives_expose_required_contract_sections() -> 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"]
for key in ["career_narrative", "finance_narrative", "relationship_narrative"]:
narrative = snapshot[key]
markdown = narrative["markdown"]
assert narrative["output_template_status"] == "used"
assert narrative["required_sections"] == REQUIRED_OUTPUT_SECTIONS
for section in REQUIRED_OUTPUT_SECTIONS:
assert f"{section}:" in markdown
assert "MEVG" in markdown
assert "Real Case Calibration" in markdown
for route in ["career", "relationship", "finance"]:
contract = snapshot["strict_workflow_contracts"][route]
assert contract["output_template_contract"]["required_sections"] == REQUIRED_OUTPUT_SECTIONS
def test_p1_p2_mevg_queue_and_real_case_index_are_executable_contracts() -> None:
strict = _collect_strict_evidence("career", _base_modules())
queue = strict["mevg_collection_queue"]
assert queue["status"] in {"queued", "blocked"}
assert queue["execution_mode"] == "cache_ttl_free_tier_queue"
assert queue["cache_ttl_hours"] >= 24
assert queue["evidence_packet"]["packet_type"] == "mevg_external_evidence_packet"
assert queue["failure_record"]["status"] == "blocked_until_external_fetch"
assert queue["failure_record"]["blocked_reason"]
case_layer = strict["real_case_calibration_layer"]
assert case_layer["batch_id"] == "real_case_studies_batch1"
assert case_layer["index_status"] == "available"
assert case_layer["fallback_policy"] == "downgrade_without_matching_cases"
assert "relationship" in case_layer["case_index_by_domain"]
assert "docs/benchmark/legacy-marriage-v6.1/verify-results-v6.1.json" in case_layer["case_index_by_domain"]["relationship"]
def test_p3_p4_domain_layers_affect_judgement_and_technical_debt_is_split() -> None:
strict = _collect_strict_evidence("career", _base_modules())
judgement = strict["event_judgement"]
for marker in [
"dasha_timing_layer_used",
"varga_strength_layer_used",
"annual_special_layer_context",
"modifier_obstacle_layer_used",
]:
assert marker in judgement["secondary_context"]
debt = strict["technical_debt_contract"]
assert debt["narayana"]["status_breakdown"]["closed"]
assert debt["narayana"]["status_breakdown"]["blocked"]
assert debt["tajika"]["status_breakdown"]["closed"]
assert debt["tajika"]["status_breakdown"]["blocked"]
assert debt["oracle_parity"]["status"] == "blocked"
def test_p5_p6_p7_p8_frontend_batches_oracle_and_hygiene_are_visible() -> 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["remaining_priority1_batch_queue"]["batch_statuses"]["real_case_studies_batch1"] == "next"
assert snapshot["oracle_parity_queue"]["systems"] == ["VedAstro", "PyJHora", "jyotishganit"]
assert snapshot["oracle_parity_queue"]["priority_domains"] == ["Dasha", "Shadbala", "Tajika", "Narayana"]
assert snapshot["release_hygiene_plan"]["git_sync_required"] is True
assert snapshot["release_hygiene_plan"]["gc_log_policy"] == "separate_safe_cleanup_plan_required"
main_js = (ROOT / "jyotish-app" / "main.js").read_text(encoding="utf-8")
assert "core source refs" in main_js
assert "why confidence downgraded" in main_js
assert "next batch queue" in main_js
assert "oracle parity" in main_js