HomeValidationValidation Report — Astrology

Validation Report — Astrology

Bounded external comparisons, doctrine checks, invariants, and explicit non-oracle cases for astrological convention layers.

Moira Validation Report - Astrology

Version: 1.6 Date: 2026-07-26 Runtime target: Python 3.14 Validation philosophy: external astrology software where stable and meaningful; canonical formulas and doctrine tables where no stable oracle exists; Moira as regression baseline once behavior is validated

Recent release evidence. The source-scoped Pancha Pakshi boundary, dignity policy controls, Gauquelin g5 corpus, spatial house-boundary geometry, and node/family evidence added in Moira 5.1-5.2 is indexed in the 5.1-5.2 release validation ledger.

Hellenistic engine gate evidence. Current source ownership, admission qualifications, and exclusions are recorded in the Hellenistic source validation audit. The capability matrix and API inventory are generated from the current runtime and fail their test gate when they drift.


1. Executive Statement

This document covers the astrological convention layer of Moira: techniques that are built on top of the astronomy engine but involve definitional choices specific to astrological tradition.

The validation standard here differs from the astronomy layer:

  • Swiss Ephemeris / Astro.com swetest is used as a sanity oracle where a stable external chart-software reference actually exists.
  • Some astrological techniques do not have one universally authoritative external oracle. Those are validated by canonical formulas, structural invariants, doctrine documentation, and deterministic test surfaces instead of pretending a nonexistent oracle exists.
  • Where Moira diverges from Swiss or other software, the cause is audited: model difference (expected) vs. implementation bug (must be fixed).
  • Once a technique is confirmed correct, Moira's own output is locked in as the regression baseline.
  • Thresholds are technique-appropriate: pure geometry can hold to microdegree scales, while predictive or doctrine-driven techniques are validated at the level their own assumptions make meaningful.

1.1 Current Rerun Receipt

On 2026-05-21, the full astrology validation corpus named in this document was re-run from the project .venv.

Current corpus result:

  • 1009 collected
  • 1008 passed
  • 1 skipped

The one skip is expected:

  • tests/integration/test_aspects_external_reference.py
    • J1900 has no tight-orb major aspects in the current fixture slice

The house validator script was also re-run successfully:

  • python -X utf8 scripts/compare_swetest.py --offline
    • 7416 iterations
    • 0 failures

This rerun receipt supersedes older point-in-time counts recorded earlier in the paper.


2. Validation Surface

DomainOracle / basisEnforcementStatus
Sidereal systems / ayanamshas (34 systems)Astro.com swetest offline fixturepytestValidated (49 current pytest cases; 31 Swiss-mapped systems plus invariants for the remainder)
House systems (15 systems, 7416 iterations)Swiss setest/t.exp offline fixturepytest + validator scriptValidated (65 current pytest cases + 7416-iteration offline validator)
Aspects (major, tight-orb)Horizons-validated position substrate + angular-distance geometrypytestValidated (unit + integration; 1 expected fixture skip at J1900)
Antiscia / contra-antisciaFormula derivation + invariants (Valens, Lilly)pytestValidated
MidpointsFormula derivation + invariants (Ebertin, Witte)pytestValidated
Lots / Arabic PartsSource-owned formula/output goldens for the four unified-profile lots; typed dependency tests for the broader catalogpytestProfile subset validated; heterogeneous catalog qualified
DignitiesSource-owned bounds and planetary-joy tables; typed component truth; explicit policy testspytestValidated with named source/policy qualifications
HarmonicsFormula derivation + round-trip invariant (Addey)pytestValidated
ProfectionsAnnual/monthly arithmetic, 12-year cycle, and explicit completed-civil-anniversary projection policypytestValidated, policy-qualified
Planetary hoursChaldean sequence + day-ruler derivation (Porphyry, Hephaestio)pytestValidated
Secondary progressionsOffline Swiss swetest fixture at progressed dates + doctrine validationpytestValidated
Solar arc directionsOffline Swiss swetest fixture for arc and directed longitudes + doctrine validationpytestValidated
Primary directionsPlacidus speculum doctrine, arc algebra, and symbolic time-key validationpytestValidated
DashasCanonical Vimshottari doctrine: nakshatra entry, proportional hierarchy, ayanamsa/year-basis settingspytestValidated
ParansHorizons-derived offline paran fixture + validated event substrate + paran logic testspytestValidated
Gauquelin sectorsCanonical diurnal-arc formula + plus-zone invariants (Gauquelin)pytestValidated
Manazil / lunar mansionsEqual-station arithmetic + canonical boundary assignments (al-Biruni)pytestValidated
Decennials L1/L2Valens VI.6-8 source-owned units and arithmetic; typed sequence invariantspytestValidated; L3/L4 are a closed exclusion
Zodiacal ReleasingValens IV.4 same-sign start-shift and 211-month source cases; typed angularity invariantspytestValidated, qualified; interpretation excluded
FirdariaSeparate medieval sequence tables and structural invariantspytestValidated outside the Hellenistic profile
Unified Hellenistic profileExact composition receipts, curated-export identity, serializers, REST models, and OpenAPIpytest + generated inventory checkValidated non-interpretive contract

