RELEASE_NOTES_2.0.0 - TheDaniel166/moira GitHub Wiki
Release Notes — Moira 2.0.0
Date: 2026-04-10
Summary
Moira 2.0.0 is a release-integrity milestone.
No new astrological features are introduced. What this release does is harden the behavioral contract of the engine: time semantics are now strict, house policy is now explicit, public result vessels are now formally frozen, and several subsystems that previously accepted ambiguous inputs now raise rather than silently proceeding on invalid assumptions.
These changes collectively produce a more honest and verifiable engine. Callers that depended on undefined behavior will need to adapt. The compatibility guide below states exactly what must change.
Breaking Changes
Four changes require caller adaptation.
Full migration guidance is in COMPATIBILITY_NOTES_2.0.0.md.
1. Naïve datetime objects now raise
jd_from_datetime() previously accepted timezone-unaware datetime objects
and silently treated them as UTC.
This is now an error.
# raises ValueError in 2.0.0
jd_from_datetime(datetime(2000, 1, 1, 12, 0, 0))
# correct
from datetime import timezone
jd_from_datetime(datetime(2000, 1, 1, 12, 0, 0, tzinfo=timezone.utc))
Callers that pass naïve datetimes anywhere in the engine must add explicit
tzinfo. This is the most pervasive caller-visible change in this release.
2. classify_house_system() now raises on unknown codes
Previously this function returned undefined or silent fallback behavior for
unrecognized house system codes. It now raises ValueError.
# raises ValueError in 2.0.0
classify_house_system("XX")
Callers must pass only valid HouseSystem constants.
3. Strict house policy now raises on unknown codes
When using HousePolicy.strict() or passing unknown_system=UnknownSystemPolicy.RAISE,
unknown house system codes that previously fell back silently to Placidus now
raise ValueError.
The default HousePolicy retains silent fallback. This change only affects
callers who explicitly request strict behavior or who construct HousePolicy
with UnknownSystemPolicy.RAISE.
4. decan_at() no longer accepts a reader parameter
The optional reader argument has been removed from decan_at(). The function
is now self-contained and computes from RAMC, true obliquity, and latitude
directly.
# raises TypeError in 2.0.0
decan_at(jd, lat, lon, reader=my_reader)
# correct
decan_at(jd, lat, lon)
Hardening (no caller breakage)
The following changes strengthen guarantees without requiring caller adaptation.
House policy objects made explicit
House calculations now carry full truth-preservation metadata:
HouseCusps.system— the system that was requestedHouseCusps.effective_system— the system that actually ranHouseCusps.fallback—Trueif a fallback occurredHouseCusps.fallback_reason— why the fallback occurred
Callers who relied on silent fallback will still get results. They now also get explicit metadata explaining what happened.
50 public policy dataclasses are now formally frozen
All public policy dataclasses are frozen=True, slots=True and are enforced as
such at test-gate time. These are hashable, immutable, and safe to use as dict
keys or in sets.
Hermetic decan night geometry now validated at construction
DecanHoursNight now validates its inputs in __post_init__. Invalid night
boundaries (non-finite JDs, inverted sunset/sunrise ordering, wrong number of
hours) raise ValueError at construction time rather than producing silently
corrupt results downstream.
Heliacal stellar rising corrected
The redundant elongation magnitude guard (abs(se) < 12.0°) has been removed
from the rising solver. This eliminated a systematic +1-day offset for stars
with small arcus visionis values (e.g., Regulus at approximately 11°). The
altitude check at the visibility-arc twilight threshold remains the sole rising
criterion, which is the correct formulation.
Operational hardening artifacts in place
- CI gate:
.github/workflows/release-hardening.yml - Doc-consistency checker:
scripts/check_doc_consistency.py - Protected-zone regression discipline:
wiki/03_release/PROTECTED_ZONE_REGRESSION_DISCIPLINE.md
Validation
The following test suites were verified green in the project .venv on 2026-04-10:
tests/unit/test_public_api_drift.py— public API surface stabilitytests/unit/test_public_doctrine_surfaces.py— frozen policy dataclass enforcementtests/unit/test_dasha.py— dasha system correctnesstests/unit/test_timelords.py— timelord engine correctnesstests/unit/test_cycles.py— cycle and return solver correctnesstests/unit/test_electional.py— electional engine correctnesstests/unit/test_hermetic_decans.py— hermetic decan hardeningtests/unit/test_house_hardening.py— house engine consistencytests/unit/test_de441_segment_boundaries.py— DE441 continuity proofstests/unit/test_ephemeris_stress_proofs.py— Delta-T robustness
Full killer-test results are in wiki/03_release/KILLER_TEST_RESULTS.md.
Doc-consistency check passes clean.
Compatibility
See COMPATIBILITY_NOTES_2.0.0.md for a concise migration guide.
Prior version
1.2.1 — production-capable engine state prior to release-integrity hardening.