Files
Jyotisha/scripts/tajika_named_yoga_governed_draft.py
T
Jesse_Chen bab0718700
Independent Staging Quality Gate / validate (push) Failing after 9m41s
Independent Staging Quality Gate / publish (push) Has been skipped
feat(report): ship full-mode longform appendix beside the five-chapter report
Web export now calls the same full pack as the long skill report and caches an owner-only Markdown download. Appendix failure stays unavailable and does not change the main report status.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-05 11:10:44 +08:00

106 lines
3.7 KiB
Python
Executable File

"""Governed named-yoga draft built from shared Tajika motion evidence.
This module does not promote named yogas into authority. It packages kernel
candidate relations into a review-ready draft so the remaining closure can be
resolved under one governed vocabulary.
"""
from __future__ import annotations
from typing import Any
try:
from tajika_kernel import calculate_tajika_interactions
except ImportError: # pragma: no cover - package import
from scripts.tajika_kernel import calculate_tajika_interactions
SCHEMA_VERSION = "jyotish.tajika_named_yoga_governed_draft.v1"
_CANDIDATE_TO_NAMED = {
"Ithasala_candidate": "Ithasala",
"Easarapha_candidate": "Easarapha",
}
def build_tajika_named_yoga_governed_draft(planets: dict[str, dict[str, Any]]) -> dict[str, Any]:
"""Package Tajika kernel candidate relations as a review-only draft."""
if not isinstance(planets, dict):
raise ValueError("planets_required")
kernel = calculate_tajika_interactions(planets)
if kernel.get("status") == "blocked":
return {
"schema_version": SCHEMA_VERSION,
"status": "blocked",
"authority_ready": False,
"claim_boundary": "governed_named_yoga_draft_requires_complete_seven_planet_kernel_inputs",
"reason": kernel.get("reason") or "tajika_kernel_blocked",
"missing": list(kernel.get("missing") or []),
"rows": [],
"summary": {
"row_count": 0,
"named_yoga_counts": {},
"motion_counts": {},
},
"limitations": [
"kernel_input_missing",
"no_named_yoga_authority",
"draft_does_not_promote_verdict",
],
}
rows: list[dict[str, Any]] = []
for item in kernel.get("candidate_yogas") or []:
if not isinstance(item, dict):
continue
named_yoga = _CANDIDATE_TO_NAMED.get(str(item.get("name") or ""))
if not named_yoga:
continue
rows.append(
{
"named_yoga": named_yoga,
"candidate_name": item.get("name"),
"planets": list(item.get("planets") or []),
"aspect": item.get("aspect"),
"motion": item.get("motion"),
"average_deeptamsa": item.get("average_deeptamsa"),
"residual": item.get("residual"),
"rule_source": item.get("rule_source"),
"review_status": "governed_seed_resolution_review_required",
"resolution_state": "governed_seed_resolution_draft",
"claim_boundary": "candidate_relation_only_no_named_yoga_authority",
}
)
return {
"schema_version": SCHEMA_VERSION,
"status": "draft_only",
"authority_ready": False,
"claim_boundary": "governed_named_yoga_draft_only_no_named_yoga_verdict_or_promotion",
"kernel_status": kernel.get("status"),
"kernel_boundary": kernel.get("boundary"),
"rows": rows,
"summary": {
"row_count": len(rows),
"named_yoga_counts": _count(rows, "named_yoga"),
"motion_counts": _count(rows, "motion"),
},
"limitations": [
"candidate_relations_only",
"no_named_yoga_authority",
"no_final_judgment",
"governed_seed_review_required_before_promotion",
],
}
def _count(rows: list[dict[str, Any]], key: str) -> dict[str, int]:
counts: dict[str, int] = {}
for row in rows:
value = row.get(key)
if value in (None, ""):
continue
value = str(value)
counts[value] = counts.get(value, 0) + 1
return counts