Status language in this table is intentional:

  • Validated means there is a finished validation story appropriate to the technique as currently implemented.
  • Validated, policy-qualified means the implementation is covered, while a named modern projection or threshold remains policy rather than ancient source data.
  • Profile subset validated does not extend one source claim across a broader heterogeneous catalog.
  • Internally validated means the subsystem has substantial doctrinal, structural, and invariant coverage but the project is still intentionally reserving a stronger validation label for a later external comparison.
  • Needs external oracle means the technique still lacks the external comparison needed to close that part of the validation story.

2.1 Python vs C++ Route Semantics

This paper validates the Python public route unless a section explicitly states otherwise.

That distinction matters because Moira's current native backend is a dual-substrate system, not a second independent doctrine authority.

Current route law:

  • Python owns doctrine semantics.
    • House fallback policy
    • fixed-star wrapper semantics
    • dasha settings and validation doctrine
    • progressions, primary directions, lots, dignities, parans, and timelords all remain Python-governed at the semantic layer
  • Native C++ currently accelerates selected numerical substrata.
    • dispatch-routed Julian/calendar and sidereal primitives where decorated
    • SPK/DAF reader and segment-evaluation layers where native reader ownership is active
    • no astrology-domain doctrine surface is currently native-authoritative

Time semantics differ by route:

  • Moira.houses(dt, lat, lon, ...)
    • accepts a UTC datetime
    • converts UTC -> JD -> UT1
    • then calls calculate_houses(jd_ut1, ...)
  • calculate_houses(jd_ut, ...)
    • expects a numeric UT/UT1 Julian Day already in the correct scale
  • Moira.fixed_star(name, dt)
    • accepts a UTC datetime
    • converts UTC -> JD -> TT
    • then calls star_at(name, jd_tt)
  • star_at(name, jd_tt)
    • expects a numeric TT Julian Day already in the correct scale
  • Moira.twilight(dt, lat, lon)
    • accepts a UTC datetime
    • converts to jd_day and passes that day-start UT value into twilight_times(...)

Validation consequence:

  • public datetime routes and direct substrate routes are both valid, but they do not always carry the same tolerance budget
  • route-specific micro-residuals caused by lawful timescale conversion are documented as route semantics, not mislabelled as engine defects

Concrete current examples from the validation corpus:

  • public houses(datetime, ...) against direct Swiss JD rows uses a slightly wider public-route budget (0.0012 deg) than the raw direct-JD Swiss house threshold (0.001 deg) because the facade lawfully converts through UTC -> UT1
  • public fixed_star(datetime) against direct star_at(jd_tt) uses a dedicated route-equivalence micro-budget (2e-6 deg) rather than exact identity

Current native parity note:

  • the previously documented native calendar_from_jd() parity defect on historical/proleptic Gregorian cases has now been corrected in the native substrate
  • tests/test_native_parity.py now passes, including the earlier boundary samples at JD 0.0, JD 1721058.0, JD 2299160.0, JD 2299161.0, and JD 2451545.0
  • this closes the specific inverse-calendar mismatch, but does not change the governing route law of this paper: astrology validation claims remain anchored to the Python public/reference semantics, while native parity is tracked as a lower-substrate architectural concern rather than as an astrology-doctrine authority

3. Sidereal Systems

Oracle: Official Astro.com swetest CGI output, captured offline Fixture: tests/fixtures/sidereal_swetest_reference.json Thresholds:

  • Mean / polynomial ayanamsas: 0.001 degrees (3.6 arcseconds)
  • Star-anchored ("true") ayanamsas: 0.035 degrees (126 arcseconds)

Test file: tests/integration/test_sidereal_external_reference.py

