Metadata-Version: 2.4
Name: moira-astro
Version: 6.2.1
Summary: Ephemeris and astrology engine with native C++ core, built on JPL DE441 and SPK kernels.
Author: Moira contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/TheDaniel166/moira
Project-URL: Repository, https://github.com/TheDaniel166/moira
Project-URL: Issues, https://github.com/TheDaniel166/moira/issues
Keywords: astronomy,astrology,ephemeris,jpl,spk,sidereal,houses,transits,swiss-ephemeris,horoscope,natal-chart,python-astrology,celestial-mechanics,jpl-de441,astrometry,ephemeris-engine,reproducible-science,astrology-api,planetary-positions,IAU-2006
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Astronomy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: lunar-graze
Requires-Dist: spiceypy>=8.0; extra == "lunar-graze"
Requires-Dist: laspy[lazrs]>=2.7; extra == "lunar-graze"
Requires-Dist: requests>=2.31; extra == "lunar-graze"
Provides-Extra: server
Requires-Dist: fastapi<0.137,>=0.115; extra == "server"
Requires-Dist: starlette<1.3,>=0.46; extra == "server"
Requires-Dist: uvicorn>=0.30; extra == "server"
Requires-Dist: pydantic>=2.8; extra == "server"
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: cmake>=3.24; extra == "dev"
Requires-Dist: pybind11>=2.12; extra == "dev"
Requires-Dist: twine>=6.0; extra == "dev"
Requires-Dist: pytest>=9.0; extra == "dev"
Requires-Dist: pytest-cov>=6.0; extra == "dev"
Requires-Dist: pytest-xdist>=3.5; extra == "dev"
Requires-Dist: ruff==0.16.0; extra == "dev"
Requires-Dist: pyyaml>=6.0; extra == "dev"
Requires-Dist: hypothesis>=6.100; extra == "dev"
Requires-Dist: httpx<0.29,>=0.27; extra == "dev"
Requires-Dist: pyerfa>=2.0; extra == "dev"
Requires-Dist: astropy>=6.0; extra == "dev"
Dynamic: license-file

# Moira

**Ephemeris and Astrology Computation Engine**

