84e6191fc2
Co-authored-by: Cursor <cursoragent@cursor.com>
182 lines
6.6 KiB
Python
182 lines
6.6 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from kp_system import KP_LORDS
|
|
from scripts.active_rectification_event_engine import (
|
|
build_candidate_static_context,
|
|
compute_event_candidate_rows,
|
|
)
|
|
from scripts.rectification.decision_policy import (
|
|
build_candidate_decisions,
|
|
build_decision_receipt,
|
|
build_technique_audit,
|
|
)
|
|
from scripts.rectification.kp_cusp_observation import observe_kp_cusps
|
|
from scripts.rectification.refinement_packet import window_scan
|
|
|
|
|
|
def _request() -> dict:
|
|
return {
|
|
"birth_date": "1993-04-17",
|
|
"start_time": "14:29",
|
|
"end_time": "14:30",
|
|
"lat": 36.683333,
|
|
"lon": 114.35,
|
|
"tz": 8.0,
|
|
"events": [{
|
|
"id": "5cb071d6-6d99-46be-85dc-a9bf59ef6ac5",
|
|
"domain": "career",
|
|
"date": "2019-07-01",
|
|
"precision": "day",
|
|
}],
|
|
}
|
|
|
|
|
|
def _score_request() -> dict:
|
|
return {
|
|
"events": [
|
|
{
|
|
"id": "00000000-0000-4000-8000-000000000001",
|
|
"domain": "career",
|
|
"summary": "入职",
|
|
"event_kind": "career_entry",
|
|
"precision": "day",
|
|
"date_start": "2016-09-15",
|
|
"date_end": "2016-09-15",
|
|
},
|
|
{
|
|
"id": "00000000-0000-4000-8000-000000000002",
|
|
"domain": "relationship",
|
|
"summary": "开始一段关系",
|
|
"event_kind": "relationship_start",
|
|
"precision": "day",
|
|
"date_start": "2018-03-01",
|
|
"date_end": "2018-03-01",
|
|
},
|
|
{
|
|
"id": "00000000-0000-4000-8000-000000000003",
|
|
"domain": "education",
|
|
"summary": "毕业",
|
|
"event_kind": "education_completion",
|
|
"precision": "day",
|
|
"date_start": "2015-06-01",
|
|
"date_end": "2015-06-01",
|
|
},
|
|
{
|
|
"id": "00000000-0000-4000-8000-000000000004",
|
|
"domain": "family",
|
|
"summary": "家人变化",
|
|
"event_kind": "family_event",
|
|
"precision": "day",
|
|
"date_start": "2020-01-01",
|
|
"date_end": "2020-01-01",
|
|
},
|
|
]
|
|
}
|
|
|
|
|
|
def _diagnostics() -> dict:
|
|
return {
|
|
"leave_one_event_out_retention_rate": 1,
|
|
"leave_one_domain_out_retention_rate": 1,
|
|
"date_sensitivity_retention_rate": 1,
|
|
"primary_secondary_margin_percent": 50,
|
|
}
|
|
|
|
|
|
def test_observe_kp_cusps_uses_placidus_not_equal_houses() -> None:
|
|
context = build_candidate_static_context(_request(), datetime(1993, 4, 17, 14, 29))
|
|
feature = context["feature"]
|
|
snapshot = feature["kp_cusps"]
|
|
natal_houses = context["chart"]["houses"]
|
|
assert snapshot["status"] == "executed"
|
|
assert snapshot["house_system"] == "placidus"
|
|
assert snapshot["ayanamsa"] == "krishnamurti"
|
|
assert len(snapshot["houses"]) == 12
|
|
tenth = snapshot["houses"]["10"]
|
|
equal_tenth = float(natal_houses["house_10"]["cusp_degree"])
|
|
assert abs(float(tenth["cusp_degree"]) - equal_tenth) > 0.05
|
|
assert tenth["sub_lord"] in KP_LORDS
|
|
assert isinstance(feature["kp1_sub_index"], int)
|
|
assert 0 <= feature["kp1_sub_index"] <= 8
|
|
assert "KP_cusps" not in feature["blocked_layers"]
|
|
assert "KP_cusps" in feature["available_layers"]
|
|
|
|
|
|
def test_kp_observation_is_absent_from_scoring_missing_layers() -> None:
|
|
request = _request()
|
|
context = build_candidate_static_context(request, datetime(1993, 4, 17, 14, 29))
|
|
rows = compute_event_candidate_rows(request, static_contexts=[context])
|
|
assert rows
|
|
assert "KP_cusps" not in rows[0]["missing_layers"]
|
|
assert context["feature"]["kp_cusps"]["status"] == "executed"
|
|
|
|
|
|
def test_window_scan_emits_kp_sub_lord_changes_without_confirmation() -> None:
|
|
scan = window_scan({
|
|
"static_contexts": [
|
|
{"feature": {"time": "05:13", "kp1_sub_index": 1, "kp4_sub_index": 2, "kp7_sub_index": 3, "kp10_sub_index": 4}},
|
|
{"feature": {"time": "05:14", "kp1_sub_index": 2, "kp4_sub_index": 2, "kp7_sub_index": 3, "kp10_sub_index": 4}},
|
|
]
|
|
})
|
|
meanings = [item["user_meaning"] for item in scan["transitions"]]
|
|
assert "KP 1宫子主 在 05:14 发生变化" in meanings
|
|
assert "KP 4宫子主 在 05:14 发生变化" not in meanings
|
|
encoded = str(scan)
|
|
assert "白羊" not in encoded
|
|
assert "Aries" not in encoded
|
|
assert scan["confirmation_allowed"] is False
|
|
assert scan["unique_minute_claim"] is False
|
|
|
|
|
|
def test_technique_audit_kp_executed_when_snapshot_present() -> None:
|
|
rows = build_technique_audit(
|
|
{
|
|
"matrix": {},
|
|
"static_contexts": [{
|
|
"feature": {
|
|
"time": "05:13",
|
|
"kp_cusps": {"status": "executed", "house_system": "placidus", "ayanamsa": "krishnamurti"},
|
|
}
|
|
}],
|
|
},
|
|
house_table={"time": "05:13", "lagna": "金牛座"},
|
|
)
|
|
kp = next(row for row in rows if row["technique"] == "KP 宫头")
|
|
assert kp["status"] == "executed"
|
|
assert "政策跳过" not in kp["note"]
|
|
assert "不计分" in kp["note"]
|
|
|
|
|
|
def test_technique_audit_kp_blocked_is_honest_and_does_not_fail_propose() -> None:
|
|
rows = build_technique_audit({"matrix": {}, "static_contexts": []}, house_table=None)
|
|
kp = next(row for row in rows if row["technique"] == "KP 宫头")
|
|
assert kp["status"] == "blocked"
|
|
assert "政策跳过" not in kp["note"]
|
|
decisions = build_candidate_decisions(
|
|
[{"time": "05:13", "score": 20, "evidence": [], "missing_layers": []},
|
|
{"time": "05:14", "score": 8, "evidence": [], "missing_layers": []}],
|
|
result_id="00000000-0000-4000-8000-000000000099",
|
|
)
|
|
receipt = build_decision_receipt(
|
|
_score_request(),
|
|
decisions,
|
|
{"missing_layers": [], "matrix": {}, "static_contexts": [{"feature": {"time": "05:13", "kp_cusps": {"status": "blocked"}}}]},
|
|
_diagnostics(),
|
|
)
|
|
assert receipt["gates"]["required_layers"]["passed"] is True
|
|
assert receipt["propose_allowed"] is True
|
|
audit = next(row for row in receipt["technique_audit_table"] if row["technique"] == "KP 宫头")
|
|
assert audit["status"] == "blocked"
|
|
assert "政策跳过" not in audit["note"]
|
|
|
|
|
|
def test_observe_kp_cusps_blocks_without_inventing_whole_sign_proxy() -> None:
|
|
snapshot = observe_kp_cusps(None, 36.6, 114.3)
|
|
assert snapshot["status"] == "blocked"
|
|
assert snapshot["houses"] == {}
|
|
polar = observe_kp_cusps(2451545.0, 80.0, 0.0)
|
|
assert polar["status"] == "blocked"
|
|
assert polar["houses"] == {}
|