34 ayanamsha systems are exposed. 31 have direct Swiss-mappable fixture data. 2 systems are permanently excluded from the Swiss fixture:

  • Aryabhata 522 - Moira-specific lineage (Pingree & Plofker); no Swiss sid_mode equivalent exists.
  • Galactic Equator (IAU 1958) - Swiss sid_mode=32 exists but carries a 190" base anchor difference (different galactic-ecliptic node computation, not drift). 1 (Galactic Center 5 Sag) is validated by invariant: Galactic Center 0 Sag
  • 5 degrees.

Validated systems include Lahiri, Fagan-Bradley, Krishnamurti, Raman, Yukteshwar, Djwhal Khul, Hipparchos, Suryasiddhanta, Aryabhata, SS Revati, SS Citra, True Chitrapaksha, True Revati, True Pushya, Aldebaran (15 Tau), Babylonian variants, Galactic Center (0 Sag), Galactic Center (Cochrane), Galactic Center (RGB), and others.

The current external-reference sidereal file contains 49 pytest cases, all passing on the 2026-05-21 rerun.

Route note:

  • sidereal doctrine claims in this paper are Python-route claims
  • native inverse-calendar parity is tracked separately and is not used as authority for historical astrology validation dates

3.1 Star-Anchored True Ayanamsa Model-Basis Difference

Five systems (True Chitrapaksha, True Revati, Aldebaran (15 Tau), True Pushya, True Mula) compute the ayanamsa from the live tropical longitude of a reference star rather than a polynomial formula. Because Moira uses IAU 2006 Fukushima-Williams precession while Swiss Ephemeris uses an older precession model, and because Moira's star pipeline does not include annual aberration (~20.5" maximum effect), a systematic residual exists between Moira and Swiss for these systems:

SystemAnchor starResidual envelopeDominant cause
True ChitrapakshaSpica5-19"Annual aberration (~20.5")
True Pushyadelta Cancri12-18"Aberration + proper motion
True Revatizeta Piscium5-20"Aberration + proper motion
Aldebaran (15 Tau)Aldebaran91-109"High proper motion (-189 mas/yr dec) + precession model

These residuals are model-basis differences where Moira's IAU 2006 pipeline is the stronger model. The 126" threshold envelope accommodates the worst case (Aldebaran at historical epochs). Mean-mode results for the same systems pass at the standard 3.6" threshold because mean mode uses polynomial formulas calibrated to Swiss.

Fixes applied 2026-04-05:

  • TRUE_REVATI target longitude corrected from 0 deg to 359 deg 50 min (Swiss sid_mode=28). Previous error: ~580"; after fix: 5-20".
  • TRUE_PUSHYA target longitude corrected from 106.667 deg (16 deg 40 min Cancer) to 106 deg (16 deg 00 min Cancer, Swiss sid_mode=29). Previous error: ~2413"; after fix: 12-18".

4. House Systems

Primary proof: Moira-owned geometric and structural covenant suites
Secondary oracle: Official Swiss Ephemeris setest/t.exp
Fixture: tests/fixtures/swe_t.exp
Threshold: 0.001 degrees (3.6 arcseconds)
Test files:

  • tests/unit/test_house_projection_geometry.py
  • tests/unit/test_house_polar_branch_selection.py
  • tests/unit/test_house_quadrant_assembly.py
  • tests/unit/test_moira_polar_houses.py
  • tests/unit/test_polar_house_breadth_gauntlet.py
  • tests/unit/test_polar_chart_public_gauntlet.py
  • tests/integration/test_houses_external_reference.py
  • tests/integration/test_houses_polar_external_reference.py
  • python -X utf8 scripts/compare_swetest.py --offline

15 house systems are validated: Placidus, Koch, Campanus, Regiomontanus, Porphyry, Equal, Whole Sign, Alcabitius, Morinus, Topocentric, Vehlow, Meridian, Azimuthal, Krusinski-Pisa, APC.

Current rerun standing for the house layer:

  • 65 pytest cases pass across geometry, polar branch doctrine, public-path fallback coherence, and both broad and polar Swiss external-reference slices
  • the offline validator script confirms 7416 Swiss-derived iterations with 0 failures

Validation order is doctrinally explicit:

  • first, Moira proves the owned geometry directly by invariant tests on plane intersections, branch selection, and quadrant-assembly symmetry
  • second, the cached Swiss corpus is used as a broad regression oracle across historical software-compatible cases
  • therefore "matches Swiss" is not the foundation of this subsystem; it is the external corroboration layer beneath already-owned computational truth

4.1 Corpus composition