[![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
[![MIT License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![PyPI](https://img.shields.io/pypi/v/moira-astro.svg?label=PyPI&color=orange)](https://pypi.org/project/moira-astro/)
[![Precision: ERFA-Audited](https://img.shields.io/badge/Precision-ERFA--Audited-success.svg)](#validation-evidence)
[![Ephemeris: JPL DE4xx](https://img.shields.io/badge/Ephemeris-JPL%20DE4xx-blueviolet.svg)](https://naif.jpl.nasa.gov/naif/index.html)
[![AI Visibility: Optimized](https://img.shields.io/badge/AI--Visibility-Optimized-success.svg)](llms.txt)
[![Status: Stable](https://img.shields.io/badge/status-stable-success.svg)](#requirements-and-installation)
[![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.19152528-blue.svg)](https://doi.org/10.5281/zenodo.19152528)
<a href="https://tools.launchllama.co?utm_source=badge&utm_medium=referral" target="_blank" rel="noopener noreferrer"><img src="https://speaktechenglish.com/wp-content/uploads/2026/04/Screenshot_2026-04-09_at_17.40.44-removebg-preview.png" alt="Featured on Launch Llama" width="200" height="50" /></a>

Moira is an astronomy-first astrology engine built for transparent astrology calculations, reproducible chart computation, and an inspectable calculation chain from astronomical inputs to astrological outputs. It is an auditable astrology engine with explicit computational policy, deterministic behavior, and readable reduction stages grounded in modern standards and references including JPL DE441, IAU 2000A/2006, ERFA/SOFA-aligned practices, and Gaia DR3-linked star data where applicable. A required C++17 extension (`_moira_native`, compiled with pybind11) accelerates admitted numerical substrates including nutation, SPK/DAF access, apparent-place evaluation, coordinate transforms, harmogram computation, and selected event-search primitives. Python remains the governing layer for public semantics, doctrine, policy, and orchestration.

## Why Moira Exists

Most astrology software surfaces results without exposing the mathematical path. Moira exists as a Swiss Ephemeris alternative for users who need visibility into assumptions, intermediates, and provenance, so astronomy remains the foundation and astrology remains the purpose.

## AI and LLM Visibility

Moira is designed to be highly discoverable and understandable by AI agents (e.g., GitHub Copilot, ChatGPT, Claude). 

- **Machine-Readable Index**: See [llms.txt](llms.txt) for a high-level summary and [llms-full.txt](llms-full.txt) for a comprehensive documentation index.
- **Agent Doctrine**: The [AGENTS.md](AGENTS.md) file defines the "Urania" persona and operational laws for AI collaboration.
- **Structured Documentation**: Canonical documentation is maintained in the `wiki/` directory with explicit validation reports.

## What Makes It Different

Moira is designed for full computational transparency: the computation pipeline is explicit and its stages are named and controllable via the Python API, computational doctrine is explicit rather than hidden in defaults, and validation is treated as first-class evidence rather than post-hoc narrative. The high-performance core (`_moira_native`) is C++17; the Python layer owns the API surface, orchestration, and per-stage controls.

## Who It Is For

Moira is for developers, researchers, and serious practitioners who want a programmable, audit-ready engine for high-integrity astrological work, reproducible pipelines, and methodical comparison against external authorities.

## What It Is Not

Moira is not primarily a UI app, not a thin wrapper over opaque compiled stacks, and not convenience-first astrology output generation without traceability.

## Quick Capabilities

Moira computes planetary and stellar positions, houses, aspects, lots, dignities, predictive techniques, a full Vedic/Jyotish suite (yogas, Shadbala, Ashtakavarga, upagrahas, avasthas, Jaimini), eclipse and occultation events, and related analytical products on top of a modern astronomical substrate (JPL kernels, IAU models, and validated star frameworks), with a native C++ computational core, Python orchestration layer, inspectable intermediate stages, and an optional FastAPI REST server (`moira_server`) exposing the engine as typed, versioned routes.

---

## What Moira Computes

### Positions and Bodies

- **Planets and luminaries** — geocentric and topocentric reduction with iterative light-time, annual aberration, multi-body relativistic deflection (Sun, Jupiter, and Saturn, excluding the target body), IAU 2006 frame bias, and WGS-84 topocentric parallax.
- **Fixed stars** — sovereign registry of 1,809 named stars with proper motion, parallax, epoch propagation, and Stellar Quality classification. Audited anchor residual against SOFA/ERFA: 0.00048 arcseconds (J1000–J3000).
- **Position-capable asteroid ephemeris** — two layers. The wheel ships catalog
  `moira-asteroids-wheel` release `2026.08.14.1`: 25 named bodies (classical
  four, named Centaurs including Chiron, named TNOs, and selected others) as
  one Type-13 shard, so Chiron and the locked roster compute after `pip install`
  plus a planetary kernel. The full optional external catalog of 10,025
  selected asteroids remains release `2026.08.12.1` (401 Type-13 SPK shards
  from JPL Horizons, 10-day / 7-node sampling, manifest-discovered under any
  kernel search root). The wheel also carries the matching 10,025-body
  canonical identity registry (names only, no positional vectors). This
  positional product is distinct from the bundled Proper25/PDS
  family-membership catalog (342 families, 200,726 unique numbered asteroids,
  221,095 membership rows). User-supplied `.bsp` kernels remain supported
  through `daf_writer` for numbered minor planets available from the selected
  source.
- **Numbered periodic comets** — 497 comets (1P/Halley through 516P) in
  immutable external release `2026.07.28.1`, generated from JPL Horizons as
  20 sharded Type-13 kernels with manifest-declared coverage, canonical
  numbered designations (`"1P/Halley"`), and curated family-scoped short
  aliases. Dedicated comet surfaces accept those aliases directly; unified
  position/chart surfaces require a canonical designation or an explicit
  `comet:` qualifier when an alias also names an asteroid.
- **Uranian / Hamburg School bodies** — 8 hypothetical transneptunian planets (Cupido through Poseidon) plus Transpluto.
- **Lunar nodes and apsides** — True Node, Mean Node, Mean Lilith, True Lilith, and orbital nodes/apsides for all planetary bodies.
- **Variable stars** — phase and magnitude engine for eclipsing binaries and intrinsic variables; dedicated Algol API.
- **Multiple star systems** — Kepler orbital mechanics for visually resolvable pairs (Sirius AB, Alpha Centauri AB); catalog of 8 astrologically significant systems across VISUAL, WIDE, SPECTROSCOPIC, and OPTICAL types.

### Chart Calculation

- **House systems** — 22 systems including Placidus, Koch, Regiomontanus, Campanus, Morinus, Porphyry, Whole Sign, Equal, APC, Pullen Sinusoidal Delta/Ratio, and Sunshine. Includes branch-aware high-latitude doctrine where admitted, explicit polar fallback policy, and `house_of` for direct house placement lookups.
- **Aspects** — 22 zodiacal aspects with applying/separating/stationary motion-state detection; declination parallels and contra-parallels; antiscia and contra-antiscia; exact partile and orbed platic status markers (`is_partile`, `is_platic`).
- **Aspect patterns** — 21 multi-body configurations: T-Square, Grand Trine, Grand Cross, Yod, Kite, Mystic Rectangle, Stellium, Grand Sextile, Thor's Hammer, Boomerang Yod, and more.
- **Midpoints** — full midpoint matrix, midpoint trees, 90°/45°/22.5° dial projections, planetary pictures.
- **Traditional dignities** — domicile, exaltation, triplicity (diurnal/nocturnal), Egyptian and Ptolemaic terms, face, sect, hayz, and Almuten Figuris.
- **Arabic Parts** — 512 lot definitions with dependency graphs and condition profiling.
- **Classical decanates** — Chaldean faces, triplicity decans, and Vedic
  drekkana; the Gundel/Harley Hermetic name-and-face catalog is reconstructed
  for research, while its geometry remains excluded from public and REST
  surfaces and unsupported fixed-star assignments fail closed.
- **Unified Hellenistic profile** — a non-interpretive, score-free Whole Sign
  composition of typed receipts for essential dignity components, sect, joy,
  solar proximity and phase, besieging, receptions, lots, annual and dated
  monthly profections, Decennials L1/L2, and Zodiacal Releasing. Dependency
  gaps return explicit `not_evaluable` truth; medieval Firdaria and almutens,
  Hermetic geometry/star attribution, Decennial L3/L4, and unscoped
  interpretive branches remain outside this product contract.
- **Draconic charts** — node-anchored draconic frame (mean or true node) with longitude rotation, engine-backed chart derivation, and caller-supplied position support.

### Predictive Techniques

- **Progressions** — secondary, tertiary, minor, solar arc (longitude and right ascension), Naibod, ascendant arc; direct and converse variants for all methods.
- **Primary directions** — eight admitted geometry methods across in-mundo and
  in-zodiaco policies (Placidus mundane, Ptolemy semi-arc, Placidian classic,
  meridian, Morinus, Regiomontanus, Campanus, and topocentric), exposed through
  25 named presets; direct and converse directions with explicit converse
  doctrine; speculum computation; fixed-star targets; and Ptolemy, Naibod,
  Cardan, and caller-supplied solar time keys.
- **Returns** — solar and lunar returns; planet returns.
- **Time lords** — annual profections with exact, civil-anniversary-bounded
  monthly intervals; Zodiacal Releasing (Vettius Valens method); admitted
  Decennials L1/L2; Firdaria (diurnal and nocturnal sequences, including the
  Bonatti variant, explicitly outside the Hellenistic profile).
- **Vitality doctrine** — Hyleg and Alcocoden calculations, kept distinct from
  time-lord chronology.

### Vedic / Jyotish Suite

Admitted Vedic surfaces name their governing classical source, modern lineage,
or source-scoped witness (including BPHS, Brihat Jataka, Saravali,
Phaladeepika, Uttara Kalamrita, Jataka Parijata, Jaimini Upadesa Sutras, and
the named 1879 Agastya- and 2024 Bogamuni-attributed Pancha Pakshi witnesses).
Where sources disagree or a modern composition is required, Moira exposes the
policy or qualification instead of presenting one silent universal rule.

- **Sidereal foundation** — 12 admitted ayanamsha systems including star-anchored "True" ayanamshas; 27-nakshatra system; Panchanga.
- **Pancha Pakshi** — an explicitly named Agastya-attributed Madras 1879
  aksara/query-or-name-initial fixed-clock schedule and directed relationship
  profile, with exact rational timing, source locators, declared omissions,
  and no implicit or universal default. A separate astronomical-paksha product
  evaluates apparent geocentric Moon-minus-Sun longitude in the true ecliptic
  of date and maps `[0, 180)` Shukla/waxing to the profile's source-attested
  Purva label and `[180, 360)` Krishna/waning to Amara. It accepts no location
  and never selects a schedule, materializes a clock, supplies paksha to another
  operation, or infers natal identity. An explicit modern local-solar context
  policy can derive topocentric day/night and local-mean-solar weekday for an
  aware instant and location while requiring the caller to supply Purva or
  Amara. A separate modern fixed-clock policy anchors the selected schedule at
  sunrise or sunset, treats one nazhigai as exactly 1,440 SI seconds on
  reader-bound TT, and publishes half-open UT1 cell intervals plus their
  unclipped relation to the astronomical half end. A separately named
  solar-half-first selector returns the unique current fixed-clock cell under
  exact half-open TT ownership, or the explicit
  `unmaterialized_solar_half_tail` status when a long solar half outlasts the
  fixed span. A distinct modern solar-proportional policy can instead preserve
  the exact nominal offset fractions and map them independently across the
  complete governing day or night half on reader-bound TT, returning 25
  half-open TT/UT1 cells with exact astronomical-boundary closure. The 1879
  witness is not credited with that proportional rule. A separate
  solar-half-first selector identifies the unique proportional cell through
  exact half-open TT ownership; complete-half coverage means its lawful status
  is always `selected`, with no fixed-clock tail or fallback. Paksha remains
  caller supplied on every schedule, materialization, and current-cell surface;
  the standalone astronomical inference is never applied automatically, and
  the 1879 profile remains explicitly non-natal. A pure Stage 2I lookup exposes
  the selected 1879 generator's first-samam EAT seed from explicit profile
  Paksha, day/night half, and weekday. It does not materialize the schedule or
  promote that seed into a whole-day eating bird, Padu, authority,
  Adhikara/Bharana, condition, score, or forecast. All 28 cells are directly
  bound to the governing 1879 leaves and separately corroborated by the 1934
  Uromarisi publication; textual-lineage independence is not claimed. A
  separate named Bogamuni 2024
  profile preserves a complete 54-cell Purva/Amara-by-nakshatra bird table.
  Its Amara verse governs because the adjacent commentary duplicates Shravana
  and omits Revati; that malformed commentary remains visible as rejected
  conflict evidence. The fixed modern
  `bogamuni_2024_apparent_lahiri_natal_moon_identity_v1` composition evaluates
  apparent geocentric Sun and Moon positions on one reader-bound TT epoch,
  derives the source-mapped lunar half, applies Lahiri true ayanamsa, assigns
  the Moon to one of 27 equal half-open nakshatras, and returns the selected
  source-table bird with every intermediate and locator visible. The source
  attests nakshatra birds and phase labels; birth-Moon application, Lahiri, and
  the equal-sector boundary policy are explicitly Moira-owned, not source
  claims. It never routes into a schedule, current cell, score, or forecast. A
  third source-scoped Bogamuni 2024 profile,
  `bogamuni_chennai_2024_padu_bird_mapping`, preserves the separate 14-cell
  Purva/Amara-by-weekday Padu-bird table. It is a pure explicit-label lookup:
  the source table has no day/night axis, and its death-or-inoperative bird is
  not relabelled as a schedule `RULE` activity, a generic authority bird, or
  the separately labelled eating bird. The primary witnesses do not present an
  `Adhikara Pakshi` table, while Bharana is secondary terminology only; neither
  alias nor product is admitted. The Padu profile performs no natal identity,
  astronomical routing, schedule/current-cell selection, condition scoring,
  or forecast.
- **Dashas** — Vimshottari with nakshatra balance; Chara Dasha (K.N. Rao's named lineage).
- **Varshaphal** — annual chart calculation.
- **Vargas** — divisional charts (navamsa, dashamansa, dwadashamsa, saptamsa, trimshamsa, and more); Vimshopaka Bala (BPHS 20-point varga-dignity strength over all four classical groups) with vargottama detection.
- **Yogas** — 61 classical yogas across six families (Pancha Mahapurusha, Chandra, Surya, all 32 Nabhasa, Raja core, Dhana core), each returned as a proof object: formation conditions with observed evidence, cancellation (bhanga) clauses evaluated first-class, and per-yoga primary-source citations.
- **Shadbala** — the complete six-fold strength system plus Bhava Bala (house strength), inline Ishta/Kashta Phala on every planet, and Graha Yuddha transfer disclosure.
- **Ashtakavarga** — bindu tables plus kakshya-level transit evaluation (Saturn-first lord order) and Shodhya Pinda, validated to the digit against BPHS Ch. 69's own worked example.
- **Upagrahas** — the five kalavelas (Gulika, Kala, Mrityu, Ardhaprahara, Yamaghantaka) with portion-point, Mandi-mode, and lord-sequence lineage policies, plus the five Sun-derived upagrahas.
- **Avasthas** — Baladi, Jagradadi, and Deeptadi as per-source rule tables (BPHS / Saravali / Jataka Parijata / Phaladeepika, never merged), plus the six non-exclusive Lajjitadi flags with evidence strings.
- **Jaimini** — rasi drishti, arudha padas A1–A12 (Rath/JHora exception default, Raman variant as policy), argala with virodha pairs, and karakamsa with both lineage readings named (Rath D9 vs. K.N. Rao D1).
- **Muhurta** — Tara Bala (nine-tara cycle) and Chandra Bala (Chandra Shuddhi with Chandrashtama flagged) as a natal-personalized electional overlay.
- **Sade Sati** — phase classification (rising/peak/setting) with Ashtama and Kantaka Shani flags, and kernel-timed phase windows via Saturn sidereal sign-ingress bisection, with retrograde re-entries reported as separate windows.

### Advanced Astronomy

- **Eclipses** — NASA-canon contact solver for solar and lunar eclipses; Saros series classification with heptagonal vertex labelling; local circumstance computation.
- **Visibility and heliacal phenomena** — heliacal and acronychal rising and
  setting, planetary elongation extremes, and opt-in physical point-source
  assessment and four-phase first/last event paths. The physical model exposes
  its atmosphere, directional background, spectral response, threshold,
  horizon, solver, error-budget, and data identities; out-of-domain or missing
  evidence fails closed. It requires the separately distributed
  `moira-physical-heliacal-visibility` `1.2.0` data pack and never downloads it.
  The legacy criterion remains the default, and Yallop lunar-crescent
  classification remains a separate policy family.
- **Parans** — paranatellonta field analysis with contour extraction and stability metrics.
- **Occultations** — lunar occultation of stars and planets; close-approach detection.
- **Stations** — retrograde stations with precise stationary-point search.
- **Mapping** — Astrocartography (ACG) lines for all planets; Local Space chart positions; Gauquelin sectors.
- **Galactic coordinates** — full equatorial-to-galactic transform and reference point catalog.
- **Temporal systems** — 28-mansion Arabic lunar stations (Manazil); Sothic cycle drift and Egyptian civil calendar conversion; void-of-course Moon windows.
- **Harmograms** — intensity-spectrum research engine (H1–H5); spectral vectors, zero-Aries parts construction, intensity doctrine, and time-domain trace analysis.
- **Harmonics** — harmonic chart calculation, aspect-harmonic profiles, vibrational fingerprint analysis.
- **Synastry** — inter-chart aspects, house overlays, composite chart (midpoint method), Davison chart (spherical midpoint).
- **Jones chart shapes** — all 7 temperament types.

---

## Quick Start

Moira initializes even when no planetary kernel is present. Kernel-dependent operations (for example `chart()`) raise a clear `MissingEphemerisKernelError` until a kernel is configured. See [Kernel Setup](#kernel-setup) below before executing planetary examples.

```python
from datetime import datetime, timezone
from moira import Moira

m = Moira()

# 1. Planetary positions
chart = m.chart(datetime(2000, 1, 1, 12, 0, tzinfo=timezone.utc))
print(f"Sun:  {chart.planets['Sun'].longitude:.6f} deg")
print(f"Moon: {chart.planets['Moon'].longitude:.6f} deg")

# 2. House cusps (Placidus, London)
from moira import HouseSystem
houses = m.houses(
    datetime(2000, 1, 1, 12, 0, tzinfo=timezone.utc),
    latitude=51.5074,
    longitude=-0.1278,
    system=HouseSystem.PLACIDUS,
)
print(f"ASC: {houses.asc:.4f} deg  |  MC: {houses.mc:.4f} deg")

# 3. Aspect patterns
from moira.patterns import find_all_patterns
patterns = find_all_patterns(chart.longitudes())
for p in patterns:
    print(f"{p.name}: {', '.join(p.bodies)}")

# 4. House placement lookup
from moira.houses import house_of
sun_house = house_of(chart.planets['Sun'].longitude, houses)
print(f"Sun is in house: {sun_house}")
```

---

## REST API Server

The engine ships with an optional FastAPI transport layer (`moira_server`) that exposes the admitted engine surface as typed, versioned REST routes.

```bash
pip install "moira-astro[server]"
uvicorn --factory moira_server:create_app
```

For latency-sensitive deployments, opt in to one bounded per-worker startup
warmup before accepting computational traffic:

```powershell
$env:MOIRA_SERVER_PREWARM = "1"
uvicorn --factory moira_server:create_app
```

With prewarm enabled, `/ready` returns HTTP 503 until the kernel-backed warmup
succeeds; `/health` remains available for liveness diagnostics. Prewarm is
disabled by default because each worker pays its own native memory cost.

- **Broad versioned surface under `/v1`** — hundreds of typed operations across
  charts, positions, houses, per-stage pipeline visibility, physical
  visibility models, progressions, primary directions, returns, transits,
  time lords, the Vedic suite, Hellenistic receipts, draconic charts,
  astrocartography, small bodies, fixed stars, harmonics, harmograms,
  electional scoring, synastry, and relationship products.
- **Typed transport** — admitted route families use typed Pydantic boundaries
  and dedicated serializer/service layers where appropriate; doctrine stays in
  the engine, while the server remains transport and orchestration only.
- **OpenAPI discovery** — tagged schema with installed discovery metadata for machine consumers.

---

## Requirements and Installation

- Python `>=3.10`; consult the PyPI file list for a wheel matching the intended
  interpreter and platform
- A published wheel for the current interpreter/platform, or a C++ compiler,
  `cmake >= 3.24`, and `pybind11 >= 2.12` when building the native extension
  from source
- A JPL DE-series planetary kernel (de430, de440, or de441 — not bundled; see below)

```bash
# Standard install (uses a published wheel when available)
pip install moira-astro

# With the FastAPI REST server (FastAPI, Starlette, Uvicorn, Pydantic)
pip install "moira-astro[server]"

# With Lunar Graze support (spiceypy, laspy, requests)
pip install "moira-astro[lunar-graze]"
```

This README documents the current `main` branch. The PyPI badge identifies the
latest packaged release; features merged after that release require a source
checkout until the next version is published.

---

## Kernel Setup

Moira requires a JPL DE-series SPK planetary kernel for all planetary computation. No kernel is bundled — the files are large and the choice of release belongs to the user.

All kernel reading is performed by Moira's own native C++ SPK/DAF reader. As of 4.0.0 there is no `jplephem` runtime fallback: segment types outside the native reader's support raise an explicit error rather than silently routing through a third-party library.

Ordinary chart and ephemeris calculations read local resources and do not make
outbound requests. Network access belongs to acquisition paths such as the
kernel downloader, the Horizons/SBDB-backed DAF writer, and uncached optional
research resources.

**Recommended, release-documented kernels:**

| Kernel | File | Size | Date range | Notes |
| :--- | :--- | :--- | :--- | :--- |
| DE441 | `de441.bsp` | ~3.1 GB | ~13 200 BCE – ~17 200 CE | Original design target; maximum date coverage |
| DE440 | `de440.bsp` | ~114 MiB | 1550 BCE – 2650 CE | Moira's recommended modern-range kernel for most users |
| DE430 | `de430.bsp` | ~114 MiB | 1550 BCE – 2650 CE | Widely deployed predecessor to DE440 |

Automatic discovery also recognizes DE431 and DE432 for compatibility. That
does not make every readable Type-2/3 SPK an admitted release kernel. Kernels
outside the release-documented set may be manually readable, but must not be
presented as release-validated without a versioned admission record.

### Kernel Manager (GUI)

The easiest way to download and configure a kernel is the built-in Tkinter
interface. Tkinter is included with official Python installers but is an
optional CPython module on some distributions; run
`python -m tkinter` in the intended environment to confirm it is available, or
install the Tcl/Tk package supplied by the Python distributor.

```bash
moira-kernel-manager
```

The window shows all supported kernels with extended descriptions (design rationale, date coverage, size trade-offs), live Installed/Missing status for each, and a real progress bar for downloads. You can also point Moira at a `.bsp` file already on disk without re-downloading.

What the GUI provides:

- **Kernel list** — planetary (de430, de440, de441) and supplemental (asteroids, small bodies) sections with size, date range, and status per row.
- **Detail panel** — selecting a row shows a full description of that kernel's coverage, accuracy, and when to prefer it over the alternatives.
- **Download with progress** — streams the selected kernel in the background; a progress bar tracks bytes received. A Cancel button interrupts the transfer and removes the partial file.
- **Use selected** — activates an installed planetary kernel for the current session via `set_kernel_path()`.
- **Browse…** — select a planetary `.bsp` already on disk and set it as the active kernel immediately.

The GUI and `moira-download-kernels` supplemental entries are the generic JPL
`asteroids.bsp` and `sb441-n373s.bsp` resources. They are separate from both
Moira asteroid catalogs (the wheel roster and the 10,025-body archive) and from
the 497-comet release described below. They remain caller-managed compatibility
inputs for explicit small-body workflows; downloading them does not install or
substitute for either Moira catalog. `moira-download-kernels` still does not
fetch the 10,025-body archive.

### CLI

```bash
# List all kernels and their status
moira-download-kernels --list

# Download all missing kernels (interactive prompt)
moira-download-kernels

# Download without prompting
moira-download-kernels --yes
```

### SPK Kernel Writer (GUI)

Moira supports building custom Type 13 SPK kernels using an integrated compiler GUI (built on Tkinter). This utility fetches physical position vectors directly from the JPL Horizons API and packages them into a native-readable binary kernel (`.bsp`).

```bash
moira-daf-writer
```

What the custom kernel writer provides:
- **Guided Horizons Import**: Search the JPL Small Body Database (SBDB) by designation or name for any numbered asteroid or comet.
- **Custom Parameter Controls**: Configure start/end Julian Days, step size in days, interpolation center, and coordinate frame.
- **Verification Loop**: Automatically runs a post-compilation check to verify segment availability and test coordinate evaluations.

### Engine readiness model

- `Moira()` succeeds even if no kernel is installed. It auto-discovers any compatible kernel in the standard locations.
- `m.is_kernel_available()` reports kernel readiness.
- `m.get_kernel_status()` explains expected paths and remediation.
- `m.available_kernels` lists installed planetary kernels (small-body shard catalogs are discovered separately via their manifests).
- Kernel-dependent calls raise `MissingEphemerisKernelError` with instructions.

**Standard location:** `kernels/<filename>.bsp` relative to the repository root, or `~/.moira/kernels/`. The engine resolves either automatically.

**Custom location:** pass the path at construction, or call `set_kernel_path()` before the first `Moira()` instantiation:

```python
from moira.spk_reader import set_kernel_path
from moira import Moira

set_kernel_path("/path/to/de440.bsp")
m = Moira()

print(m.is_kernel_available())
print(m.get_kernel_status())
print(m.available_kernels)
```

**Direct download links (JPL):**

- DE441: [https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de441.bsp](https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de441.bsp)
- DE440: [https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de440.bsp](https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de440.bsp)
- DE430: [https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de430.bsp](https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de430.bsp)

### Small-Body Catalogs (Asteroids and Comets)

The wheel ships catalog `moira-asteroids-wheel` release `2026.08.14.1`: 25
named bodies (including Chiron) as one Type-13 shard under
`moira/kernels/asteroids_wheel/`. After `pip install` plus a planetary kernel,
that roster is position-capable without a separate small-body download.

The full unified asteroid catalog (10,025 bodies as 401 Type-13 shards in
release `2026.08.12.1`) and the numbered periodic comet catalog (497 comets as
20 shards in release `2026.07.28.1`) are too large to ship inside the wheel and
are distributed separately. `moira-download-kernels` still does not fetch the
10,025-body catalog. Generic JPL files (`asteroids.bsp`, `sb441-n373s.bsp`)
do not substitute for either Moira catalog.

Search by name, designation, catalog number, or NAIF ID and download the exact
published files from the
[Moira Small-Body Ephemerides archive](https://moira-astro.com/ephemerides).
The archive maps each body to its shared multi-body shard and provides direct
BSP and metadata links, release manifests, coverage/provenance, and SHA-256
receipts. A body search therefore returns the shard *containing* that body, not
a one-body BSP.

For automatic catalog admission of a full external release, place the
**complete** release in `asteroids/` or `comets/` under a kernel search root
(`kernels/` at the repository root or `~/.moira/kernels/`), with
`manifest.json`, `SHA256SUMS`, all declared shards, per-shard metadata, and
support files together in that directory. Do not retain an additional
catalog-version directory between `asteroids/` or `comets/` and
`manifest.json`. The engine discovers these manifests automatically; no
configuration call is required. Release-finalized manifests are verified as
complete before any shard is opened, so a lone shard is suitable for
independent inspection but is not a complete automatic catalog installation.
When both the wheel catalog and a higher-precedence full asteroid catalog are
present, first-match discovery leaves the full catalog in charge for bodies it
covers. A bundled canonical name alone does not imply position capability for
bodies outside the wheel roster.

Distributed catalog releases are immutable and versioned. Each extracted release
contains `SHA256SUMS`; its `manifest.json` also records the byte length and
SHA-256 of every Moira-generated Type-13 kernel and its per-shard build
evidence. Verify an extracted release with:

```powershell
.\.venv\Scripts\python.exe -m moira.small_body_catalog_release verify C:\path\to\catalog-release
```

Verify individually downloaded files against the manifest and SHA-256
receipts. If a release maintainer or mirror supplies a ZIP produced by Moira's
release tooling, verify that archive before extraction with:

```powershell
.\.venv\Scripts\python.exe -m moira.small_body_catalog_release verify-archive C:\path\to\catalog-release.zip
```

Release maintainers finalize an already-built catalog without recalculating its
ephemeris using the `prepare` command documented by
`python -m moira.small_body_catalog_release --help`. A changed file, membership
set, sampling policy, or coverage rule always receives a new catalog version;
published bytes are never replaced beneath an existing version.

Note for pre-4.0.0 installs: standalone supplemental kernels such as
`comets.bsp`, `centaurs.bsp`, and `minor_bodies.bsp` no longer auto-load into
the main facade. Automatic catalog discovery is manifest-based; the named
Centaurs formerly associated with `centaurs.bsp` are covered by the wheel
catalog. Compatible standalone SPKs remain available only through explicit
caller-managed loading where the relevant API admits it.

---

## Data Inventory

| Layer | Source | Bundled | Note |
| :--- | :--- | :--- | :--- |
| IAU 2000A/2006 nutation and precession tables | IAU | Yes | 2,414 terms; native C++ (`_moira_native`) |
| DE-series planetary kernel | JPL | No | de430 (~114 MiB), de440 (~114 MiB), or de441 (~3.1 GB); download separately |
| Named star registry | Sovereign (`star_registry.csv` + JSON provenance) | Yes | 1,809 stars; license-independent |
| Canonical small-body identity registries | Moira release catalogs with JPL identity lineage | Yes | 10,025 asteroid and 497 comet identities; names and disambiguation only, with no positional vectors implied |
| Wheel asteroid ephemeris | JPL Horizons (Moira Type-13 packaging) | Yes | Catalog `moira-asteroids-wheel` `2026.08.14.1`; 25 named bodies including Chiron; one Type-13 shard |
| Full position-capable asteroid ephemeris | JPL Horizons | No | 10,025 selected asteroids; 401 Type-13 shards in release `2026.08.12.1`; [public archive](https://moira-astro.com/ephemerides), manifest-discovered; not fetched by `moira-download-kernels` |
| Asteroid-family membership catalog | Proper25 + retained NASA PDS exclusions | Yes | 342 families; 200,726 unique numbered asteroids; 221,095 many-to-many membership rows; no positional ephemeris implied |
| Numbered periodic comet catalog | JPL Horizons | No | 497 comets (1P–516P); 20 Type-13 shards in release `2026.07.28.1`; [public archive](https://moira-astro.com/ephemerides), manifest-discovered |

---

## Native C++ Performance

Moira's required numerical extension (`_moira_native`) is implemented in
C++17 with pybind11. Published wheels install the compiled extension directly;
source distributions build it during installation. Admitted native paths
include IAU 2000A nutation, SPK/DAF access and segment evaluation, apparent
planetary evaluation through `NativePlanetaryEvaluator`, selected coordinate
transforms, light-time primitives, harmogram computation, precession, and
selected event-search kernels.

Python remains responsible for public policy, result semantics, orchestration,
and event-search branches that have not been explicitly admitted to the native
substrate. This selective boundary matters most in phenomenon searches where
Python-owned doctrine can reuse native numerical primitives thousands of
times without pretending the entire technique is native-owned.

---

## Validation Evidence

Moira is validated as a three-layer corpus. Each layer has its own correct evidence standard.

**Astronomy layer** — authoritative physical oracles first, enforced regression thereafter.
References: IAU ERFA/SOFA, JPL Horizons, NASA catalogs, IERS.

**Astrology layer** — named primary texts, source-owned fixtures, and
doctrine-grounded invariants; bounded external chart-software comparison where
its settings and mathematical product are actually commensurate. Swiss
Ephemeris and Astro.com are secondary comparators, not Moira's governing
runtime or universal authority.

**Experimental layer** — subsystem-specific surfaces for sovereign or modern domains.
Domains: sovereign fixed stars, variable stars, multiple star systems, galactic transforms, eclipse Saros classification.

Every validated claim must pass three gates:

1. **Gate of Source** — inputs and reference data are tied to an independent authority.
2. **Gate of Flow** — the computational path is explicit and inspectable.
3. **Gate of Validation** — outputs meet a product-appropriate external
   authority, source-owned golden, independent invariant, or explicitly
   bounded secondary comparison.

When residuals remain, Moira isolates the discrepancy by identity, time scale,
frame, correction regime, and product semantics before classifying it as a
defect, a model-basis difference, or unresolved evidence. Agreement between
two internally consistent systems is not assumed when they answer different
mathematical questions.

The reports below are dated evidence ledgers, not self-updating assertions.
Release-specific changes and validation boundaries are recorded in the
[changelog](CHANGELOG.md) and the
[6.1.0 release notes](wiki/03_release/RELEASE_NOTES_6.1.0.md).

| Report | Verification Source |
| :--- | :--- |
| [`VALIDATION_ASTRONOMY.md`](wiki/03_validation/VALIDATION_ASTRONOMY.md) | Product-specific IAU ERFA/SOFA, JPL Horizons, NASA, IERS, and invariant evidence with named tolerances and qualifications. |
| [`PLANETARY_REDUCTION_PIPELINE.md`](wiki/02_standards/PLANETARY_REDUCTION_PIPELINE.md) | Major-body route identity, reader-bound time and context ownership, reduction stages, compatibility boundary, and target/time/frame-matched Horizons contracts. |
| [`VALIDATION_ASTROLOGY.md`](wiki/03_validation/VALIDATION_ASTROLOGY.md) | Primary texts, source-owned goldens, doctrine tables, invariants, and bounded Swiss/Astro.com corroboration where applicable. |
| [`VALIDATION_EXPERIMENTAL.md`](wiki/03_validation/VALIDATION_EXPERIMENTAL.md) | Dated subsystem evidence and explicit partial-status boundaries for sovereign and modern products. |

---

## The Reduction Pipeline

```mermaid
graph TD
    A[JPL Planetary Kernel\nChebyshev state vectors] --> B[SSB Barycentric Position\nkm · ICRF]
    C[Sovereign Star Registry\n1809 named stars] --> D[Stellar Astrometric Position\nproper motion · parallax]
    B --> E[1 · Light-Time Iteration\nbody at t − τ  where τ = d/c]
    E --> F[2 · Gravitational Deflection\nSun · Jupiter · Saturn]
    F --> G[3 · Annual Aberration\nrelativistic · IAU SOFA]
    G --> H[4 · IAU 2006 Frame Bias\nICRF → Mean Equator J2000]
    D --> H
    H --> I[5 · IAU 2006 Precession\nP03 polynomial series]
    I --> J[6 · IAU 2000A Nutation\n1358 luni-solar + 1056 planetary terms]
    J --> K[True Equinox and Equator of Date]
    K --> L[7 · Topocentric Parallax\nWGS-84 · optional]
    L --> R[8 · Diurnal Aberration\nobserver rotation · optional]
    R --> M[Atmospheric Refraction\nsky altitude only · optional]
    K --> N[Ecliptic Projection\nTrue obliquity of date]
    N --> O[Zodiacal Longitude · Latitude · Distance]
    K --> P[Sidereal Frame · Ayanamsa\noptional]
    K --> Q[House Cusps · 22 Systems\nrequires lat/lon]
```

### Worked Example: Mars at 2000-01-01 12:00 UT1

This snapshot is reproduced by `planet_reduction_breakdown_at("Mars",
2451545.0, reader)` with the admitted DE441 kernel. The input is
`JD_UT1 2451545.0`; it is about 63.829 seconds after the exact J2000.0 TT
epoch and is therefore not labelled as exact J2000.0.

**Time:** JD_UT1 2451545.000000 → JD_TT 2451545.000739
&nbsp;(ΔT = +63.829 s)

| Stage | Operation | Engine receipt | Longitude contribution |
| :---: | :--- | :--- | ---: |
| 0 | **Geometric geocentric** | SSB-to-Mars minus SSB-to-Earth; λ = 327.975456°; distance = 276,697,408.4 km | reference |
| 1 | **Light-time iteration** | τ = 0.010683 days = 15.383 min | −15.762371″ |
| 2 | **Gravitational deflection** | Sun, Jupiter, and Saturn | −0.003057″ |
| 3 | **Annual aberration** | Earth barycentric velocity; relativistic | −14.069158″ |
| 4 | **IAU 2006 frame bias** | ICRF to dynamical mean J2000 | +0.000300″ |
| 5 | **IAU 2006 precession** | P03; mean equator/ecliptic of date | +0.006571″ |
| 6 | **IAU 2000A nutation** | Δψ = −13.932004″; Δε = −5.769413″ | −13.932004″ |
| 7–8 | **Topocentric parallax and diurnal aberration** | disabled for this geocentric example | 0 |

**Final position: Aquarius 27° 57′ 48″** &nbsp;·&nbsp;
λ = 327.963300° &nbsp;·&nbsp; β = −1.067779° &nbsp;·&nbsp;
distance = 1.849688 AU &nbsp;·&nbsp; speed = +0.775674°/day

**Total visible reduction from the geometric J2000-ecliptic reference to the
final true-of-date ecliptic longitude: −43.759719 arcseconds.**

The stage contributions above come from the typed reduction receipt. They
should not be reconstructed by subtracting unrelated coordinate frames or by
treating `apparent=False` as “no frame transformation.”

### Pipeline Controls

Selected correction policies can be toggled via `planet_at()`. The table below
shows the measurable effect of disabling each exposed policy in this
`JD_UT1 = 2451545.0` Mars snapshot.

| Parameter | Default | Effect on snapshot longitude | Function |
| :--- | :--- | :--- | :--- |
| `apparent=True` | `True` | Full pipeline active | `planet_at()` |
| `apparent=False` | — | Omits light-time, deflection, and aberration while retaining the declared ecliptic-of-date frame and nutation policy. Δ = **+29.835 arcsec** | `planet_at()` |
| `aberration=False` | — | Aberration stage skipped. Δ = **+14.069 arcsec** | `planet_at()` |
| `grav_deflection=False` | — | Deflection stage skipped. Δ = **+0.003 arcsec** | `planet_at()` |
| `nutation=False` | — | Nutation skipped; mean equinox used. Δ = **+13.932 arcsec** | `planet_at()` |
| `observer_lat/lon` | `None` | When supplied together, adds WGS-84 topocentric parallax and observer-rotation diurnal aberration; the effect is body-, location-, and epoch-dependent. | `planet_at()` |
| `refraction=True` | `True` | Applies the declared pressure, temperature, and humidity model to geometric sky altitude. | `sky_position_at()` |
| `delta_t_policy` | `None` | Controls UT → TT conversion branch (IERS tables, polynomial, hybrid physical) | both |

---

## Project Documentation

The canonical documentation tree lives in `wiki/`. The flat `moira.wiki/` Git
wiki mirror is generated from it by
`.\.venv\Scripts\python.exe scripts\sync_git_wiki.py` and should not be edited
by hand. Website-publishable documents are governed by
`website_docs/publication_sources.json` and built with
`.\.venv\Scripts\python.exe scripts\build_website_docs_bundle.py`. After
changing server routes, run
`.\.venv\Scripts\python.exe scripts\sync_rest_api_reference.py` in an
environment with the `server` extra installed; CI checks its generated OpenAPI
inventory, the Git wiki mirror, and the website publication manifest for
drift.

| Document | Contents |
| :--- | :--- |
| [`CHANGELOG.md`](CHANGELOG.md) | Versioned release history and current unreleased boundary. |
| [`RELEASE_NOTES_6.1.0.md`](wiki/03_release/RELEASE_NOTES_6.1.0.md) | Published 6.1.0 release notes, validation summary, and explicit exclusions. |
| [`01_LIGHT_BOX_DOCTRINE.md`](wiki/01_doctrines/01_LIGHT_BOX_DOCTRINE.md) | Transparency and derivation as design constraints. |
| [`BEYOND_SWISS_EPHEMERIS.md`](wiki/01_doctrines/BEYOND_SWISS_EPHEMERIS.md) | Capabilities enabled by sovereign catalogs, explicit policy, and modern Python. |
| [`MIGRATING_FROM_SWISS_EPHEMERIS.md`](wiki/02_services/MIGRATING_FROM_SWISS_EPHEMERIS.md) | Contract-first porting guide for Swiss flags, bodies, time scales, units, houses, REST, and dual-run verification. |
| [`HOUSE_SYSTEM_DIVERGENCE.md`](wiki/01_doctrines/houses/HOUSE_SYSTEM_DIVERGENCE.md) | House-system derivation and discretionary divergence from conventional Swiss-facing behavior. |
| [`PHYSICAL_HELIACAL_VISIBILITY_CAPABILITY_MATRIX.generated.md`](wiki/03_validation/PHYSICAL_HELIACAL_VISIBILITY_CAPABILITY_MATRIX.generated.md) | Current physical-visibility admission, evidence classes, tolerances, and closed exclusions. |
| [`PHYSICAL_HELIACAL_VISIBILITY_API_INVENTORY.generated.md`](wiki/03_validation/PHYSICAL_HELIACAL_VISIBILITY_API_INVENTORY.generated.md) | Generated Python/facade/REST/OpenAPI inventory for the opt-in physical contract. |
| [`CONSTITUTIONAL_PROCESS.md`](wiki/00_foundations/CONSTITUTIONAL_PROCESS.md) | The Subsystem Constitutional Process — the development and governance protocol. |
| [`MOIRA_ROADMAP.md`](wiki/06_roadmap/MOIRA_ROADMAP.md) | Living implementation roadmap and improvement register; validation claims remain owned by the validation ledgers and release notes. |

---

## License

MIT (c) 2026 TheDaniel166. See [PROVENANCE.md](PROVENANCE.md) for license and Swiss-lineage provenance clarity.
