From ab55eca4f4b238bbb3d3b6dbf0daf8d059c632d9 Mon Sep 17 00:00:00 2001 From: zhenheco Date: Tue, 15 Sep 2026 10:16:56 +0700 Subject: [PATCH] fix: correct Human Design gate wheel OFFSET (-1.375 -> -1.75) scripts/chart_engine.py's gate_line() used OFFSET=-1.375, shifting the whole 64-gate Human Design wheel 0.375 deg from the published mandala (barneyandflow.com/gate-zodiac-degrees; Scribd "Gates and Zodiac Placements"): Gate 25 starts 358.25 deg, Gate 17 starts 3.875 deg, Gate 41 starts 302.0 deg. Only OFFSET=-1.75 puts all three anchors in their documented gate. Independently confirmed by npm hd-chart-engine@0.1.1 (WHEEL_START=223.25 = -1.75 + 40*5.625), already used by life-web's question-first path. At the wrong offset, ~6.5% of gate activations land in the wrong gate and ~83% of charts have at least one wrong gate. TDD: tests/test_human_design_gate_wheel_offset.py pins the three published mandala boundaries plus a preceding-gate, previous-line and 0 deg wrap-around case; all failed under -1.375 and pass under -1.75. Every Human Design fixture generated by the old offset is regenerated from the corrected engine, not hand-edited: - tests/fixtures/ephemeris_baseline.json via the new tests/fixtures/update_hd_baseline.py (11 of 12 fixtures' human_design changed; jupiter_station_before also changes type/authority/definition/ channels; the two human_design_boundary annotations are recomputed for the corrected wheel rather than left describing the old wheel's boundary). PROTECTED_SHA256 in tests/test_synastry_cli.py is updated deliberately for this regeneration, per its own comment. - tests/fixtures/golden_example.json/.md and examples/sample-output.json via their existing GOLDEN_PROVENANCE.md commands. - tests/fixtures/golden_example_pre_1_2.json is regenerated too (a documented exception): it freezes "1.1 -> 1.2 only adds one field", not a known-wrong gate wheel, so leaving it stale would permanently pin the bug through test_single_json_bytes_match_pre_1_2_after_version_bump. - tests/test_synastry_hd.py's test_time_unknown_channel_confidence_exhaustive_split_pinned pinned B0's noon fast-planet gate set, which also shifts under the corrected wheel (gate 60 -> 41), dropping the hd-chan-3-60 connection. - README.md and all 18 translations' Human Design sample snippet (profile 1/3 -> 2/4, gate 12.1/36.3 -> 12.2/36.4). See tests/fixtures/GOLDEN_PROVENANCE.md's 2026-09-15 entry for the full diff-scope writeup and regeneration commands. pyproject.toml version bumped 1.2.0 -> 1.2.1 (patch; no CHANGELOG file exists in this repo). schema_version stays "1.2" (JSON contract shape is unchanged). Full suite: 447 passed, 2 skipped (same 2 pre-existing skips as baseline; 441 passed before this change's 6 new anchor tests). Claude-Session: https://claude.ai/code/session_016ZLLbCYxw9wxqX6rsSrbMX --- README.ar.md | 6 +- README.de.md | 6 +- README.es.md | 6 +- README.fr.md | 6 +- README.hi.md | 6 +- README.id.md | 6 +- README.it.md | 6 +- README.ja.md | 6 +- README.ko.md | 6 +- README.md | 6 +- README.nl.md | 6 +- README.pl.md | 6 +- README.pt.md | 6 +- README.ru.md | 6 +- README.th.md | 6 +- README.tr.md | 6 +- README.vi.md | 6 +- README.zh-CN.md | 6 +- README.zh-TW.md | 6 +- examples/sample-output.json | 22 +- pyproject.toml | 2 +- scripts/chart_engine.py | 2 +- tests/fixtures/GOLDEN_PROVENANCE.md | 52 +++ tests/fixtures/ephemeris_baseline.json | 344 ++++++++++--------- tests/fixtures/golden_example.json | 24 +- tests/fixtures/golden_example.md | 18 +- tests/fixtures/golden_example_pre_1_2.json | 24 +- tests/fixtures/update_hd_baseline.py | 189 ++++++++++ tests/test_human_design_gate_wheel_offset.py | 46 +++ tests/test_synastry_cli.py | 7 +- tests/test_synastry_hd.py | 8 +- 31 files changed, 575 insertions(+), 277 deletions(-) create mode 100644 tests/fixtures/update_hd_baseline.py create mode 100644 tests/test_human_design_gate_wheel_offset.py diff --git a/README.ar.md b/README.ar.md index 39bef9b..68659b0 100644 --- a/README.ar.md +++ b/README.ar.md @@ -144,7 +144,7 @@ iztro@2.5.8 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ iztro@2.5.8 "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ iztro@2.5.8 "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.de.md b/README.de.md index 1dd7087..3373549 100644 --- a/README.de.md +++ b/README.de.md @@ -144,7 +144,7 @@ Gekürzte echte Probe (Aspekte sind in Markdown-Modus auf Top-10 begrenzt): 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Gekürzte echte Probe (Arrays auf 1–2 Einträge gekürzt; Werte wörtlich): "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Gekürzte echte Probe (Arrays auf 1–2 Einträge gekürzt; Werte wörtlich): "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.es.md b/README.es.md index 6abeeea..6085757 100644 --- a/README.es.md +++ b/README.es.md @@ -144,7 +144,7 @@ Muestra real recortada (los aspectos se limitan a los 10 mejores en modo Markdow 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Muestra real recortada (matrices truncadas a 1–2 entradas; valores literales): "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Muestra real recortada (matrices truncadas a 1–2 entradas; valores literales): "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.fr.md b/README.fr.md index e64431e..ebd2182 100644 --- a/README.fr.md +++ b/README.fr.md @@ -144,7 +144,7 @@ Exemple réel élagué (les aspects sont plafonnés aux 10 premiers en mode Mark 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Exemple réel élagué (les tableaux sont tronqués à 1–2 entrées ; les vale "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Exemple réel élagué (les tableaux sont tronqués à 1–2 entrées ; les vale "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.hi.md b/README.hi.md index c112a7b..5f58b40 100644 --- a/README.hi.md +++ b/README.hi.md @@ -144,7 +144,7 @@ Engine अभी verified **CPython 3.12** runtime पर चलता है। 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Engine अभी verified **CPython 3.12** runtime पर चलता है। "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Engine अभी verified **CPython 3.12** runtime पर चलता है। "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.id.md b/README.id.md index 7f7b375..27cbfdb 100644 --- a/README.id.md +++ b/README.id.md @@ -144,7 +144,7 @@ Sampel nyata terpangkas (aspek terbatas pada top-10 dalam mode Markdown): 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Sampel nyata terpangkas (array terpotong menjadi 1–2 entri; nilai verbatim): "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Sampel nyata terpangkas (array terpotong menjadi 1–2 entri; nilai verbatim): "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.it.md b/README.it.md index 18d4846..9b8e1db 100644 --- a/README.it.md +++ b/README.it.md @@ -144,7 +144,7 @@ Esempio reale ritagliato (gli aspetti sono limitati a top-10 in modalità Markdo 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Esempio reale ritagliato (array troncati a 1–2 elementi; valori verbatim): "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Esempio reale ritagliato (array troncati a 1–2 elementi; valori verbatim): "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.ja.md b/README.ja.md index 0e96fb0..3498863 100644 --- a/README.ja.md +++ b/README.ja.md @@ -144,7 +144,7 @@ iztro@2.5.8 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ iztro@2.5.8 "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ iztro@2.5.8 "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.ko.md b/README.ko.md index f519d3c..9c588b8 100644 --- a/README.ko.md +++ b/README.ko.md @@ -144,7 +144,7 @@ iztro@2.5.8 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ iztro@2.5.8 "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ iztro@2.5.8 "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.md b/README.md index a3c3d36..3bb628f 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ Trimmed real sample (aspects are capped at top-10 in Markdown mode): 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -236,7 +236,7 @@ Trimmed real sample (arrays truncated to 1–2 entries; values verbatim): "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -244,7 +244,7 @@ Trimmed real sample (arrays truncated to 1–2 entries; values verbatim): "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.nl.md b/README.nl.md index 6c04671..ed606f9 100644 --- a/README.nl.md +++ b/README.nl.md @@ -144,7 +144,7 @@ Ingekort reëel voorbeeld (aspecten zijn beperkt tot top-10 in Markdown-modus): 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Ingekort reëel voorbeeld (arrays afgekapt tot 1–2 invoer; waarden woordelijk) "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Ingekort reëel voorbeeld (arrays afgekapt tot 1–2 invoer; waarden woordelijk) "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.pl.md b/README.pl.md index f1c1267..a13b3eb 100644 --- a/README.pl.md +++ b/README.pl.md @@ -144,7 +144,7 @@ Przycięty przykład ze świata rzeczywistego (aspekty są ograniczone do 10 pie 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Przycięty przykład ze świata rzeczywistego (tablice skrócone do 1–2 wpisó "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Przycięty przykład ze świata rzeczywistego (tablice skrócone do 1–2 wpisó "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.pt.md b/README.pt.md index be805a9..e957692 100644 --- a/README.pt.md +++ b/README.pt.md @@ -144,7 +144,7 @@ Amostra real aparada (aspectos são limitados aos 10 principais no modo Markdown 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Amostra real aparada (arrays truncados para 1–2 entradas; valores verbatim): "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Amostra real aparada (arrays truncados para 1–2 entradas; valores verbatim): "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.ru.md b/README.ru.md index 74e0f57..63f5f35 100644 --- a/README.ru.md +++ b/README.ru.md @@ -144,7 +144,7 @@ iztro@2.5.8 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ iztro@2.5.8 "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ iztro@2.5.8 "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.th.md b/README.th.md index b3579ef..0b9e8e0 100644 --- a/README.th.md +++ b/README.th.md @@ -144,7 +144,7 @@ iztro@2.5.8 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ iztro@2.5.8 "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ iztro@2.5.8 "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.tr.md b/README.tr.md index 6085720..314584c 100644 --- a/README.tr.md +++ b/README.tr.md @@ -144,7 +144,7 @@ Kesilmiş gerçek örnek (yönler Markdown modunda ilk 10 ile sınırlıdır): 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Kesilmiş gerçek örnek (diziler 1–2 giriş ile kesilmiş; değerler olduğu "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Kesilmiş gerçek örnek (diziler 1–2 giriş ile kesilmiş; değerler olduğu "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.vi.md b/README.vi.md index f2f33bf..be0f940 100644 --- a/README.vi.md +++ b/README.vi.md @@ -144,7 +144,7 @@ Mẫu thực được cắt ngắn (các khía cạnh được capped ở top-10 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -199,7 +199,7 @@ Mẫu thực được cắt ngắn (mảng bị cắt ngắn thành 1–2 mục; "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -207,7 +207,7 @@ Mẫu thực được cắt ngắn (mảng bị cắt ngắn thành 1–2 mục; "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.zh-CN.md b/README.zh-CN.md index 1dfd15b..a0a8ca2 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -158,7 +158,7 @@ iztro@2.5.8 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -213,7 +213,7 @@ iztro@2.5.8 "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -221,7 +221,7 @@ iztro@2.5.8 "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/README.zh-TW.md b/README.zh-TW.md index cc03aed..d0ee1fa 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -158,7 +158,7 @@ iztro@2.5.8 主要相位: 北交點-南交點對分(0.0°);北交點-上升對分(0.4°);南交點-上升合相(0.4°);木星-冥王星三分(0.4°);月亮-天王星六分(0.8°)… 【人類圖 Human Design】 -類型 投射者 | 權威 自我投射型權威 | 角色 1/3 | 定義 一分人(單一定義) +類型 投射者 | 權威 自我投射型權威 | 角色 2/4 | 定義 一分人(單一定義) 輪迴交叉 右角度交叉(12/11 | 36/6) 定義中心 G,喉 | 開放中心 情緒,意志,根,脾,薦骨,邏輯,頭 設計日期 1990-03-16 @@ -213,7 +213,7 @@ iztro@2.5.8 "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -221,7 +221,7 @@ iztro@2.5.8 "open_centers": ["情緒", "意志", "根", "脾", "薦骨", "邏輯", "頭"], "channels": ["13-33"], "gates": [ - { "planet": "☉", "personality": { "gate": 12, "line": 1 }, "design": { "gate": 36, "line": 3 } } + { "planet": "☉", "personality": { "gate": 12, "line": 2 }, "design": { "gate": 36, "line": 4 } } ] }, "ziwei": { diff --git a/examples/sample-output.json b/examples/sample-output.json index 0ca7f7f..4691295 100644 --- a/examples/sample-output.json +++ b/examples/sample-output.json @@ -409,7 +409,7 @@ "human_design": { "type": "投射者", "authority": "自我投射型權威", - "profile": "1/3", + "profile": "2/4", "definition": "一分人(單一定義)", "incarnation_cross": "右角度交叉(12/11 | 36/6)", "design_date": "1990-03-16", @@ -434,22 +434,22 @@ "planet": "☉", "personality": { "gate": 12, - "line": 1 + "line": 2 }, "design": { "gate": 36, - "line": 3 + "line": 4 } }, { "planet": "⊕", "personality": { "gate": 11, - "line": 1 + "line": 2 }, "design": { "gate": 6, - "line": 3 + "line": 4 } }, { @@ -482,14 +482,14 @@ }, "design": { "gate": 43, - "line": 3 + "line": 4 } }, { "planet": "☿", "personality": { "gate": 20, - "line": 5 + "line": 6 }, "design": { "gate": 36, @@ -500,7 +500,7 @@ "planet": "♀", "personality": { "gate": 2, - "line": 5 + "line": 6 }, "design": { "gate": 19, @@ -511,7 +511,7 @@ "planet": "♂", "personality": { "gate": 21, - "line": 1 + "line": 2 }, "design": { "gate": 41, @@ -559,14 +559,14 @@ }, "design": { "gate": 38, - "line": 5 + "line": 6 } }, { "planet": "♇", "personality": { "gate": 1, - "line": 2 + "line": 3 }, "design": { "gate": 1, diff --git a/pyproject.toml b/pyproject.toml index 6cc51a3..8d6c41a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "life-chart-engine" -version = "1.2.0" +version = "1.2.1" description = "Deterministic offline engine computing Western natal, Human Design, and Zi Wei Dou Shu (紫微斗數) charts from one birth record — CLI + JSON for humans and AI agents." readme = "README.md" license = "MIT" diff --git a/scripts/chart_engine.py b/scripts/chart_engine.py index bd55049..8f81e44 100644 --- a/scripts/chart_engine.py +++ b/scripts/chart_engine.py @@ -95,7 +95,7 @@ def aspects(pos, asc, mc): # ---------- 人類圖 ---------- SEQ=[25,17,21,51,42,3,27,24,2,23,8,20,16,35,45,12,15,52,39,53,62,56,31,33,7,4,29,59,40,64, 47,6,46,18,48,57,32,50,28,44,1,43,14,34,9,5,26,11,10,58,38,54,61,60,41,19,13,49,30,55,37,63,22,36] -OFFSET=-1.375 +OFFSET=-1.75 GATE_CENTER={ # 閘門->中心 64:'頭',61:'頭',63:'頭', 47:'邏輯',24:'邏輯',4:'邏輯',17:'邏輯',43:'邏輯',11:'邏輯', 62:'喉',23:'喉',56:'喉',35:'喉',12:'喉',45:'喉',33:'喉',8:'喉',31:'喉',20:'喉',16:'喉', diff --git a/tests/fixtures/GOLDEN_PROVENANCE.md b/tests/fixtures/GOLDEN_PROVENANCE.md index 1b973e2..2d49db9 100644 --- a/tests/fixtures/GOLDEN_PROVENANCE.md +++ b/tests/fixtures/GOLDEN_PROVENANCE.md @@ -60,3 +60,55 @@ at capture time on macOS). ``` - **Determinism:** 上述三個指令各連續執行兩次,第二次輸出與第一次位元組相同。 - **Pre-change oracle:** `tests/fixtures/golden_example_pre_1_2.json` 未重新產生(依 2026-08-06 條目規定)。 + +## 2026-09-15 — Human Design 命盤輪 OFFSET 修正(-1.375 → -1.75):全量重新產生(含 pre-1.2 oracle) + +- **Date:** 2026-09-15 +- **Reason:** `scripts/chart_engine.py:98` 的 `OFFSET` 錯了 0.375°,使整條人類圖 64 閘門輪相對真實星座 + 度數轉錯位置。以已出版的 Human Design 命盤輪為準(barneyandflow.com/gate-zodiac-degrees; + Scribd "Gates and Zodiac Placements":閘門25 = 358°15′(358.25°) 起、閘門17 = 3°52′30″(3.875°) 起、 + 閘門41 = 寶瓶座2°00′(302.0°) 起)比對,`OFFSET=-1.375` 使這三個錨點全部落在錯誤的閘門; + `OFFSET=-1.75` 三點全部吻合,並與獨立套件 `hd-chart-engine@0.1.1`(`WHEEL_START=223.25`, + 即 `-1.75 + 40*5.625`)互相印證。新增 `tests/test_human_design_gate_wheel_offset.py` 把這三個 + 錨點釘死為回歸測試。 +- **Diff scope:** + - `tests/fixtures/golden_example.json` / `.md` — `--example` 範例人:通道 `3-60` → `27-50`, + 9 個星體的人類圖 personality/design 閘門或爻改變。 + - `examples/sample-output.json` — 小明範例:profile `1/3` → `2/4`,10 個星體的 gate/line 改變 + (太陽 12.1→12.2、設計 36.3→36.4 等)。 + - `tests/fixtures/ephemeris_baseline.json` — 12 個 fixture 中 11 個(`ok:true` 的全部)的 + `build_json.human_design` 改變;`jupiter_station_before` 額外變了 type(顯示者→生產者)、 + authority、definition、channels;`high_latitude_65_valid` 失去 `26-44` 通道與「脾」中心的定義。 + 兩個 `human_design_boundary` 註記(`hd_boundary_design_sun`、`hd_boundary_personality_moon`) + 用同一批出生資料重新算出最近邊界距離(舊值是相對錯誤輪盤的邊界,換到正確輪盤後不再貼齊, + 但仍在 0.01° 內,案例依然有效);`western`/`ephemeris` 兩節未動(見 + `tests/fixtures/update_hd_baseline.py` 的內建理由與容忍界線)。完整 per-case before/after + 表見該腳本的執行輸出與 PR 說明。 + - `README.md` 與其 18 份翻譯 — 人類圖範例片段(`角色 1/3`、`"profile": "1/3"`、 + `{ "gate": 12, "line": 1 }`/`{ "gate": 36, "line": 3 }`)同步改為 `2/4` / `12,2` / `36,4`。 + - `tests/fixtures/golden_example_pre_1_2.json` — **這次例外重新產生**:取修正後的 + `golden_example.json` 把 `"schema_version": "1.2"` 換回 `"1.1"`(與 2026-08-06 條目記載的 + 「pre = golden 換掉 schema_version 這一行」關係完全一致,byte-diff 驗證過兩檔案在該次之前 + 也只差這一行)。原因:這支 fixture 凍結的是「1.1→1.2 只加一個欄位」這個宣稱,不是要永遠背著 + 一個已知錯誤的人類圖輪盤;放著不修,`test_single_json_bytes_match_pre_1_2_after_version_bump` + 會強迫未來的引擎輸出繼續符合錯誤輪盤,等於把 bug 焊進保護測試。測試本身(byte-identity 邏輯) + 完全未改動,只有凍結的位元組內容更新。 +- **Commands:** + ```bash + .venv/bin/python scripts/chart_engine.py --example --json > tests/fixtures/golden_example.json + .venv/bin/python scripts/chart_engine.py --example > tests/fixtures/golden_example.md + .venv/bin/python scripts/chart_engine.py --json --name "小明" --gender 女 \ + --date 1990-06-15 --time 08:30 --tz 8 --lat 25.033 --lon 121.5654 --target 2025-01-01 \ + > examples/sample-output.json + .venv/bin/python tests/fixtures/update_hd_baseline.py + python3 -c " + data = open('tests/fixtures/golden_example.json','rb').read() + pre = data.replace(b'\"schema_version\": \"1.2\"', b'\"schema_version\": \"1.1\"', 1) + open('tests/fixtures/golden_example_pre_1_2.json','wb').write(pre) + " + ``` +- **Determinism:** 上述引擎指令各連續執行兩次,第二次輸出與第一次位元組相同。 +- **Protected hash pin:** `tests/test_synastry_cli.py` 的 + `PROTECTED_SHA256["tests/fixtures/ephemeris_baseline.json"]` 依規定隨這次刻意的重新產生一併 + 更新(不是刪除該保護測試;它保護的是「不該被別的 slice 順手改到」,不是「這個檔案的內容永遠不能 + 因為修 bug 而變」)。 diff --git a/tests/fixtures/ephemeris_baseline.json b/tests/fixtures/ephemeris_baseline.json index 74cedc6..0fe2a06 100644 --- a/tests/fixtures/ephemeris_baseline.json +++ b/tests/fixtures/ephemeris_baseline.json @@ -19,22 +19,22 @@ { "design": { "gate": 36, - "line": 3 + "line": 4 }, "personality": { "gate": 12, - "line": 1 + "line": 2 }, "planet": "☉" }, { "design": { "gate": 6, - "line": 3 + "line": 4 }, "personality": { "gate": 11, - "line": 1 + "line": 2 }, "planet": "⊕" }, @@ -63,7 +63,7 @@ { "design": { "gate": 43, - "line": 3 + "line": 4 }, "personality": { "gate": 37, @@ -78,7 +78,7 @@ }, "personality": { "gate": 20, - "line": 5 + "line": 6 }, "planet": "☿" }, @@ -89,7 +89,7 @@ }, "personality": { "gate": 2, - "line": 5 + "line": 6 }, "planet": "♀" }, @@ -100,7 +100,7 @@ }, "personality": { "gate": 21, - "line": 1 + "line": 2 }, "planet": "♂" }, @@ -140,7 +140,7 @@ { "design": { "gate": 38, - "line": 5 + "line": 6 }, "personality": { "gate": 38, @@ -155,7 +155,7 @@ }, "personality": { "gate": 1, - "line": 2 + "line": 3 }, "planet": "♇" } @@ -170,7 +170,7 @@ "邏輯", "頭" ], - "profile": "1/3", + "profile": "2/4", "type": "投射者" }, "input": { @@ -1281,7 +1281,7 @@ }, "personality": { "gate": 39, - "line": 3 + "line": 4 }, "planet": "☊" }, @@ -1292,7 +1292,7 @@ }, "personality": { "gate": 38, - "line": 3 + "line": 4 }, "planet": "☋" }, @@ -1314,7 +1314,7 @@ }, "personality": { "gate": 55, - "line": 4 + "line": 5 }, "planet": "☿" }, @@ -1336,14 +1336,14 @@ }, "personality": { "gate": 5, - "line": 5 + "line": 6 }, "planet": "♂" }, { "design": { "gate": 20, - "line": 3 + "line": 4 }, "personality": { "gate": 20, @@ -1358,25 +1358,25 @@ }, "personality": { "gate": 8, - "line": 2 + "line": 3 }, "planet": "♄" }, { "design": { "gate": 13, - "line": 5 + "line": 6 }, "personality": { "gate": 49, - "line": 4 + "line": 5 }, "planet": "♅" }, { "design": { "gate": 41, - "line": 3 + "line": 4 }, "personality": { "gate": 19, @@ -1387,11 +1387,11 @@ { "design": { "gate": 5, - "line": 2 + "line": 3 }, "personality": { "gate": 5, - "line": 4 + "line": 5 }, "planet": "♇" } @@ -2412,7 +2412,6 @@ "channels": [ "5-15", "23-43", - "26-44", "35-36", "37-40", "39-55", @@ -2424,7 +2423,6 @@ "情緒", "意志", "根", - "脾", "薦骨", "邏輯", "頭" @@ -2439,7 +2437,7 @@ }, "personality": { "gate": 37, - "line": 5 + "line": 6 }, "planet": "☉" }, @@ -2450,7 +2448,7 @@ }, "personality": { "gate": 40, - "line": 5 + "line": 6 }, "planet": "⊕" }, @@ -2460,8 +2458,8 @@ "line": 2 }, "personality": { - "gate": 24, - "line": 6 + "gate": 2, + "line": 1 }, "planet": "☊" }, @@ -2471,8 +2469,8 @@ "line": 2 }, "personality": { - "gate": 44, - "line": 6 + "gate": 1, + "line": 1 }, "planet": "☋" }, @@ -2490,7 +2488,7 @@ { "design": { "gate": 10, - "line": 5 + "line": 6 }, "personality": { "gate": 37, @@ -2505,14 +2503,14 @@ }, "personality": { "gate": 42, - "line": 4 + "line": 5 }, "planet": "♀" }, { "design": { "gate": 36, - "line": 1 + "line": 2 }, "personality": { "gate": 2, @@ -2527,7 +2525,7 @@ }, "personality": { "gate": 64, - "line": 3 + "line": 4 }, "planet": "♃" }, @@ -2545,11 +2543,11 @@ { "design": { "gate": 30, - "line": 5 + "line": 6 }, "personality": { "gate": 55, - "line": 3 + "line": 4 }, "planet": "♅" }, @@ -2577,8 +2575,10 @@ } ], "incarnation_cross": "左角度交叉(37/40 | 5/35)", - "open_centers": [], - "profile": "5/2", + "open_centers": [ + "脾" + ], + "profile": "6/2", "type": "顯示生產者" }, "input": { @@ -3669,19 +3669,20 @@ }, "build_json": { "human_design": { - "authority": "意志力(心)權威", + "authority": "薦骨型權威", "channels": [ "1-8", "11-56", - "25-51" + "42-53" ], "defined_centers": [ "G", "喉", - "意志", + "根", + "薦骨", "邏輯" ], - "definition": "一分人(單一定義)", + "definition": "二分人", "design_date": "2024-11-08", "gates": [ { @@ -3709,7 +3710,7 @@ { "design": { "gate": 17, - "line": 2 + "line": 3 }, "personality": { "gate": 36, @@ -3720,7 +3721,7 @@ { "design": { "gate": 18, - "line": 2 + "line": 3 }, "personality": { "gate": 6, @@ -3731,11 +3732,11 @@ { "design": { "gate": 19, - "line": 4 + "line": 5 }, "personality": { - "gate": 51, - "line": 6 + "gate": 42, + "line": 1 }, "planet": "☾" }, @@ -3746,18 +3747,18 @@ }, "personality": { "gate": 19, - "line": 3 + "line": 4 }, "planet": "☿" }, { "design": { "gate": 11, - "line": 4 + "line": 5 }, "personality": { "gate": 25, - "line": 1 + "line": 2 }, "planet": "♀" }, @@ -3775,7 +3776,7 @@ { "design": { "gate": 45, - "line": 3 + "line": 4 }, "personality": { "gate": 16, @@ -3797,7 +3798,7 @@ { "design": { "gate": 8, - "line": 1 + "line": 2 }, "personality": { "gate": 23, @@ -3808,7 +3809,7 @@ { "design": { "gate": 36, - "line": 5 + "line": 6 }, "personality": { "gate": 36, @@ -3822,8 +3823,8 @@ "line": 4 }, "personality": { - "gate": 60, - "line": 6 + "gate": 41, + "line": 1 }, "planet": "♇" } @@ -3831,13 +3832,12 @@ "incarnation_cross": "右角度交叉(13/7 | 1/2)", "open_centers": [ "情緒", - "根", + "意志", "脾", - "薦骨", "頭" ], "profile": "2/4", - "type": "顯示者" + "type": "生產者" }, "input": { "date": "2025-02-03", @@ -4888,17 +4888,20 @@ }, "build_json": { "human_design": { - "authority": "自我投射型權威", + "authority": "情緒型權威", "channels": [ "1-8", - "11-56" + "11-56", + "30-41" ], "defined_centers": [ "G", "喉", + "情緒", + "根", "邏輯" ], - "definition": "一分人(單一定義)", + "definition": "二分人", "design_date": "2024-11-09", "gates": [ { @@ -4926,7 +4929,7 @@ { "design": { "gate": 17, - "line": 2 + "line": 3 }, "personality": { "gate": 36, @@ -4937,7 +4940,7 @@ { "design": { "gate": 18, - "line": 2 + "line": 3 }, "personality": { "gate": 6, @@ -4948,11 +4951,11 @@ { "design": { "gate": 30, - "line": 1 + "line": 2 }, "personality": { "gate": 27, - "line": 3 + "line": 4 }, "planet": "☾" }, @@ -5014,7 +5017,7 @@ { "design": { "gate": 8, - "line": 1 + "line": 2 }, "personality": { "gate": 23, @@ -5025,7 +5028,7 @@ { "design": { "gate": 36, - "line": 5 + "line": 6 }, "personality": { "gate": 36, @@ -5039,17 +5042,15 @@ "line": 4 }, "personality": { - "gate": 60, - "line": 6 + "gate": 41, + "line": 1 }, "planet": "♇" } ], "incarnation_cross": "右角度交叉(13/7 | 1/2)", "open_centers": [ - "情緒", "意志", - "根", "脾", "薦骨", "頭" @@ -6108,19 +6109,21 @@ "human_design": { "authority": "自我投射型權威", "channels": [ - "1-8" + "7-31", + "23-43" ], "defined_centers": [ "G", - "喉" + "喉", + "邏輯" ], "definition": "一分人(單一定義)", "design_date": "2024-11-10", "gates": [ { "design": { - "gate": 1, - "line": 6 + "gate": 43, + "line": 1 }, "personality": { "gate": 13, @@ -6130,8 +6133,8 @@ }, { "design": { - "gate": 2, - "line": 6 + "gate": 23, + "line": 1 }, "personality": { "gate": 7, @@ -6142,7 +6145,7 @@ { "design": { "gate": 17, - "line": 2 + "line": 3 }, "personality": { "gate": 36, @@ -6153,7 +6156,7 @@ { "design": { "gate": 18, - "line": 2 + "line": 3 }, "personality": { "gate": 6, @@ -6164,18 +6167,18 @@ { "design": { "gate": 37, - "line": 4 + "line": 5 }, "personality": { - "gate": 2, - "line": 6 + "gate": 23, + "line": 1 }, "planet": "☾" }, { "design": { "gate": 9, - "line": 5 + "line": 6 }, "personality": { "gate": 13, @@ -6196,8 +6199,8 @@ }, { "design": { - "gate": 56, - "line": 6 + "gate": 31, + "line": 1 }, "personality": { "gate": 53, @@ -6230,7 +6233,7 @@ { "design": { "gate": 8, - "line": 1 + "line": 2 }, "personality": { "gate": 23, @@ -6241,7 +6244,7 @@ { "design": { "gate": 36, - "line": 5 + "line": 6 }, "personality": { "gate": 36, @@ -6255,23 +6258,22 @@ "line": 4 }, "personality": { - "gate": 60, - "line": 6 + "gate": 41, + "line": 1 }, "planet": "♇" } ], - "incarnation_cross": "右角度交叉(13/7 | 1/2)", + "incarnation_cross": "並列交叉(13/7 | 43/23)", "open_centers": [ "情緒", "意志", "根", "脾", "薦骨", - "邏輯", "頭" ], - "profile": "4/6", + "profile": "4/1", "type": "投射者" }, "input": { @@ -7406,22 +7408,22 @@ { "design": { "gate": 36, - "line": 5 + "line": 6 }, "personality": { "gate": 22, - "line": 3 + "line": 4 }, "planet": "☊" }, { "design": { "gate": 6, - "line": 5 + "line": 6 }, "personality": { "gate": 47, - "line": 3 + "line": 4 }, "planet": "☋" }, @@ -7443,29 +7445,29 @@ }, "personality": { "gate": 7, - "line": 1 + "line": 2 }, "planet": "☿" }, { "design": { "gate": 36, - "line": 2 + "line": 3 }, "personality": { "gate": 16, - "line": 3 + "line": 4 }, "planet": "♀" }, { "design": { "gate": 56, - "line": 1 + "line": 2 }, "personality": { "gate": 64, - "line": 3 + "line": 4 }, "planet": "♂" }, @@ -7483,7 +7485,7 @@ { "design": { "gate": 36, - "line": 3 + "line": 4 }, "personality": { "gate": 25, @@ -7497,19 +7499,19 @@ "line": 1 }, "personality": { - "gate": 8, - "line": 6 + "gate": 20, + "line": 1 }, "planet": "♅" }, { "design": { "gate": 25, - "line": 2 + "line": 3 }, "personality": { "gate": 25, - "line": 4 + "line": 5 }, "planet": "♆" }, @@ -8591,29 +8593,29 @@ { "design": { "gate": 36, - "line": 5 + "line": 6 }, "personality": { "gate": 22, - "line": 3 + "line": 4 }, "planet": "☊" }, { "design": { "gate": 6, - "line": 5 + "line": 6 }, "personality": { "gate": 47, - "line": 3 + "line": 4 }, "planet": "☋" }, { "design": { "gate": 32, - "line": 3 + "line": 4 }, "personality": { "gate": 49, @@ -8635,11 +8637,11 @@ { "design": { "gate": 36, - "line": 2 + "line": 3 }, "personality": { "gate": 16, - "line": 4 + "line": 5 }, "planet": "♀" }, @@ -8657,11 +8659,11 @@ { "design": { "gate": 45, - "line": 1 + "line": 2 }, "personality": { "gate": 52, - "line": 4 + "line": 5 }, "planet": "♃" }, @@ -8682,19 +8684,19 @@ "line": 1 }, "personality": { - "gate": 8, - "line": 6 + "gate": 20, + "line": 1 }, "planet": "♅" }, { "design": { "gate": 25, - "line": 2 + "line": 3 }, "personality": { "gate": 25, - "line": 4 + "line": 5 }, "planet": "♆" }, @@ -9802,11 +9804,11 @@ { "design": { "gate": 28, - "line": 3 + "line": 4 }, "personality": { "gate": 37, - "line": 1 + "line": 2 }, "planet": "☾" }, @@ -9824,7 +9826,7 @@ { "design": { "gate": 36, - "line": 2 + "line": 3 }, "personality": { "gate": 16, @@ -9835,7 +9837,7 @@ { "design": { "gate": 56, - "line": 2 + "line": 3 }, "personality": { "gate": 64, @@ -9846,11 +9848,11 @@ { "design": { "gate": 45, - "line": 1 + "line": 2 }, "personality": { "gate": 52, - "line": 4 + "line": 5 }, "planet": "♃" }, @@ -9871,8 +9873,8 @@ "line": 1 }, "personality": { - "gate": 8, - "line": 6 + "gate": 20, + "line": 1 }, "planet": "♅" }, @@ -9883,7 +9885,7 @@ }, "personality": { "gate": 25, - "line": 4 + "line": 5 }, "planet": "♆" }, @@ -10922,13 +10924,13 @@ "annotations": { "human_design_boundary": { "chart": "design", - "gate": 4, - "gate_boundary_deg": 0.9375005115, - "line": 2, - "line_boundary_deg": 5.115e-07, - "lon": 140.1875005115, - "nearest_boundary_deg": 5.115e-07, - "planet": "☉" + "gate": 50, + "gate_boundary_deg": 2.8031487598, + "line": 4, + "line_boundary_deg": 0.0093512402, + "lon": 209.1968512402, + "nearest_boundary_deg": 0.0093512402, + "planet": "♄" } }, "build_json": { @@ -10954,7 +10956,7 @@ }, "personality": { "gate": 1, - "line": 5 + "line": 6 }, "planet": "☉" }, @@ -10965,7 +10967,7 @@ }, "personality": { "gate": 2, - "line": 5 + "line": 6 }, "planet": "⊕" }, @@ -10976,7 +10978,7 @@ }, "personality": { "gate": 35, - "line": 5 + "line": 6 }, "planet": "☊" }, @@ -10987,7 +10989,7 @@ }, "personality": { "gate": 5, - "line": 5 + "line": 6 }, "planet": "☋" }, @@ -11016,7 +11018,7 @@ { "design": { "gate": 40, - "line": 2 + "line": 3 }, "personality": { "gate": 46, @@ -11031,25 +11033,25 @@ }, "personality": { "gate": 6, - "line": 3 + "line": 4 }, "planet": "♂" }, { "design": { "gate": 34, - "line": 1 + "line": 2 }, "personality": { "gate": 5, - "line": 3 + "line": 4 }, "planet": "♃" }, { "design": { "gate": 50, - "line": 3 + "line": 4 }, "personality": { "gate": 44, @@ -11060,7 +11062,7 @@ { "design": { "gate": 34, - "line": 5 + "line": 6 }, "personality": { "gate": 9, @@ -11071,11 +11073,11 @@ { "design": { "gate": 11, - "line": 4 + "line": 5 }, "personality": { "gate": 11, - "line": 5 + "line": 6 }, "planet": "♆" }, @@ -11086,7 +11088,7 @@ }, "personality": { "gate": 50, - "line": 4 + "line": 5 }, "planet": "♇" } @@ -11099,7 +11101,7 @@ "脾", "頭" ], - "profile": "5/2", + "profile": "6/2", "type": "生產者" }, "input": { @@ -12095,14 +12097,14 @@ { "annotations": { "human_design_boundary": { - "chart": "personality", - "gate": 32, - "gate_boundary_deg": 1.7621e-06, + "chart": "design", + "gate": 38, + "gate_boundary_deg": 0.0010399149, "line": 6, - "line_boundary_deg": 1.7621e-06, - "lon": 206.7499982379, - "nearest_boundary_deg": 1.7621e-06, - "planet": "☾" + "line_boundary_deg": 0.0010399149, + "lon": 285.1239600851, + "nearest_boundary_deg": 0.0010399149, + "planet": "☊" } }, "build_json": { @@ -12147,8 +12149,8 @@ "line": 6 }, "personality": { - "gate": 58, - "line": 6 + "gate": 38, + "line": 1 }, "planet": "☊" }, @@ -12158,8 +12160,8 @@ "line": 6 }, "personality": { - "gate": 52, - "line": 6 + "gate": 39, + "line": 1 }, "planet": "☋" }, @@ -12169,8 +12171,8 @@ "line": 6 }, "personality": { - "gate": 32, - "line": 6 + "gate": 50, + "line": 1 }, "planet": "☾" }, @@ -12181,25 +12183,25 @@ }, "personality": { "gate": 5, - "line": 4 + "line": 5 }, "planet": "☿" }, { "design": { "gate": 29, - "line": 3 + "line": 4 }, "personality": { "gate": 14, - "line": 3 + "line": 4 }, "planet": "♀" }, { "design": { - "gate": 57, - "line": 6 + "gate": 32, + "line": 1 }, "personality": { "gate": 26, @@ -12221,7 +12223,7 @@ { "design": { "gate": 60, - "line": 4 + "line": 5 }, "personality": { "gate": 41, @@ -12236,7 +12238,7 @@ }, "personality": { "gate": 38, - "line": 4 + "line": 5 }, "planet": "♅" }, @@ -12247,7 +12249,7 @@ }, "personality": { "gate": 54, - "line": 1 + "line": 2 }, "planet": "♆" }, @@ -12258,7 +12260,7 @@ }, "personality": { "gate": 43, - "line": 3 + "line": 4 }, "planet": "♇" } diff --git a/tests/fixtures/golden_example.json b/tests/fixtures/golden_example.json index c9d5e39..677f1ba 100644 --- a/tests/fixtures/golden_example.json +++ b/tests/fixtures/golden_example.json @@ -403,10 +403,10 @@ "頭" ], "channels": [ - "3-60", "10-34", "13-33", "26-44", + "27-50", "30-41" ], "gates": [ @@ -436,7 +436,7 @@ "planet": "☊", "personality": { "gate": 31, - "line": 2 + "line": 3 }, "design": { "gate": 33, @@ -447,7 +447,7 @@ "planet": "☋", "personality": { "gate": 41, - "line": 2 + "line": 3 }, "design": { "gate": 19, @@ -469,7 +469,7 @@ "planet": "☿", "personality": { "gate": 10, - "line": 3 + "line": 4 }, "design": { "gate": 50, @@ -480,11 +480,11 @@ "planet": "♀", "personality": { "gate": 34, - "line": 1 + "line": 2 }, "design": { "gate": 29, - "line": 4 + "line": 5 } }, { @@ -495,7 +495,7 @@ }, "design": { "gate": 26, - "line": 5 + "line": 6 } }, { @@ -505,8 +505,8 @@ "line": 5 }, "design": { - "gate": 3, - "line": 6 + "gate": 27, + "line": 1 } }, { @@ -535,7 +535,7 @@ "planet": "♆", "personality": { "gate": 41, - "line": 1 + "line": 2 }, "design": { "gate": 60, @@ -545,8 +545,8 @@ { "planet": "♇", "personality": { - "gate": 9, - "line": 6 + "gate": 5, + "line": 1 }, "design": { "gate": 9, diff --git a/tests/fixtures/golden_example.md b/tests/fixtures/golden_example.md index e12f3e8..6025938 100644 --- a/tests/fixtures/golden_example.md +++ b/tests/fixtures/golden_example.md @@ -22,21 +22,21 @@ 輪迴交叉 右角度交叉(38/39 | 48/21) 定義中心 G,喉,情緒,意志,根,脾,薦骨 | 開放中心 邏輯,頭 設計日期 1999-10-06 -通道 ['3-60', '10-34', '13-33', '26-44', '30-41'] +通道 ['10-34', '13-33', '26-44', '27-50', '30-41'] 26閘門(體|個性|設計): ☉ 38.1 | 48.3 ⊕ 39.1 | 21.3 - ☊ 31.2 | 33.4 - ☋ 41.2 | 19.4 + ☊ 31.3 | 33.4 + ☋ 41.3 | 19.4 ☾ 44.2 | 29.3 - ☿ 10.3 | 50.5 - ♀ 34.1 | 29.4 - ♂ 30.4 | 26.5 - ♃ 42.5 | 3.6 + ☿ 10.4 | 50.5 + ♀ 34.2 | 29.5 + ♂ 30.4 | 26.6 + ♃ 42.5 | 27.1 ♄ 24.3 | 2.3 ♅ 13.2 | 19.6 - ♆ 41.1 | 60.6 - ♇ 9.6 | 9.3 + ♆ 41.2 | 60.6 + ♇ 5.1 | 9.3 【紫微斗數 iztro】 五行局 土五局 | 命主 破軍 | 身主 天同 diff --git a/tests/fixtures/golden_example_pre_1_2.json b/tests/fixtures/golden_example_pre_1_2.json index ee694e1..cd43bcf 100644 --- a/tests/fixtures/golden_example_pre_1_2.json +++ b/tests/fixtures/golden_example_pre_1_2.json @@ -403,10 +403,10 @@ "頭" ], "channels": [ - "3-60", "10-34", "13-33", "26-44", + "27-50", "30-41" ], "gates": [ @@ -436,7 +436,7 @@ "planet": "☊", "personality": { "gate": 31, - "line": 2 + "line": 3 }, "design": { "gate": 33, @@ -447,7 +447,7 @@ "planet": "☋", "personality": { "gate": 41, - "line": 2 + "line": 3 }, "design": { "gate": 19, @@ -469,7 +469,7 @@ "planet": "☿", "personality": { "gate": 10, - "line": 3 + "line": 4 }, "design": { "gate": 50, @@ -480,11 +480,11 @@ "planet": "♀", "personality": { "gate": 34, - "line": 1 + "line": 2 }, "design": { "gate": 29, - "line": 4 + "line": 5 } }, { @@ -495,7 +495,7 @@ }, "design": { "gate": 26, - "line": 5 + "line": 6 } }, { @@ -505,8 +505,8 @@ "line": 5 }, "design": { - "gate": 3, - "line": 6 + "gate": 27, + "line": 1 } }, { @@ -535,7 +535,7 @@ "planet": "♆", "personality": { "gate": 41, - "line": 1 + "line": 2 }, "design": { "gate": 60, @@ -545,8 +545,8 @@ { "planet": "♇", "personality": { - "gate": 9, - "line": 6 + "gate": 5, + "line": 1 }, "design": { "gate": 9, diff --git a/tests/fixtures/update_hd_baseline.py b/tests/fixtures/update_hd_baseline.py new file mode 100644 index 0000000..2767a01 --- /dev/null +++ b/tests/fixtures/update_hd_baseline.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +"""Regenerate the Human Design portion of ephemeris_baseline.json from the +corrected engine (fix/hd-gate-wheel-offset: OFFSET -1.375 -> -1.75). + +Only `build_json.human_design` and the `human_design_boundary` annotation are +touched. Everything else in each fixture (western, ephemeris, id, purpose, +input, station_check annotations) is carried over unchanged: + + - `western` does not depend on OFFSET/gate_line at all, and this script + asserts the freshly computed western section is byte-identical to the + stored one before overwriting anything, so unrelated drift fails loudly + instead of being silently baked in. + - `ephemeris` is a frozen swisseph (AGPL-era) ground-truth snapshot; the + engine no longer depends on swisseph (MIT/astronomy-engine), so it cannot + be regenerated here and is intentionally left alone. + +The two `human_design_boundary` fixtures were originally chosen to sit +sub-micro-degree from a gate/line boundary *under the old wrong offset*. That +property does not carry over (the wheel is not just relabeled, it is rotated +by a constant 0.375 deg), so their boundary annotation is recomputed honestly +for the corrected offset rather than hand-edited or silently left stale. No +test asserts boundary tightness (see tests/test_engine_astronomy_contract.py +test_human_design_boundary_fixtures_report_gate_or_line_jumps), only that the +`human_design_boundary` flag stays truthy, so this keeps the case valid. + +Usage: + .venv/bin/python tests/fixtures/update_hd_baseline.py +""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT / "scripts")) + +import chart_engine as engine # noqa: E402 + +BASELINE = Path(__file__).with_name("ephemeris_baseline.json") + +HD_BODIES = ["☉", "☾", "☿", "♀", "♂", "♃", "♄", "♅", "♆", "♇", "☊"] +HD_LINE_DEG = 0.9375 +HD_GATE_DEG = 5.625 + +# Sanity bound for the western sanity-check below, not a rewrite of western. +# ephemeris_baseline.json's stored `western` section was frozen from the old +# swisseph engine (01-baseline-oracle-freeze, pre astronomy-engine +# migration); tests/test_engine_astronomy_contract.py already compares it +# with tolerance (DEFAULT_LON_TOL=0.017 deg) for exactly this reason, not +# byte equality. This script never overwrites `western`; the bound below only +# guards against a *gross* mismatch (e.g. a real regression) slipping through +# unnoticed, using a bound looser than the test's so it never false-positives +# on that known, accepted swisseph-vs-astronomy-engine numerical drift. +WESTERN_SANITY_TOL_DEG = 0.05 + + +def r(value: float) -> float: + return round(float(value), 10) + + +def angular_delta(a: float, b: float) -> float: + return abs((a - b + 180) % 360 - 180) + + +def build_json_or_error(inp: dict) -> dict: + # Mirrors the CLI's own catch-all (scripts/chart_engine.py main()) and the + # test suite's build_json_or_error() helper: engine.build_json() itself + # lets validation/computation errors propagate. + try: + return engine.build_json(inp) + except Exception as exc: + return {"ok": False, "error": str(exc)} + + +def engine_input(item: dict) -> dict: + y, mo, d = map(int, item["input"]["date"].split("-")) + hh, mm = map(int, item["input"]["time"].split(":")) + return { + "name": item["input"]["name"], + "gender": item["input"]["gender"], + "date": (y, mo, d), + "time": (hh, mm), + "tz_offset": item["input"]["tz_offset"], + "lat": item["input"]["lat"], + "lon": item["input"]["lon"], + "target": item["input"]["target"], + } + + +def hd_positions(jd: float) -> dict: + out = {n: engine.eph.body_lon_speed(jd, n)[0] for n in HD_BODIES} + out["⊕"] = (out["☉"] + 180) % 360 + out["☋"] = (out["☊"] + 180) % 360 + return out + + +def design_jd(inp: dict) -> float: + birth_jd = engine.jd_of(inp["date"], inp["time"], inp["tz_offset"]) + sun_lon = engine.eph.body_lon_speed(birth_jd, "☉")[0] + target = (sun_lon - 88) % 360 + lo, hi = birth_jd - 100, birth_jd - 80 + for _ in range(60): + mid = (lo + hi) / 2 + mid_sun = engine.eph.body_lon_speed(mid, "☉")[0] + diff = (mid_sun - target + 180) % 360 - 180 + if diff < 0: + lo = mid + else: + hi = mid + return (lo + hi) / 2 + + +def nearest_hd_boundary(lon: float) -> dict: + wheel_lon = (lon - engine.OFFSET) % 360 + line_rem = wheel_lon % HD_LINE_DEG + gate_rem = wheel_lon % HD_GATE_DEG + line_distance = min(line_rem, HD_LINE_DEG - line_rem) + gate_distance = min(gate_rem, HD_GATE_DEG - gate_rem) + return { + "line_boundary_deg": r(line_distance), + "gate_boundary_deg": r(gate_distance), + "nearest_boundary_deg": r(min(line_distance, gate_distance)), + } + + +def hd_boundary(inp: dict) -> dict: + birth_jd = engine.jd_of(inp["date"], inp["time"], inp["tz_offset"]) + candidates = [] + for chart, jd in (("personality", birth_jd), ("design", design_jd(inp))): + for planet, lon in hd_positions(jd).items(): + gate, line = engine.gate_line(lon) + boundary = nearest_hd_boundary(lon) + candidates.append( + {**boundary, "chart": chart, "planet": planet, "gate": gate, "line": line, "lon": r(lon)} + ) + return min(candidates, key=lambda c: c["nearest_boundary_deg"]) + + +def main() -> None: + data = json.loads(BASELINE.read_text(encoding="utf-8")) + changed = [] + for item in data["fixtures"]: + inp = engine_input(item) + old_bj = item["build_json"] + new_bj = build_json_or_error(inp) + assert new_bj.get("ok") == old_bj.get("ok"), f"{item['id']}: ok flag changed" + if new_bj.get("ok"): + old_planets = {p["name"]: p for p in old_bj["western"]["planets"]} + for planet in new_bj["western"]["planets"]: + delta = angular_delta(planet["lon"], old_planets[planet["name"]]["lon"]) + assert delta <= WESTERN_SANITY_TOL_DEG, ( + f"{item['id']} {planet['name']}: western lon delta={delta:.6f} " + f"exceeds sanity bound {WESTERN_SANITY_TOL_DEG} — OFFSET fix should not " + "move western this much; investigate before overwriting human_design" + ) + old_hd = old_bj["human_design"] + new_hd = new_bj["human_design"] + if old_hd != new_hd: + changed.append((item["id"], old_hd, new_hd)) + item["build_json"]["human_design"] = new_hd + if item.get("annotations", {}).get("human_design_boundary"): + item["annotations"]["human_design_boundary"] = hd_boundary(inp) + + BASELINE.write_text( + json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True) + "\n", + encoding="utf-8", + ) + print(f"wrote {BASELINE}") + print(f"{len(changed)} of {len(data['fixtures'])} fixtures changed human_design:") + for fid, old_hd, new_hd in changed: + print(f"\n== {fid} ==") + for key in ("type", "authority", "definition", "profile", "channels", "defined_centers", "open_centers"): + if key not in old_hd: + continue + if old_hd[key] != new_hd[key]: + print(f" {key}: {old_hd[key]!r} -> {new_hd[key]!r}") + for og, ng in zip(old_hd["gates"], new_hd["gates"], strict=True): + for side in ("personality", "design"): + if og[side] != ng[side]: + print( + f" {og['planet']} {side}: " + f"{og[side]['gate']}.{og[side]['line']} -> {ng[side]['gate']}.{ng[side]['line']}" + ) + + +if __name__ == "__main__": + main() diff --git a/tests/test_human_design_gate_wheel_offset.py b/tests/test_human_design_gate_wheel_offset.py new file mode 100644 index 0000000..48ea07f --- /dev/null +++ b/tests/test_human_design_gate_wheel_offset.py @@ -0,0 +1,46 @@ +from __future__ import annotations + +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / "scripts")) + +from chart_engine import SEQ, gate_line # noqa: E402 + +# Published Human Design mandala boundaries (barneyandflow.com/gate-zodiac-degrees; +# Scribd "Gates and Zodiac Placements"): +# Gate 25 = 28deg15'00" Pisces (358.25 deg) .. 03deg52'30" Aries +# Gate 17 = 03deg52'30" (3.875 deg) .. 09deg30' Aries +# Gate 41 starts 02deg00' Aquarius (302.0 deg) +# These pin the wheel's absolute rotation, independent of the OFFSET constant's +# own value, so a future re-derivation of OFFSET is still checked against the +# real mandala instead of against itself. + + +def test_gate_25_starts_at_358_25_degrees(): + assert gate_line(358.25) == (25, 1) + + +def test_last_line_before_gate_25_is_the_preceding_wheel_gate(): + preceding_gate = SEQ[-1] # wheel is circular; SEQ[-1] is gate 36 + assert gate_line(358.24) == (preceding_gate, 6) + + +def test_gate_17_starts_at_3_875_degrees(): + assert gate_line(3.875) == (17, 1) + + +def test_gate_41_starts_at_302_degrees(): + assert gate_line(302.0) == (41, 1) + + +def test_just_below_302_degrees_is_previous_gate_line_6(): + previous_gate = SEQ[SEQ.index(41) - 1] # gate 60 + assert gate_line(301.999) == (previous_gate, 6) + + +def test_wheel_wraps_around_0_degrees_consistently(): + # -0.1 deg and 359.9 deg are the same ecliptic longitude; the wheel lookup + # must agree across the 360/0 modulo boundary. + assert gate_line(-0.1) == gate_line(359.9) == (25, 2) diff --git a/tests/test_synastry_cli.py b/tests/test_synastry_cli.py index a68fe34..c84f141 100644 --- a/tests/test_synastry_cli.py +++ b/tests/test_synastry_cli.py @@ -29,8 +29,13 @@ # Do not use `git diff` as an oracle: it is blind to staged-only changes and # to content after commit. Hashes match the HEAD content as of this pin. PROTECTED_SHA256 = { + # Updated 2026-09-15: deliberate regeneration for the Human Design gate + # wheel OFFSET fix (-1.375 -> -1.75); see tests/fixtures/GOLDEN_PROVENANCE.md + # "2026-09-15" entry and tests/fixtures/update_hd_baseline.py. Not a + # loosened guard — this pin still fails if anything besides that + # deliberate, documented regeneration touches the file. "tests/fixtures/ephemeris_baseline.json": ( - "ca1ca71e50985c1c246fab58b1c6246f7d58e94157f2876262f1b523f689dd8f" + "10c4447198e2ace4722c585121828dbc6da128611d6eac0d1fa01204c326b47e" ), "docs/specs/2026-07-13-engine-polish-funnel-design.md": ( "7e2ec5669411c9af1f32faa2017d8997586ec1e444e6f4061227f446e31e8e2e" diff --git a/tests/test_synastry_hd.py b/tests/test_synastry_hd.py index 964cd76..59092db 100644 --- a/tests/test_synastry_hd.py +++ b/tests/test_synastry_hd.py @@ -874,10 +874,14 @@ def test_time_unknown_channel_confidence_exhaustive_split_pinned(): conns = synastry.build_synastry(inp_a, b_unknown)["human_design"][ "channel_connections" ] - # B's noon fast-planet gates are {2,3,10,13,43,54,55,60}; a connection is + # B's noon fast-planet gates are {2,3,10,13,41,43,54,55}; a connection is # 0.6 iff one of its endpoints is in that set, else 0.85. + # (Gate set updated 2026-09-15 for the corrected Human Design gate wheel + # OFFSET, -1.375 -> -1.75 — see tests/fixtures/GOLDEN_PROVENANCE.md. Gate + # 60 shifted to gate 41 in B's noon fast gates, which drops the 3-60 + # dominance connection entirely: 41 is not a fast-side endpoint of any + # other CHANNELS pair A0 completes, and no new connection appears.) expected = { - "hd-chan-3-60-dominance": 0.6, "hd-chan-10-20-electromagnetic": 0.6, "hd-chan-13-33-compromise": 0.6, "hd-chan-25-51-dominance": 0.85,