The Swiss setest/t.exp fixture contains 12,757 raw ITERATION blocks across six test sections. After analysis, the 7,416 validated iterations are drawn from two distinct calling conventions:

SourceBlocksAPI exercisedNotes
Standard tropical (no flag / iflag=0)3,888swe_houses() + swe_houses_ex(iflag=0)Degree output, tropical; iflag=0 is equivalent to no flag
ARMC-direct3,528swe_houses_armc()ARMC supplied directly from fixture; obliquity computed independently by Moira
Total7,416All pass at 3.6" threshold

The remaining 5,341 blocks are excluded for documented reasons:

CategoryCountReason
iflag=8192 (radians output)720Swiss returns cusps in radians under this flag; same computation, different units - excluded by design
Sidereal (iflag=65536 + isid)1,080Requires ayanamsa-adjusted house computation; see section 4.3
swe_house_pos() blocks1,536Single-point house membership query, no cusp array
Unsupported system (G)312Not mapped in Moira's HouseSystem constants
Missing coordinates18Incomplete fixture records
Total excluded5,341

Stress cases covered across all 7,416 validated iterations:

  • equatorial latitudes
  • polar edge and polar fallback behavior
  • deep southern latitudes
  • multiple east/west longitudes
  • ARMC sweep across full 24-hour range (2-hour increments)

Two systems (Azimuthal, APC) were found genuinely wrong during earlier validation and corrected. All 7,416 iterations now pass.

4.2 ARMC-direct validation

The 3,528 ARMC-direct blocks exercise houses_from_armc() - Moira's equivalent of Swiss swe_houses_armc(). In these blocks the fixture supplies the ARMC value directly (degrees) rather than deriving it from a Julian date and geographic longitude. Moira computes obliquity independently from the block's JD_UT via its own TT conversion and IAU 2006 pipeline.

This makes ARMC-direct validation a clean regression-oracle test: given the exact ARMC that Swiss used, do Moira's house cusp algorithms still produce the same 12 cusp longitudes? Any residual here is attributable solely to the cusp computation itself, not to ARMC derivation. All 3,528 pass at 3.6".

4.3 Sidereal house blocks - residual audit

The 1,080 sidereal blocks (iflag=65536, isid in {0, 18, 27}) were audited but not included in the passing test surface. The residuals are entirely in ayanamsa computation, not in house cusp geometry. When Swiss's ARMC is supplied directly and Moira's ayanamsa is applied, all discrepancy traces to the ayanamsa value alone.

isidSystemMoira constantAyanamsa diff at 2013House cusp residualCategory
0Fagan-BradleyAyanamsa.FAGAN_BRADLEY+1.24"1.24" maxPrecession rate
27True ChitrapakshaAyanamsa.TRUE_CHITRAPAKSHA-9.71"10.0" maxPrecession rate + absent aberration
18J2000None--No Moira constant

