Skip to content

fix: correct Human Design gate wheel offset (-1.375 -> -1.75) - #14

Open
zhenheco wants to merge 1 commit into
mainfrom
fix/hd-gate-wheel-offset
Open

zhenheco wants to merge 1 commit into
mainfrom
fix/hd-gate-wheel-offset

Conversation

@zhenheco

Copy link
Copy Markdown
Owner

Root cause

scripts/chart_engine.py:98 — OFFSET=-1.375 in gate_line(). This shifts the entire 64-gate Human Design wheel by 0.375 deg away from its real position relative to the ecliptic. SEQ (the gate sequence) and the line-width math in gate_line() are correct; only the rotational offset constant is wrong.

def gate_line(lon):
    w=(lon-OFFSET)%360; idx=int(w//5.625); g=SEQ[idx]
    line=int((w-idx*5.625)//0.9375)+1
    return g,line

Sources

  • Published Human Design mandala (barneyandflow.com/gate-zodiac-degrees; Scribd "Gates and Zodiac Placements"):
    • Gate 25 = 28°15′00″ Pisces (358.25°) – 03°52′30″ Aries
    • Gate 17 = 03°52′30″ (3.875°) – 09°30′ Aries
    • Gate 41 starts 02°00′ Aquarius (302.0°)
  • OFFSET=-1.375 (current main) puts all three anchors in the wrong gate. OFFSET=-1.75 puts all three in the documented gate.
  • Independent confirmation: npm hd-chart-engine@0.1.1 (used by life-web's question-first path, life-web/node_modules/hd-chart-engine/dist/index.js) has WHEEL_START=223.25, i.e. -1.75 + 40*5.625 — the same offset, derived independently.

Impact

At OFFSET=-1.375: ~6.5% of gate activations land in the wrong gate, ~39.7% land on the wrong gate-or-line, and ~83% of charts have at least one wrong gate. Every consumer of this engine (server.py, webapp.py, mcp_server.py, synastry.py, the WordPress plugin over HTTP) inherits the wrong values, since they all go through gate_line().

Fix

One line: OFFSET=-1.375 → OFFSET=-1.75.

TDD

tests/test_human_design_gate_wheel_offset.py (new) pins the three published mandala anchors plus a preceding-gate/previous-line case and a 0°-wrap-around case:

tests/test_human_design_gate_wheel_offset.py::test_gate_25_starts_at_358_25_degrees            RED -> GREEN
tests/test_human_design_gate_wheel_offset.py::test_last_line_before_gate_25_is_the_preceding_wheel_gate   GREEN (unaffected — relative to SEQ)
tests/test_human_design_gate_wheel_offset.py::test_gate_17_starts_at_3_875_degrees             RED -> GREEN
tests/test_human_design_gate_wheel_offset.py::test_gate_41_starts_at_302_degrees               RED -> GREEN
tests/test_human_design_gate_wheel_offset.py::test_just_below_302_degrees_is_previous_gate_line_6         GREEN (unaffected — relative to SEQ)
tests/test_human_design_gate_wheel_offset.py::test_wheel_wraps_around_0_degrees_consistently   GREEN (unaffected — relative to SEQ)

RED (at OFFSET=-1.375, captured before the fix):

AssertionError: assert (36, 6) == (25, 1)   # gate_line(358.25)
AssertionError: assert (25, 6) == (17, 1)   # gate_line(3.875)
AssertionError: assert (60, 6) == (41, 1)   # gate_line(302.0)
3 failed, 3 passed

GREEN (at OFFSET=-1.75): 6 passed.

Fixtures regenerated from the corrected engine (no hand edits)

tests/fixtures/update_hd_baseline.py (new) regenerates only build_json.human_design and the human_design_boundary annotations in ephemeris_baseline.json, asserting western stays within a sanity tolerance first so any unrelated drift would fail loudly instead of being silently baked in. golden_example.json/.md and examples/sample-output.json are regenerated with their existing GOLDEN_PROVENANCE.md commands. See that file's new 2026-09-15 entry for the full writeup, including why golden_example_pre_1_2.json is regenerated too (it freezes "1.1→1.2 adds one field", not a known-wrong gate wheel — leaving it stale would permanently pin the bug through its byte-identity test).

Per-case before/after (tests/fixtures/ephemeris_baseline.json, via update_hd_baseline.py)

11 of 12 fixtures changed (the 12th, placidus_lat70_invalid, has ok:false — no human_design to regenerate).

Fixture type/authority/definition/profile change channels / centers change gate/line jumps
taipei_standard profile 1/3 → 2/4 — 10 (☉ 12.1→12.2, ⊕ 11.1→11.2, ☾design 43.3→43.4, ☿ 20.5→20.6, ♀ 2.5→2.6, ♂ 21.1→21.2, ♆design 38.5→38.6, ♇ 1.2→1.3, +2 more)
london_solar_sign_cusp — — 11
high_latitude_65_valid profile 5/2 → 6/2 loses channel 26-44; loses 「脾」from defined_centers (open_centers gains it) 10
placidus_lat70_invalid — (ok:false, unchanged) — —
jupiter_station_before type 顯示者→生產者; authority 意志力(心)權威→薦骨型權威; definition 一分人→二分人 channels [1-8,11-56,25-51]→[1-8,11-56,42-53]; defined_centers [G,喉,意志,邏輯]→[G,喉,根,薦骨,邏輯] 11
jupiter_station_middle authority 自我投射型權威→情緒型權威; definition 一分人→二分人 channels gain 30-41; defined_centers gains 情緒,根 7
jupiter_station_after profile 4/6→4/1 channels [1-8]→[7-31,23-43]; defined_centers gains 邏輯 11
saturn_station_before — — 12
saturn_station_middle — — 10
saturn_station_after — — 8
hd_boundary_design_sun profile 5/2→6/2 — 13; boundary re-anchored: 土星 design 50.4, 0.0094° from edge (was 0.0000005° from a different, now-wrong edge)
hd_boundary_personality_moon — — 11; boundary re-anchored: 北交點 design 38.1, 0.0010° from edge (was 0.0000018° from a different, now-wrong edge)

golden_example.json/.md (--example sample): channel 3-60 replaced by 27-50; 9 gate/line values change.
examples/sample-output.json (小明 sample): profile 1/3→2/4; 10 gate/line values change (matches taipei_standard above — same birth input).
README.md + all 18 translations: the embedded 小明 sample snippet updated to match (角色 1/3→2/4, 12.1/36.3→12.2/36.4).

tests/test_synastry_hd.py::test_time_unknown_channel_confidence_exhaustive_split_pinned (not in the original sweep) also pinned a gate set derived from the old offset — person B0's noon fast-planet gates shift {...,60} → {...,41}, dropping the hd-chan-3-60-dominance connection. Updated to match the corrected engine's actual output (verified by direct invocation, not guessed).

Test commands

cd life-chart-engine
uv venv --python 3.12 .venv   # or: bash setup.sh
uv pip install --python .venv/bin/python -r requirements.txt -r requirements-dev.txt
.venv/bin/python -m pytest -q
.venv/bin/python -m pytest tests/test_human_design_gate_wheel_offset.py -v
.venv/bin/python -m pytest -m deploy_regression -q -r s
.venv/bin/python -m ruff check .

Verification run (this branch, HEAD)

447 passed, 2 skipped (1 pre-existing mcp extra skip, 1 other pre-existing skip; baseline on main before this change was 441 passed, 2 skipped — the +6 are the new anchor tests). ruff check . — all checks passed.

Not merged, not deployed

Per instructions this PR is opened for review only. pyproject.toml version bumped 1.2.0→1.2.1 (patch); no CHANGELOG file exists in this repo so none was added. schema_version stays "1.2" (JSON contract shape unchanged).

Also fixed (same bug, separate copy, not part of this repo)

$HOME/Documents/CC Cli/agents-skills/life/scripts/chart_engine.py is an older, separate fork (Swiss Ephemeris/py-iztro, not a copy of this engine) with the same OFFSET=-1.375 at its own line 72. Edited to -1.75 in the working tree; not committed here (different repo, out of scope for this PR) — see the session notes for that repo's status.

Out of scope, flagged not fixed

  • GATE_CENTER[19] in the CC Cli skill fork (agents-skills/life/scripts/chart_engine.py:78) is still '情緒'; this engine repo already fixed the equivalent bug on 2026-08-30 (docs/2026-08-30-gate19-root-fix-impact.md), but the older fork never got that fix. Separate issue, separate repo.
  • placidus_lat70_invalid's frozen ephemeris_baseline.json error string ("swisseph.houses_ex: error") predates the AGPL→MIT/astronomy-engine migration; the current engine raises a different message for the same input ("placidus undefined at high latitude"). Unrelated to the OFFSET bug — the ok:false flag itself is unchanged and no test asserts the error text — left untouched.

https://claude.ai/code/session_016ZLLbCYxw9wxqX6rsSrbMX

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
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-15T03:21:05.972406Z ab55eca PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant