The review found empty sections and an English job that stayed running. Take evidence from reader briefs, retry one section, and settle before marking the report ready. Co-Authored-By: Grok (agent loop) Co-authored-by: Cursor <cursoragent@cursor.com>
211 lines
12 KiB
Python
211 lines
12 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
MODULE_PATH = ROOT / "skills" / "jyotish-full-synastry-reading" / "scripts" / "validate_bilingual_synastry_delivery.py"
|
|
spec = importlib.util.spec_from_file_location("bilingual_synastry_delivery", MODULE_PATH)
|
|
module = importlib.util.module_from_spec(spec)
|
|
assert spec and spec.loader
|
|
spec.loader.exec_module(module)
|
|
|
|
|
|
def _full_chinese_report() -> str:
|
|
headings = ["结论总纲", "各自带入关系的需求", "情绪安全与相处感受", "吸引与亲密", "沟通、冲突与修复", "关系如何推进", "共同生活的收益与压力", "能不能稳定走下去", "关系应期"]
|
|
prose = "双方需要清楚说明节奏、边界、现实安排与实际互动;任何判断都需由两人的现实经验验证,不能由单一配置替代。"
|
|
sections = []
|
|
for heading in headings:
|
|
suffix = "D9 婚姻分盘用于检验长期承诺的结构,不能代替本命互动。" if heading == "能不能稳定走下去" else ""
|
|
sections.append(f"{heading}\n{(prose * 5) + suffix}")
|
|
return "\n".join(sections)
|
|
|
|
|
|
def _full_english_report() -> str:
|
|
headings = [
|
|
"Relationship Thesis", "What Each Person Brings", "Emotional Safety and Lived Experience",
|
|
"Attraction and Closeness", "Communication, Conflict and Repair",
|
|
"How the Relationship Progresses", "Shared Life: Gains and Pressures",
|
|
"Can It Stay Steady?", "Relationship Weather",
|
|
]
|
|
prose = "Each conclusion remains conditional on both charts, actual interaction, practical circumstances, and repeated real-world observation by both people. "
|
|
sections = []
|
|
for heading in headings:
|
|
suffix = "Navamsa (D9) qualifies long-term commitment and does not replace lived natal interaction. " if heading == "Can It Stay Steady?" else ""
|
|
sections.append(f"{heading}\n{(prose * 8) + suffix}")
|
|
return "\n".join(sections)
|
|
|
|
|
|
def test_receipt_requires_independent_full_report_shapes_without_forced_term_dumping():
|
|
dossier = {
|
|
"schema": "jyotish.full_synastry_dossier.v1",
|
|
"delivery_readiness": "ready_for_narrative",
|
|
"source_map": [],
|
|
"execution_receipt": {"pair_execution_tasks": []},
|
|
}
|
|
chinese = _full_chinese_report()
|
|
english = _full_english_report()
|
|
receipt = module.build_delivery_receipt(dossier, chinese, english)
|
|
assert receipt["status"] == "passed"
|
|
assert receipt["composition"]["english"] == "direct_from_structured_dossier_not_translated_from_chinese"
|
|
assert not any(receipt["supplementary_method_terms"]["english"].values())
|
|
|
|
|
|
def test_receipt_rejects_incomplete_or_chinese_english_delivery():
|
|
receipt = module.build_delivery_receipt({"delivery_readiness": "blocked"}, "结论总纲", "结论总纲")
|
|
assert receipt["status"] == "review_required"
|
|
|
|
|
|
def test_receipt_allows_primary_jyotish_terms_but_hides_supplementary_method_names():
|
|
dossier = {
|
|
"schema": "jyotish.full_synastry_dossier.v1",
|
|
"delivery_readiness": "ready_for_narrative",
|
|
"source_map": [],
|
|
"execution_receipt": {"pair_execution_tasks": []},
|
|
}
|
|
chinese = _full_chinese_report() + "\nD9 与 UL 的结论在此一致"
|
|
english = _full_english_report() + "\nNavamsa Upapada Darakaraka Vimshottari Narayana"
|
|
assert module.build_delivery_receipt(dossier, chinese, english)["status"] == "passed"
|
|
assert module.build_delivery_receipt(dossier, chinese, english + "\nWestern synastry")["status"] == "review_required"
|
|
assert module.build_delivery_receipt(dossier, chinese, english + "\nexecution_receipt")["status"] == "review_required"
|
|
assert module.build_delivery_receipt(dossier, chinese, english + "\nreader_section_brief")["status"] == "review_required"
|
|
|
|
|
|
def test_receipt_rejects_heading_only_or_fated_language():
|
|
dossier = {"schema": "jyotish.full_synastry_dossier.v1", "delivery_readiness": "ready_for_narrative", "source_map": [], "execution_receipt": {"pair_execution_tasks": []}}
|
|
assert module.build_delivery_receipt(dossier, "结论总纲", "Relationship Thesis")["reader_depth"]["status"] == "review_required"
|
|
assert module.build_delivery_receipt(dossier, _full_chinese_report() + "灵魂伴侣", _full_english_report())["status"] == "review_required"
|
|
|
|
|
|
def test_receipt_rejects_analyst_led_not_x_but_y_opening():
|
|
dossier = {"schema": "jyotish.full_synastry_dossier.v1", "delivery_readiness": "ready_for_narrative", "source_map": [], "execution_receipt": {"pair_execution_tasks": []}}
|
|
chinese = _full_chinese_report().replace("结论总纲", "结论总纲\n这段关系的核心,不是有没有吸引,而是能否落实承诺。", 1)
|
|
receipt = module.build_delivery_receipt(dossier, chinese, _full_english_report())
|
|
assert receipt["opening_quality"]["status"] == "review_required"
|
|
assert receipt["status"] == "review_required"
|
|
|
|
|
|
def test_receipt_requires_warm_reciprocal_opening_when_affection_evidence_is_executed():
|
|
dossier = {
|
|
"schema": "jyotish.full_synastry_dossier.v1",
|
|
"delivery_readiness": "ready_for_narrative",
|
|
"source_map": [],
|
|
"execution_receipt": {"pair_execution_tasks": []},
|
|
"mutual_affection_activation": {"status": "executed"},
|
|
}
|
|
cold_chinese = _full_chinese_report()
|
|
cold_english = _full_english_report()
|
|
cold = module.build_delivery_receipt(dossier, cold_chinese, cold_english)
|
|
assert cold["opening_affection_coverage"]["required_in_opening"] is True
|
|
assert cold["status"] == "review_required"
|
|
|
|
chinese = cold_chinese.replace(
|
|
"结论总纲\n", "结论总纲\nA 会在 B 的稳定回应里感到被重视与安心,B 也会在 A 的投入中感到被珍惜。\n", 1,
|
|
)
|
|
english = cold_english.replace(
|
|
"Relationship Thesis\n", "Relationship Thesis\nA feels valued and safe in B's steady response, while B feels cherished by A's investment.\n", 1,
|
|
)
|
|
receipt = module.build_delivery_receipt(dossier, chinese, english)
|
|
assert receipt["opening_affection_coverage"]["chinese_terms"]
|
|
assert receipt["opening_affection_coverage"]["english_terms"]
|
|
assert receipt["attraction_reciprocity_coverage"]["status"] == "review_required"
|
|
|
|
|
|
def test_receipt_rejects_long_report_with_empty_reader_sections():
|
|
dossier = {
|
|
"schema": "jyotish.full_synastry_dossier.v1",
|
|
"delivery_readiness": "ready_for_narrative",
|
|
"source_map": [],
|
|
"execution_receipt": {"pair_execution_tasks": []},
|
|
}
|
|
headings_zh = "\n".join(["结论总纲", "各自带入关系的需求", "情绪安全与相处感受", "吸引与亲密", "沟通、冲突与修复", "关系如何推进", "共同生活的收益与压力", "能不能稳定走下去", "关系应期"])
|
|
headings_en = "\n".join(["Relationship Thesis", "What Each Person Brings", "Emotional Safety and Lived Experience", "Attraction and Closeness", "Communication, Conflict and Repair", "How the Relationship Progresses", "Shared Life: Gains and Pressures", "Can It Stay Steady?", "Relationship Weather"])
|
|
receipt = module.build_delivery_receipt(
|
|
dossier,
|
|
headings_zh + "\n" + "双方需要核对实际互动与现实安排。" * 140,
|
|
headings_en + "\n" + "Both people need to verify practical interaction and real circumstances before drawing conclusions. " * 180,
|
|
)
|
|
assert receipt["reader_depth"]["status"] == "passed"
|
|
assert receipt["section_depth_coverage"]["status"] == "review_required"
|
|
assert receipt["status"] == "review_required"
|
|
|
|
|
|
def test_section_depth_recognizes_markdown_and_numbered_headings():
|
|
chinese = "## 一、结论总纲\n" + "双方需要把现实互动说清。" * 20
|
|
english = "## I. Relationship Thesis\n" + "Both people need clear real-world interaction before conclusions. " * 20
|
|
assert module._section_bodies(chinese, ("结论总纲",))["结论总纲"]
|
|
assert module._section_bodies(english, ("Relationship Thesis",))["Relationship Thesis"]
|
|
|
|
|
|
def test_receipt_requires_warmth_and_space_in_attraction_section_when_evidence_exists():
|
|
dossier = {
|
|
"schema": "jyotish.full_synastry_dossier.v1",
|
|
"delivery_readiness": "ready_for_narrative",
|
|
"source_map": [],
|
|
"execution_receipt": {"pair_execution_tasks": []},
|
|
"mutual_affection_activation": {"status": "executed"},
|
|
}
|
|
chinese = _full_chinese_report().replace(
|
|
"结论总纲\n", "结论总纲\nA 会在 B 的稳定回应里感到被重视与安心,B 也会在 A 的投入中感到被珍惜。\n", 1,
|
|
)
|
|
english = _full_english_report().replace(
|
|
"Relationship Thesis\n", "Relationship Thesis\nA feels valued and safe in B's steady response, while B feels cherished by A's investment.\n", 1,
|
|
)
|
|
cold_attraction = module.build_delivery_receipt(dossier, chinese, english)
|
|
assert cold_attraction["attraction_reciprocity_coverage"]["status"] == "review_required"
|
|
|
|
chinese = chinese.replace("吸引与亲密\n", "吸引与亲密\n双方在被珍惜时更愿意靠近,也要为彼此保留空间,避免压力累积。\n", 1)
|
|
english = english.replace("Attraction and Closeness\n", "Attraction and Closeness\nBoth feel warmer and closer when valued, while each needs space so pressure does not accumulate.\n", 1)
|
|
receipt = module.build_delivery_receipt(dossier, chinese, english)
|
|
assert receipt["attraction_reciprocity_coverage"]["status"] == "passed"
|
|
assert receipt["status"] == "passed"
|
|
|
|
|
|
def test_receipt_requires_d9_narrative_when_native_d9_pair_evidence_executed():
|
|
dossier = {
|
|
"schema": "jyotish.full_synastry_dossier.v1",
|
|
"delivery_readiness": "ready_for_narrative",
|
|
"source_map": [],
|
|
"execution_receipt": {"pair_execution_tasks": []},
|
|
"pair_interaction_evidence": {"d9_interaction_evidence": {"status": "executed"}},
|
|
}
|
|
receipt = module.build_delivery_receipt(dossier, _full_chinese_report(), _full_english_report())
|
|
assert receipt["status"] == "passed"
|
|
assert receipt["d9_narrative_coverage"]["required_in_narrative"] is True
|
|
without_d9 = _full_chinese_report().replace("D9 婚姻分盘用于检验长期承诺的结构,不能代替本命互动。", "")
|
|
assert module.build_delivery_receipt(dossier, without_d9, _full_english_report())["status"] == "review_required"
|
|
|
|
|
|
def test_single_language_receipt_accepts_an_independent_chinese_delivery():
|
|
dossier = {
|
|
"schema": "jyotish.full_synastry_dossier.v1",
|
|
"delivery_readiness": "ready_for_narrative",
|
|
"source_map": [],
|
|
"execution_receipt": {"pair_execution_tasks": []},
|
|
}
|
|
receipt = module.build_single_language_delivery_receipt(
|
|
dossier, _full_chinese_report(), "zh",
|
|
)
|
|
assert receipt["status"] == "passed"
|
|
assert receipt["schema"] == module.SINGLE_LANGUAGE_SCHEMA
|
|
assert receipt["composition"] == "direct_from_structured_dossier"
|
|
|
|
|
|
def test_single_language_receipt_keeps_affection_and_section_gates():
|
|
dossier = {
|
|
"schema": "jyotish.full_synastry_dossier.v1",
|
|
"delivery_readiness": "ready_for_narrative",
|
|
"source_map": [],
|
|
"execution_receipt": {"pair_execution_tasks": []},
|
|
"mutual_affection_activation": {"status": "executed"},
|
|
}
|
|
receipt = module.build_single_language_delivery_receipt(dossier, _full_chinese_report(), "zh")
|
|
assert receipt["status"] == "review_required"
|
|
warm = _full_chinese_report().replace(
|
|
"结论总纲\n", "结论总纲\n双方在稳定回应中感到被重视与珍惜,也能安心靠近。\n", 1,
|
|
).replace(
|
|
"吸引与亲密\n", "吸引与亲密\n彼此被珍惜时更愿意靠近,也需保留空间和边界,避免压力累积。\n", 1,
|
|
)
|
|
assert module.build_single_language_delivery_receipt(dossier, warm, "zh")["status"] == "passed"
|