Fagan-Bradley (+1.24"): This is not a calibration offset. Decomposition shows:

  • J2000 anchor difference (Moira vs Swiss stored mean): +0.018" - constant, negligible
  • Precession model accumulation (IAU 2006 vs Swiss model, 13.11 years): +1.22" - grows linearly from J2000

The Moira J2000 anchor was calibrated against Swiss at J2000 (difference is 0.018"). The growing component is the precession rate difference between Moira's IAU 2006 Fukushima-Williams model and Swiss Ephemeris's older model. At J2000 the total residual is about 0.02"; at 13 years it is 1.24"; projected to 100 years it reaches about 9.3" in magnitude. This is not fixable by adjusting the J2000 anchor - the source is the precession rate, not the epoch value.

True Chitrapaksha (-9.71"): Same IAU 2006 vs Swiss precession rate difference applies (~0.09"/year), but the dominant source is Moira's fixed-star pipeline not including annual aberration (~20.5" maximum effect). The anchor star Spica's apparent position differs between Moira and Swiss by the aberration amount. This matches the documented residual envelope already recorded in section 3.1 for star-anchored ayanamsas.

Conclusion: Both residuals arise from the same root cause - Moira's stronger IAU 2006 precession substrate produces ayanamsa values that diverge from Swiss as epochs depart from J2000, with star-anchored systems carrying an additional aberration contribution. Neither is a calibration error. Neither is fixable without downgrading the precession model. The house cusp computation itself is correct; the residual lives entirely in the ayanamsa layer.

isid=18 (J2000 ayanamsa): Swiss SE_SIDM_J2000 anchors the tropical and sidereal zodiacs to coincide at J2000.0, accumulating purely from precession thereafter. Moira does not yet have a corresponding constant. If added, it would carry the same precession rate residual as Fagan-Bradley (~0.09"/year), since the J2000 anchor would be exact by construction. since the J2000 anchor would be exact by construction.


5. Aspects

Validation layers:

  • Layer A - position substrate: ecliptic longitudes are produced by Moira's planet_at() pipeline, which is externally validated against JPL Horizons. Storing those positions in the fixture anchors aspect geometry to a validated astronomical substrate.
  • Layer C - angular-distance arithmetic: for every body pair the fixture records the expected angular separation. The tests recompute those separations from scratch and verify they match the stored values to within a pure-geometry threshold.

Fixture: tests/fixtures/aspects_reference.json
Generated by: scripts/build_aspects_fixture.py
Threshold: 1e-6 degrees
Test file: tests/integration/test_aspects_external_reference.py
Aspect tier: major aspects only
Tight-orb window: 1.0 degree
Epochs: J1900, J1950, J2000, J2024
Bodies: 10 major bodies (Sun through Pluto)

Minor aspects remain covered by the larger unit suite in tests/unit/test_aspects.py.

Current rerun standing:

  • 10 integration cases are currently collected from the offline fixture
  • 9 pass
  • 1 is the expected J1900 skip because no tight-orb major aspects exist in that fixture epoch

6. Rule-Engine Validation

Primary test file: tests/unit/test_rule_engine_validation.py

The following modules are pure arithmetic / rule-table engines with no ephemeris dependency. Their validation is therefore formula-derivation and invariant-based rather than external-oracle comparison.

6.1 Antiscia and Contra-antiscia

Canon: Vettius Valens, Anthology II.37; William Lilly, Christian Astrology (1647) p. 90
Formula: antiscion = (180 - lon) mod 360; contra = (360 - lon) mod 360
Validation: hand-derived reference table, round-trip invariants, contact detection, and seam-edge cases

6.2 Midpoints

Canon: Reinhold Ebertin, The Combination of Stellar Influences (1940); Alfred Witte, Rules for Planetary Pictures
Formula: shorter-arc midpoint; 90-degree dial projection
Validation: hand-derived midpoint table, commutativity, self-midpoint, pair-count, sort-order, and seam-crossing invariants

6.3 Profections

Canon: Chris Brennan, Hellenistic Astrology (2017), Ch. 9; Vettius Valens, Anthology, Book IV
Formula: profected ASC = (natal_asc + age * 30) mod 360; house = (age mod 12) + 1
Validation: hand-derived table across ages 0-30, house-range guard, monthly-lord length and first-lord invariants, 12-year cycle identity, exact anniversary boundaries, and February 29 handling

The sign-cycle doctrine and the civil projection are separate claims. Completed civil anniversaries and leap-day handling are explicit Moira policy, not a reconstructed ancient civil-calendar rule.

6.4 Planetary Hours

Canon: Porphyry, Introduction to Tetrabiblos; Hephaestio of Thebes, Apotelesmatika I
Validation: Chaldean sequence, weekday day-ruler mapping, first night-hour derivation, 24-hour completeness, and the next-day +3 shift invariant

6.5 Harmonics

Canon: John Addey, Harmonics in Astrology (1976)
Formula: harmonic longitude = (natal_lon * H) mod 360
Validation: hand-derived table, H1 identity, output-range invariant, sorting, and harmonic-number clamping

6.6 Lots / Arabic Parts

Canon: Paulus Alexandrinus, Introductory Matters; Vettius Valens, Anthology Books II-IV
Formula: ASC + Add - Sub modulo 360, with night reversal where doctrine requires it
Validation: source-owned day/night formulas and concrete outputs for Fortune, Spirit, Valens Eros, and Valens Necessity; dependency completeness, range guards, and the Fortune/Spirit complement invariant

This source claim is limited to the four lots admitted by HellenisticChartProfile. The wider catalog has mixed Hellenistic, medieval, and modern authorities and remains source-qualified item by item.

6.7 Dignities

Canon: William Lilly, Christian Astrology Book I; Ptolemy, Tetrabiblos I.17-22
Validation: complete source-owned Egyptian/Ptolemaic bounds and sect-explicit Chaldaean construction rules; source-owned planetary-joy houses; typed essential, sect, solar phase/proximity, besieging, and reception truth; legacy-score projection invariants; mutual reception; deterministic ordering; and fail-closed dependency behavior

Solar proximity thresholds and the besieging enclosure orb remain named policies. Halb/Hayz is admitted from a medieval al-Qabisi/Bonatti lineage and is not relabeled as ancient Hellenistic doctrine.


7. Predictive and Extended Technique Validation

The techniques below are not correctly described as "untested." They already have real validation surfaces. The distinction is whether that surface is a finished external-oracle comparison or a strong internal / doctrinal pass.

7.1 Secondary Progressions and Solar Arc Directions

Current validation surface: tests/unit/test_moira_progressions.py, tests/unit/test_progressions_public_api.py, tests/integration/test_progressions_external_reference.py
Backend standard: moira/docs/PROGRESSIONS_BACKEND_STANDARD.md

What is already validated:

  • secondary progression time-key mapping (1 day = 1 year)
  • solar arc as progressed Sun minus natal Sun
  • Naibod longitude and right-ascension variants
  • converse forms of supported progression techniques
  • tertiary, tertiary II, and minor progression mapping rules
  • ascendant-arc and daily-house-frame doctrine
  • doctrine/classification/relation/condition-profile invariants
  • policy override behavior and deterministic failure modes
  • Swiss swetest longitudes for secondary progressions at curated progressed dates
  • Swiss-derived solar-arc values and directed longitudes from the same curated cases

What is not yet externally validated:

  • progressed Ascendant / MC against an external chart oracle
  • published historical examples as software-to-software spot checks

Fixture: tests/fixtures/progressions_swetest_reference.json
Builder: scripts/build_progressions_swetest_fixture.py
Threshold: 1.0 arcsecond\

Status: externally validated for planetary positions and solar-arc values against offline Swiss references; angle-specific extensions remain desirable.

7.2 Dashas

Current validation surface: tests/unit/test_dasha.py
Backend standard: moira/docs/DASHA_BACKEND_STANDARD.md

What is already validated:

  • Vimshottari year-basis doctrine and policy handling
  • birth nakshatra capture and nakshatra-fraction preservation
  • Mahadasha through Prana hierarchy generation
  • active-line, condition-profile, sequence-profile, and lord-pair layers
  • structural invariants, containment checks, and malformed-input rejection
  • fixed lord sequence and canonical year allocations
  • antardasha and deeper-level proportional duration doctrine
  • ayanamsa-sensitive nakshatra entry through the declared policy surface

Research conclusion:

  • there is no stable Swiss-like oracle for Vimshottari that can be treated as final authority across software without first fixing doctrine settings
  • public and commercial software vary on at least ayanamsa and year basis
  • therefore the authoritative validation target for Vimshottari is doctrine, not software mimicry

Oracle harness now present:

  • manual fixture template: tests/fixtures/vimshottari_reference.manual.json
  • normalizer: scripts/build_vimshottari_manual_fixture.py
  • offline integration suite: tests/integration/test_vimshottari_external_reference.py

Reference doctrine adopted for Moira validation:

  • ayanamsa: Lahiri
  • year basis: julian_365.25 by default, with alternate basis handling tested explicitly

Status: validated against doctrine and invariants. External Vedic software comparison is optional supplemental cross-checking, not a prerequisite for claiming a truthful validation story.

7.3 Primary Directions

Current validation surface: tests/unit/test_primary_directions.py\

What is now validated:

  • Placidus mundane speculum construction on analytically simple equatorial cases
  • semi-arc and mundane-fraction behavior across upper and lower hemisphere cases
  • direct and converse arc algebra for simple speculum pairs
  • symbolic time-key conversion for Ptolemy, Naibod, and solar keys
  • arc filtering, ordering, self-direction exclusion, and solar-rate handling

Status:

  • validated by doctrine, explicit speculum math, and invariant-based unit tests
  • external software comparison remains useful as supplemental cross-checking, but the subsystem is no longer undocumented or validation-empty

7.4 Parans

Current validation surface: tests/unit/test_parans.py, tests/integration/test_parans_external_reference.py
Backend standard: moira/docs/PARANS_BACKEND_STANDARD.md

What is already validated:

  • crossing extraction delegates consistently to the validated rise/set/transit engine
  • paran matching, classification, policy filters, strength, and stability layers
  • field sampling, contour extraction, contour consolidation, and structure analysis
  • deterministic failure behavior and invariant preservation
  • offline Horizons-derived expected paran matches for curated multi-body cases
  • a high-latitude no-paran case derived from the same external event oracle

Fixture: tests/fixtures/parans_horizons_reference.json
Builder: scripts/build_parans_horizons_fixture.py\

Status: validated against an external event oracle for curated paran cases, plus the existing internal coverage for matching, policy, and field behavior.

7.5 Gauquelin Sectors

Current validation surface: tests/unit/test_experimental_validation.py, tests/unit/test_session_fixes.py, tests/integration/test_gauquelin_external_reference.py, scripts/validate_g5_gauquelin_sectors.py, and wiki/03_validation/GAUQUELIN_G5_HISTORICAL_VALIDATION_2026-07-20.md

Validated against the canonical diurnal-arc sector model:

  • sector falls in 1-36 when ordinary rise/set geometry exists and is None otherwise
  • primary plus zones are exactly sectors 1-3 and 10-12
  • Ascendant-anchored half-open boundary numbering is explicit: sectors 1, 10, 19, and 28 begin at ASC, MC, DSC, and IC respectively
  • zone labels match plus-zone membership
  • circumpolar, never-rising, and horizon-coincident inputs expose horizon_status while leaving sector-derived quantities undefined
  • cached Swiss swe_gauquelin_sector() method-0 Sun rows match within the fixture precision of 1e-3 sector units
  • 1,107 of 1,120 historical CFEPP Mars assignments match exactly after the source's 12-sector grouping is applied; all 13 differences are adjacent-bin cases within 0.535° of a 12-sector boundary
  • 904 of 916 explicit-LMT Müller Mars assignments match exactly at 36-sector resolution; seven differences are adjacent bins and five remain source outliers

The external personal-record archive remains non-bundled. Its committed aggregate fixture contains no names, dates, places, or coordinates. This technique is already validated and should not be described as merely "mentioned."

7.6 Manazil / Lunar Mansions

Current validation surface: tests/unit/test_experimental_validation.py

Validated as canonical equal-station arithmetic:

  • MANSION_SPAN = 360 / 28
  • all 28 mansions are reachable
  • boundary advancement and wraparound are correct
  • degrees_in stays in range for all tested longitudes

This is a real validation pass for the current doctrine. A future comparison to published mansion tables would be supplemental, not the first validation.

7.7 Hellenistic Time Lords and Separately Scoped Firdaria

Current validation surface: tests/unit/test_timelords.py and tests/unit/test_hellenistic_source_goldens.py

What is already validated:

  • Decennial L1/L2 129-unit circuit, minor-period allotments, 30-day symbolic months, admitted sequence arithmetic, grouping, and active-path truth
  • Zodiacal Releasing same-sign Fortune/Spirit start shift, exact 211-month circuit behavior, minor-year table integrity, level scaling, typed angularity, grouping, and active-pair truth
  • diurnal/nocturnal Firdaria tables, Bonatti variant behavior, node handling, sub-period structure, and sequence totals on its separate medieval surface

Decennial L3/L4 are outside the closed L1/L2 contract. Zodiacal Releasing interpretation is excluded. Firdaria is live and separately tested but is structurally excluded from HellenisticChartProfile.

Status: admitted Hellenistic arithmetic is validated against named Valens evidence plus invariants; Firdaria is validated separately. External software comparison may still be useful as a supplemental cross-check.

7.8 Unified Hellenistic Profile

Current validation surface: tests/unit/test_hellenistic_profile.py, tests/unit/test_hellenistic_contract_parity.py, tests/server/test_server_hellenistic_profile.py, and the generated capability and OpenAPI inventory checks.

The profile composes exact score-free atomic receipts for Whole Sign framing and aspects, dignity components and planetary condition, triplicity, bounds, ordinary faces, four source-locked lots, annual profection, Decennials L1/L2, and Zodiacal Releasing. Curated imports, facade methods, serializers, REST models, and OpenAPI schemas preserve the same policy and provenance.

Firdaria, medieval almutens, later electional rules, unscoped primary directions, Decennial L3/L4, Hermetic geometry, and Valens distribution interpretation are typed exclusions. No chart-wide score, recommendation, or interpretive narrative is admitted.


8. Supplemental Validation Expansion Roadmap

8.1 Aspects

Recommended oracle: Astro.com chart output or Solar Fire
Threshold: 0.001 degrees

Useful next checks:

  • minor-aspect software comparison
  • applying vs separating determination
  • partile detection
  • out-of-sign aspect behavior
  • orb-calculation consistency across chart software

8.2 Primary Directions

The current Placidus mundane implementation is now doctrine-validated.

Useful supplemental expansion:

  • software-to-software spot checks against one declared model only
  • converse examples from published traditional sources
  • angle-specific historical examples
  • explicit variant separation if Regiomontanus or topocentric directions are added

8.3 Secondary Progressions

External oracle coverage is already in place via the offline Swiss swetest fixture in tests/fixtures/progressions_swetest_reference.json.

Useful supplemental expansion:

  • progressed Ascendant and MC
  • progressed lunation cycle
  • known historical examples

8.4 Solar Arc Directions

External oracle coverage is already in place for solar-arc values and directed planetary longitudes via the offline Swiss swetest fixture.

Useful supplemental expansion:

  • converse solar arcs
  • directed angles
  • known historical examples

8.5 Dashas

External-software comparison for Vimshottari is now treated as supplemental, not foundational.

If performed, it must declare at minimum:

  • ayanamsa
  • year basis
  • hierarchy depth being compared

Useful supplemental checks:

  • Mahadasha / Antardasha dates for a few known charts in JHora or Parashara's Light
  • birth nakshatra agreement under explicit Lahiri settings

Implementation note:

  • the repo contains a manual-oracle harness for optional software-to-software comparison, but doctrine validation is the primary standard

8.6 Parans

The subsystem is now externally anchored through Horizons-derived event timing for curated paran cases.

Useful supplemental expansion:

  • dedicated paran-software spot checks where the software's paran doctrine is declared
  • named-star focused examples beyond the current planet-heavy external corpus
  • more latitude-sensitive mixed-event cases

8.7 Manazil / Lunar Mansions

Recommended oracle: published lunar-mansion tables (Ibn Arabi, Picatrix, al-Biruni variants as implemented)

What to validate:

  • mansion boundary calculation against published tables
  • Moon mansion assignment for known dates
  • name-map consistency across Arabic / Sanskrit naming layers if both are exposed

9. Astrology Validation Status

DomainCurrent stateRecommended oraclePriority
House corpus expansionClosed, re-verified 2026-05-21. Standard tropical blocks remain 3,888, ARMC-direct blocks remain 3,528, and the validated Swiss-derived house corpus remains 7,416 iterations total. The current pytest surface for houses is 65 passing cases across geometry, branch doctrine, public fallback behavior, and external-reference slices. Sidereal house residuals remain classified as ayanamsa-layer model-basis differences, not cusp-computation defects.Swiss setest/t.expClosed
Sidereal true-ayanamsa target fixesClosed, re-verified 2026-05-21. TRUE_REVATI remains corrected from 0 deg to 359 deg 50 min and TRUE_PUSHYA remains corrected from 106.667 deg to 106 deg. Residuals remain in the documented 5-20 arcsecond envelope and are still classified as model-basis differences between Moira's IAU 2006 path and Swiss.Astro.com swetestClosed
Sidereal fixture coverage gapClosed, re-verified 2026-05-21. The current offline sidereal corpus still covers 31 Swiss-mapped systems, with Aryabhata 522 and GALEQU_IAU1958 remaining intentionally excluded for stated methodological reasons. The live integration file now collects 49 cases, all passing on rerun.Astro.com swetestClosed
Aspects integration fixtureClosed, re-verified 2026-05-21. aspects_reference.json remains anchored to Horizons-validated positions across four epochs. The current integration file collects 10 cases: 9 pass and the J1900 no-tight-orb case remains the one expected skip.Horizons-validated substrateClosed
Vimshottari integration fixtureClosed, re-verified 2026-05-21. The manual-oracle corpus still contains the three declared Lahiri plus Julian-year reference cases, and the current integration file still collects 4 passing cases. Doctrine validation remains the primary proof surface because no single Swiss-like external authority exists for Vimshottari without first fixing settings.Doctrinal self-consistencyClosed
Python versus native route semanticsPartially closed, re-verified 2026-05-21. Astrology validation claims in this paper remain anchored to the Python public/reference route, and native C++ is still not treated as a second astrology-doctrine authority. However, the specific native calendar_from_jd() parity defect on historical/proleptic Gregorian cases has been corrected, and tests/test_native_parity.py now passes on the previously failing boundary samples. Broader route-authority separation remains intentional doctrine, not an unresolved bug.Python public route plus native parity auditIntentional
Hellenistic source ownership and public-contract inventoryClosed 2026-07-26. Independent goldens now own the admitted source tables and disputed time-lord cases; generated capability and OpenAPI inventories track current runtime truth and prohibited public paths. Qualifications and exclusions remain explicit rather than being counted as completion.Named editions, hand-authored goldens, runtime/OpenAPI generationClosed engine gate