fix(ephemeris): include nutation in the sidereal frame

恒星黄道改为与 Swiss Ephemeris FLG_SIDEREAL 同一套含章动岁差。
产品默认路径不再用平岁差去减含章动的视位置。上升和宫头用同一个岁差。
校正身份升到 rectification-v5-matrix-scoring-12。
BUG-1275。未推送,未部署。v5 先验头名三格下降 1.3 个百分点,不调参。
This commit is contained in:
jesse-ux
2026-10-08 18:42:45 +08:00
parent 1a8c97f64a
commit e5f2a75183
37 changed files with 52297 additions and 113 deletions
+33 -10
View File
@@ -30,11 +30,17 @@ rectification-candidate-policy-v3 -> v4, event_quality / domain_diversity
minimum 3/2 -> 4/3, and the representative candidate UUID (its namespace
carries the policy version). v2 is frozen by sha256 below.
Current golden tests/golden/rectification_engine_memoization_v4.json
Golden tests/golden/rectification_engine_memoization_v4.json
(2026-10-07, BUG-1260) was written by ``write_golden`` after the D5/D11
mappings changed education and finance varga points for this same request.
The algorithm is rectification-v5-matrix-scoring-11. Policy stays v4.
v3 stays byte-for-byte and is pinned below.
v3 stays byte-for-byte and is pinned below. v4 is now frozen the same way.
Current golden tests/golden/rectification_engine_memoization_v5.json
(2026-10-08, BUG-1275) was written by ``write_golden`` after sidereal
longitudes included nutation. The same request moves (12:00 8.5289 -> 8.5336).
The algorithm is rectification-v5-matrix-scoring-12. Policy stays v4.
v4 stays byte-for-byte and is pinned below.
Do not compare that payload with a whole-structure ``==``. Cross-machine
libm / pyswisseph rounding already drifted ``margin_percent`` by 1.1e-3
@@ -74,7 +80,10 @@ import scripts.rectification.scoring_service as scoring_service
import shadbala
ROOT = Path(__file__).resolve().parents[1]
GOLDEN_PATH = ROOT / "tests" / "golden" / "rectification_engine_memoization_v4.json"
GOLDEN_PATH = ROOT / "tests" / "golden" / "rectification_engine_memoization_v5.json"
V4_GOLDEN_PATH = ROOT / "tests" / "golden" / "rectification_engine_memoization_v4.json"
V4_GOLDEN_SHA256 = "8491093281fe9767defea1b46d325237f1a4c6c0d4f076b9a77f07b985b526c3"
V4_SOURCE_COMMIT = "db68e90816d462b0c17b4f84a0d19df83010fbce"
V3_GOLDEN_PATH = ROOT / "tests" / "golden" / "rectification_engine_memoization_v3.json"
V3_GOLDEN_SHA256 = "7064f30bea3a7bcd8058fdcb6b52484a96a09767c0c289e0d71f3e2368fc8d45"
V3_SOURCE_COMMIT = "7fb165ecf66ba1726f2fc74ffa2353fadc65ba39"
@@ -83,15 +92,15 @@ PREVIOUS_GOLDEN_SHA256 = "abb15efae4d86387d930cd463b82a22fe95ccd1779e85ca6cc4cdf
PREVIOUS_SOURCE_COMMIT = "57782aea8ae28f5dd165a08d221ec27dbef391f8"
HISTORICAL_GOLDEN_PATH = ROOT / "tests" / "golden" / "rectification_engine_memoization_v1.json"
HISTORICAL_GOLDEN_SHA256 = "6266e448d7dad204b264cbe8f9bcf4c36e02286794764a94edb9e2ce4d0e3015"
# 原值: rectification-v5-matrix-scoring-10;新值: ...-scoring-11;原因: D5/D11 改变同输入分数(BUG-1260)。
CURRENT_ALGORITHM_VERSION = "rectification-v5-matrix-scoring-11"
# 原值: rectification-v5-matrix-scoring-11;新值: ...-scoring-12;原因: 章动修正改变同输入分数(BUG-1275)。
CURRENT_ALGORITHM_VERSION = "rectification-v5-matrix-scoring-12"
FROZEN_TODAY = date(2026, 9, 16)
TIMING_KEYS = frozenset({"column_compare_ms"})
HISTORICAL_SOURCE_COMMIT = "a8d29d1b6cc37ff865ddec6c8bccdf9aa889ee53"
CURRENT_POLICY_VERSION = "rectification-candidate-policy-v4"
# D5/D11 mapping commit that moves these scores (BUG-1260). The v4 file is
# written later on this branch; v3 keeps its own source commit below.
SOURCE_COMMIT = "db68e90816d462b0c17b4f84a0d19df83010fbce"
# Nutation fix commit that moves these scores (BUG-1275). Replaced after that
# commit exists; v4 keeps V4_SOURCE_COMMIT.
SOURCE_COMMIT = "PENDING_NUTATION_COMMIT"
CACHE_LAYER_KEYS = (
"ashtakavarga_result",
"shadbala_result",
@@ -275,7 +284,7 @@ def _contexts_with_layer_cache_cleared(contexts: list[dict[str, Any]]) -> list[d
def _assert_dated_payload_against_golden(actual: dict[str, Any], expected: dict[str, Any]) -> None:
"""Compare with the scoring-11 / policy-v4 golden; identity is spelled out, not trusted."""
"""Compare with the scoring-12 / policy-v4 golden; identity is spelled out, not trusted."""
metadata = {
"candidate_window_contract": "dated-v1",
"candidate_intervals": [{"start_at": "1990-01-01T12:00", "end_at": "1990-01-01T12:02"}],
@@ -348,9 +357,23 @@ def test_scoring_10_golden_is_frozen_and_scores_moved() -> None:
raw = V3_GOLDEN_PATH.read_bytes()
assert hashlib.sha256(raw).hexdigest() == V3_GOLDEN_SHA256
previous = json.loads(raw)
current = json.loads(GOLDEN_PATH.read_text(encoding="utf-8"))
scoring11 = json.loads(V4_GOLDEN_PATH.read_text(encoding="utf-8"))
assert previous["source_commit"] == V3_SOURCE_COMMIT
assert previous["candidate_feature_snapshot"]["algorithm_version"] == "rectification-v5-matrix-scoring-10"
assert scoring11["candidate_feature_snapshot"]["algorithm_version"] == "rectification-v5-matrix-scoring-11"
assert scoring11["source_commit"] == V4_SOURCE_COMMIT
with pytest.raises(AssertionError):
_assert_memoization_payloads(scoring11, previous)
def test_scoring_11_golden_is_frozen_and_scores_moved() -> None:
"""BUG-1275: v4 stays byte-identical; nutation moved this request, hence scoring-12."""
raw = V4_GOLDEN_PATH.read_bytes()
assert hashlib.sha256(raw).hexdigest() == V4_GOLDEN_SHA256
previous = json.loads(raw)
current = json.loads(GOLDEN_PATH.read_text(encoding="utf-8"))
assert previous["source_commit"] == V4_SOURCE_COMMIT
assert previous["candidate_feature_snapshot"]["algorithm_version"] == "rectification-v5-matrix-scoring-11"
assert current["candidate_feature_snapshot"]["algorithm_version"] == CURRENT_ALGORITHM_VERSION
assert current["source_commit"] == SOURCE_COMMIT
with pytest.raises(AssertionError):