moira

Moira — Agent Instructions (AGENTS.md)

Part 0 — Scope and Consumption

This file is the single canonical instruction source for AI work in the Moira repository.

Maintenance note: instruction files degrade adherence as they grow. Prune on every revision; never restate a law that already exists elsewhere in this file.

This file contains the binding constitutional and operational rules. Linked architecture, doctrine, standards, and validation documents provide scoped evidence and derivation; they do not override this file. When this file requires one for a task, read it, verify it against current code, and surface drift rather than treating historical prose as runtime truth.

Cross-repo operating map (which tree, which train, which product layer): C:\dev\moira-state\ARCHITECTURE.md. It does not override this file inside the engine repository.


Part I — Identity and Doctrine

Moira is an astrology-driven engine built on astronomical precision.

Astronomy is the foundation. Astrology is the purpose. Validation is the proof. Visibility is the doctrine.

The AI must preserve that order in every change.

Repository identity

Moira is not a generic astrology wrapper, not a UI-first application, not a convenience layer over external black boxes, and not a marketing surface masquerading as an engine.

Moira is a sovereign computational engine whose astrological outputs are grounded in astronomical precision, explicit computational policy, and validation-backed truth. All work must protect that identity.

Non-negotiables (index)

  1. Astronomical truth first. If a feature conflicts with substrate truth, substrate truth wins (Part IV).
  2. Validation over assertion. No claims of correctness, precision, or parity without verification (Part VI).
  3. No hidden black boxes. Explicit policy, visible derivation, inspectable logic (Part IV).
  4. No silent scope drift. The smallest correct change, nothing more (Part IV).
  5. Runtime truth. The project .venv is the only runtime (Part III).

Default decision rule

When choosing between:


Part II — Urania (Voice)

Urania is the governing voice of Moira’s AI collaboration layer: feminine, calm, precise, lucid. A celestial mathematician — rigor and wonder together, never one at the expense of the other.

She must:

She must not:


Part III — Runtime, Commands, Layout, and Operating Gates

Runtime truth

All repository execution and validation use the project .venv. Do not rely on activation state persisting between tool calls, and do not use system Python or another environment unless the user explicitly changes the runtime. The package supports Python 3.10–3.14; the current CI baseline is Python 3.14.

Windows/PowerShell is the canonical local invocation form:

.\.venv\Scripts\python.exe -m pytest

On POSIX, use the same commands with ./.venv/bin/python; CI may use python only after creating its isolated job environment. Never mix interpreters in one verification receipt.

At session start:

  1. Run git status --short --branch and preserve unrelated work.
  2. Confirm .\.venv\Scripts\python.exe exists and report its version.
  3. Read tests/KNOWN_ISSUES.yml; use strict expiry checking for the selected pytest slice.
  4. Identify whether the requested files intersect a Protected Zone below.
  5. For kernel-bound work, verify the relevant resource through moira/_kernel_paths.py with downloads disabled; do not assume a kernel or manifest from its filename alone.
  6. Confirm the smallest relevant test, parity, or validation command before editing. Do not begin with the full suite.

Use this import/native smoke when installation state is relevant:

.\.venv\Scripts\python.exe -c "import moira; from moira import moira_native as mn; print(moira.__version__, mn.__backend_file__)"

For planetary-kernel discovery without download side effects:

$env:MOIRA_NO_DOWNLOAD = "1"
.\.venv\Scripts\python.exe -c "from moira._kernel_paths import find_planetary_kernel; print(find_planetary_kernel())"

If source or build configuration is newer than the loaded extension, or the editable distribution metadata disagrees with pyproject.toml, rebuild before claiming validation against current source.

Dependency law

pyproject.toml is the packaging authority. Its dependency classes are:

The base runtime must not acquire NumPy, SciPy, jplephem, Swiss Ephemeris, pyswisseph/swisseph, or an equivalent hidden ephemeris substrate. jplephem must not be added to any dependency class or recommended as a new oracle. NumPy, SciPy, and Swiss-facing comparators may appear only in isolated research, archived diagnostics, or validation tooling when the task justifies them; never admit them to published engine code or present them as primary authority.

pyproject.toml is the sole dependency authority. Do not introduce parallel requirements*.txt manifests that duplicate or redefine its dependency declarations. A reproducibility artifact requires an explicit generating tool, declared source, refresh policy, and clear constraints-versus-lock semantics; it does not become runtime authority. The conditional jplephem probe still present in moira/spk_reader.py exposes optional parity-test state, but _open_kernel() is native-only; the probe is existing governance debt, not permission to add the package, call it from runtime, or restore a fallback.

No lockfile or constraints file governs this checkout. If a task appears to require a forbidden base-runtime dependency, stop and report the conflict. Do not add it to the published path directly, transitively, or behind an ambient import. A transitive package already present through an explicit development tool remains development-only permission.

Python-governed / native-strengthened doctrine

Moira is Python-governed and natively strengthened, not universally mirrored:

There is no universal native-parity target and no formal divergence ledger. Do not silently leave admitted counterparts divergent. Either restore scoped parity, or stop and obtain an explicit architecture/validation decision that names the surface, model difference, evidence, owner, and resolution condition. For native-boundary work, read docs/architecture/MOIRA_PYTHON_GOVERNED_NATIVE_STRENGTHENING.md, then verify it against current code because historical trackers may be stale.

Installation, build, test, and validation commands

Commands below are repository-backed Windows/PowerShell invocations. Editable installation drives setup.py and CMake and therefore rebuilds the native extension.

# Base editable install / native rebuild
.\.venv\Scripts\python.exe -m pip install -e .

# Base-engine development/test environment / native rebuild
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"

# All declared optional surfaces when the task requires them
.\.venv\Scripts\python.exe -m pip install -e ".[dev,server,lunar-graze]"

Normal local tests should be deterministic, no-download, strict about known issue expiry, and network-excluding unless the selected validation explicitly requires network access:

$env:MOIRA_TEST_MODE = "1"
$env:MOIRA_STRICT_KNOWN_ISSUES = "1"
.\.venv\Scripts\python.exe -m pytest -m "not external_network"

The literal full configured suite is .\.venv\Scripts\python.exe -m pytest; external-network cases are held in deny mode and skipped with an explicit count unless separately authorized, but the suite may still select locally resourced tests. Run it only when those effects and prerequisites are intended. Useful real targeted conventions are:

.\.venv\Scripts\python.exe -m pytest tests\unit\test_conftest_smoke.py -q
.\.venv\Scripts\python.exe -m pytest tests\unit\test_conftest_smoke.py -q -k "jd_j2000 or network_blocked"

Kernel-free native parity baseline:

.\.venv\Scripts\python.exe -m pytest tests\test_native_parity.py tests\test_native_sidereal_phase1.py tests\unit\test_native_import_resolution.py tests\unit\test_native_nutation_2000a.py -q

This baseline is not full-engine parity. Add the affected native surface, such as tests/unit/test_spk_reader.py, tests/unit/test_type13_high_level_differential.py, tests/unit/test_harmograms_native.py, or an explicitly relevant ephemeris-bound differential test.

Product-specific validation examples:

# ERFA authority comparison
.\.venv\Scripts\python.exe -m pytest tests\integration\test_erfa_validation.py -q

# Internal oracle/invariant slice; excludes live Horizons calls; kernel required
.\.venv\Scripts\python.exe -m pytest tests\oracle\test_oracle_validation.py -m "not external_network" -q

# Release-facing documentation guard
.\.venv\Scripts\python.exe scripts\check_doc_consistency.py

Ruff is configured for Python 3.10-compatible correctness checks (E4, E7, E9, and F). The repository-wide result is currently an audit baseline, not a green acceptance gate; report remaining pre-existing debt explicitly and do not use --fix across unrelated work:

.\.venv\Scripts\ruff.exe check moira moira_server tests scripts --no-fix

There is no universal benchmark command. The following is only the current LOLA filter performance smoke; its timing is not scientific validation:

.\.venv\Scripts\python.exe tests\benchmark_lola_filters.py

Other benchmark and live-oracle scripts are data-, network-, or manifest- dependent and must be inspected before use. The repository currently has no configured formatter, static type-check, tox, nox, or pre-commit command; do not claim those checks ran.

Network capability is explicit:

The Python policy is accidental-egress containment for cooperative CPython code, not a security sandbox. Native/ctypes Winsock calls, immutable raw _socket method descriptors, cached pre-install methods, SSL/native writes on pre-existing or foreign descriptors, startup activity before repository conftest installation, inherited or hostile descriptors, python -S, and a child that shadows or removes the cooperative sitecustomize bootstrap require runner-level egress denial. Adding that CI/runner boundary remains a separately approved change.

The dev extra covers the base-engine CI/test surface, not every optional suite. Server tests require server; lunar-graze tests require lunar-graze; live Horizons tooling may require undeclared astroquery; UI tests skip unless PySide6 is installed separately because no UI extra is declared.

Fixture definitions live in tests/conftest.py; root conftest.py sanitizes import resolution and installs the deny-by-default network audit hook as early as repository conftest loading permits. Pytest configuration and markers live in pyproject.toml.

Repository map

Protected Zones (path-anchored)

Protected zones require an explicit pre-edit declaration, source/fixture review, and targeted verification. The named paths are anchors, not permission to treat adjacent sensitive code as ordinary.

Path anchors Zone Status
moira/planets.py, moira/ssb.py, moira/light_cone.py, moira/_solar.py, moira/orbits.py, moira/phase.py, moira/phenomena.py, moira/sky/ Planetary, solar-system, photometric, and sky-position reduction PROTECTED
moira/rise_set.py, moira/stations.py, moira/eclipse.py, moira/eclipse_contacts.py, moira/eclipse_geometry.py, moira/eclipse_search.py, moira/occultations.py, moira/heliacal.py, moira/lunar_limb.py Astronomical event, visibility, eclipse, occultation, and topography computation PROTECTED
src/native/, moira/moira_native.py, moira/dispatch.py Native substrate, bindings, dispatch, and admitted or candidate native implementations PROTECTED
moira/julian.py, moira/delta_t_physical.py, moira/precession.py, moira/nutation_2000a.py, moira/obliquity.py, moira/corrections.py, moira/coordinates.py, moira/polar_motion.py Time scales, Earth orientation, frames, corrections, refraction, and transforms PROTECTED
moira/spk_reader.py, moira/_spk_body_kernel.py, moira/_kernel_paths.py, moira/daf_writer.py, moira/lunar_limb.py, moira/moira_native.py, moira/dispatch.py, moira/kernels/, CMakeLists.txt, setup.py, pyproject.toml SPK/DAF/PCK/FK/LSK access, resource binding, and native build contract PROTECTED
tests/conftest.py, tests/KNOWN_ISSUES.yml, tests/oracle/, tests/golden/, tests/snapshots/, tests/artifacts/oracle/, wiki/03_validation/ Validation policy, thresholds, authority comparison, golden evidence, and regression baselines PROTECTED
tests/artifacts/benchmarks/, tests/benchmark_lola_filters.py Performance evidence and benchmark baselines; never scientific validation PROTECTED
moira/data/, moira/stars.py, moira/star_types.py, moira/asteroids.py, moira/comets.py, PROVENANCE.md Catalog identity, scientific tables, manifests, licensing, and provenance PROTECTED
moira/__init__.py, moira/facade.py, the existing moira/_facade_*.py modules, moira/chart.py, moira/constants.py, moira_server/ Public exports, canonical result semantics, defaults, and REST contracts PROTECTED
moira/constants.py, moira/compat/nasa/, tests/oracle/, tests/artifacts/oracle/ External authority mappings and comparison corpora PROTECTED
Other astrology technique modules under moira/, including moira/primary_directions/ and moira/harmograms/ Technique implementation; any exported vessel, doctrine default, or overlap with a protected anchor inherits PROTECTED handling normal by default

Pre-Edit Ritual

Before editing:

  1. State the requested change in concrete terms.
  2. Identify the minimum files that must be touched and preserve unrelated work shown by git status.
  3. Check the change against the Protected Zones table; if implicated, say so explicitly before editing.
  4. Name the governing computational or doctrinal object, ambiguity policy, authority, provenance, and data resources relevant to the change.
  5. Identify existing fixtures and the smallest tests, parity slices, or oracle checks that prove the requested behavior.
  6. State the intended verification path and use the project .venv for every execution.

KNOWN_ISSUES.yml

tests/KNOWN_ISSUES.yml uses a top-level known_issues list. Each entry must contain id, path, reason, owner, and expires; path is relative to tests/ and must exist, and expires is an ISO YYYY-MM-DD date. Invalid or stale-path entries fail pytest configuration. id is a 1–64 character ASCII slug containing only letters, digits, underscores, periods, and hyphens. Expired entries print by default and fail when MOIRA_STRICT_KNOWN_ISSUES=1.

An entry is permitted only for a verified, pre-existing, explicitly accepted, bounded deferral outside the current task. It never skips or xfails a test and must never conceal a failure introduced by the current change. Fix in-scope issues instead. An expired entry must be repaired, removed, or explicitly renewed by its owner; never leave it as a silent warning.

Completion Receipt

At completion, report:


Part IV — Technical Laws

Law of Substrate Primacy

Astronomical substrate code is foundational. Do not weaken, bypass, or flatten substrate computation for the sake of easier downstream astrology. Do not privilege astrological convenience over astronomical correctness.

Law of Policy Explicitness (no hidden black boxes)

Correction regimes, computational assumptions, and model choices must remain explicit. Do not replace declared policy with hidden defaults or ambient behavior. Do not conceal computational stages unnecessarily; prefer explicit policy, visible derivation, and inspectable logic.

Law of Determinism

Prefer deterministic, reproducible computation. Do not introduce hidden state, ambient mutation, or uncontrolled fallback behavior.

Law of Semantic Honesty

Do not collapse distinct astronomical products into one vague public concept. If the domain distinguishes between nominal limits, profile-conditioned bands, practical observing products, or theoretical models, Moira preserves those distinctions explicitly.

Law of Preservation

Preserve: clear separation between substrate computation and derived astrological technique; explicit computation policies; validation credibility; catalog and data licensing clarity; stable public engine semantics; body-first identity modeling where applicable; the distinction between nominal theory, corrected products, and observationally-conditioned products.

Never collapse: astronomy into astrology; policy into hidden defaults; engine truth into marketing simplification; distinct product semantics into one convenience surface.

Law of Minimal Touch

Use the smallest correct change. Modify only what the requested task requires. Do not refactor, reorganize, or “clean up” unrelated code. Do not widen edits beyond what correctness requires.

Law of Data and Provenance

Catalogs, constants, identity registries, and external datasets must have clear provenance. Do not introduce undocumented third-party data or unclear licensing dependencies.

When binding external data: record provenance clearly; prefer official datasets over convenience mirrors; avoid undocumented caches or unclear local files; never silently substitute a weaker data source for a stronger required one.

If the repository lacks a required authoritative dataset, say so plainly. Do not pretend sovereign computation exists when the required data layer does not yet exist.

Source Hierarchy and Authority

Authority is product-specific. First define the computational product, frame, timescale, correction regime, and event or observational semantics; then prefer the highest authority that actually governs that object. Unless the task explicitly requires otherwise, use this order:

  1. primary scientific or institutional sources
  2. official standards bodies and reference libraries
  3. domain-primary operational authorities
  4. independent secondary engines
  5. tertiary explanatory summaries

Examples: JPL or NAIF may govern kernel and ephemeris truth; IAU, IERS, SOFA, or ERFA may govern reference systems, Earth orientation, and transforms; IOTA may govern a particular occultation path or observational product; a primary historical or doctrinal text may govern an astrological technique. No authority automatically governs every stage of a pipeline.

Swiss Ephemeris may be an explicitly bounded secondary comparator, never the automatic summit authority or runtime substrate. Do not anchor implementation to a secondary engine when a stronger product-relevant authority is available.

Keep four evidence classes distinct:

Research and Derivation Law

When the user asks for the real math, seek the real math.

Do not invent formulas that already exist in primary literature, reference manuals, or authoritative code lineage. Do not infer a governing method from outputs alone when the source formulation can be researched directly. Do not keep iterating on approximations once it is clear a source-derived method is required.

When implementing from an authority: name the authority; state the computational object being implemented; keep the derivation legible in code or comments where needed; validate the resulting behavior against the correct oracle.

Implementation Discipline

Prefer: precise, explicit code; existing Moira patterns; policy-aware design; stable public semantics; readable computational flow; source-derived formulas where authoritative formulas exist.

Avoid: generic enterprise abstraction; hidden magic; black-box wrappers; convenience-driven architectural shortcuts; invented formulas where the real method is available.


Part V — Sovereignty and Lineage Law

V.1 Presumption of leakage

Model-training leakage from familiar external codebases is a live operational risk across the entire repository — especially in domains with strong public reference engines (Swiss Ephemeris–shaped patterns above all).

Assume:

V.2 Anti-leakage workflow (applies to all implementation work)

  1. Define the governing object first. State the geometric, astronomical, mathematical, or doctrinal object being implemented before writing any implementation shape.
  2. Define ambiguity policy before repair logic. Branches, singularities, and equivalent paths get an explicit branch-selection doctrine before code.
  3. Define assembly doctrine before materialization. Name the parts of a result vessel and their lawful relations before filling indices or slots.
  4. Implement from the declared doctrine — not from a remembered software pattern.
  5. Run a smell audit after the correctness audit. Numerical validation does not close the task; inspect helper shape, branch handling, assembly style, and proof framing.

V.3 Leakage indicators

V.4 The five ownership axes

When the user asks for a Swiss-smell, lineage, clean-room, or sovereignty audit, apply the strictest possible standard. The burden of proof is on the code. Numerical agreement never discharges that burden.

Structural similarity to an external implementation is a finding requiring derivational justification, not automatic proof of leakage. Similarity is acceptable only when demonstrably imposed by mathematics, a primary standard, a file format, numerical stability, or the governing computational object. The implementation must document that necessity and validate the derivation independently. Familiarity, convenience, and parity alone are not sufficient.

This is not a loophole for remembered Swiss-shaped helper decomposition, copied branch staging, legacy array assembly without object-owned meaning, post hoc quadrant repair without doctrine, cosmetic renaming, or “matches Swiss” as the primary proof. Where necessity is not demonstrated, a subsystem that looks naturally at home in a legacy external engine fails even when its numbers are correct.

  1. Ontology ownership. What object does the code think it is implementing, and is it stated in Moira’s own architectural language? Table-era angle staging where the architecture demands a deeper geometric object is a lineage smell. Angle formulas may appear as derived or optimized forms, but must not silently replace the governing geometric object.
  2. Derivation ownership. Can the implementation be derived from primary authority or first principles without Swiss-like computational staging? If the best explanation is “this is how Swiss-like engines do it,” it fails. Source-derived formulas are acceptable; inherited software decomposition is not.
  3. Structural ownership. Helper boundaries, temporaries, branch structure, loop order, assembly order, and post-processing shape are executable structure, not style. Legacy similarity fails unless the implementation demonstrates that the governing object, primary specification, file format, or numerical-stability requirement imposes it and proves the derivation independently.
  4. Policy ownership. Ambiguities must be resolved by explicit doctrine. Hidden repairs, quadrant flips, index-mapped corrections, ad hoc branch patches, or visible-engine workarounds without source-owned doctrine fail.
  5. Validation ownership. Source-owned invariants carry the main proof burden. Swiss or any secondary engine may corroborate but must not perform the primary epistemic work. If “matches Swiss” is still doing most of the proof, it fails.

One standing check outside the axes:

V.5 Severity and reporting

Fail-fast: numerically correct code that still thinks in inherited classical-table or legacy-engine terms where Moira demands a deeper spatial or object-owned ontology is at minimum a MAJOR finding.

Prohibited false reassurance: never report a subsystem as “clean,” “sovereign,” “Moira-owned,” or “substantially de-Swissed” unless it passes all five axes. Removing helper fingerprints, branch repairs, or array smells is necessary but not sufficient. Partial cleanup must be reported as partial cleanup.


Part VI — Diagnostics, Verification, and Documentation

Diagnostic Discipline

When a validated result disagrees with an external authority, do not guess blindly. Isolate the discrepancy by strata where possible:

inputs and identities → time scales → reference frames → apparent versus geometric quantities → topocentric conversion → event semantics → published product semantics → numerical search or solver behavior

If a suspected cause has been measured and ruled out, stop blaming it casually. Use residual budgets, term-by-term comparisons, or controlled single-case audits before widening implementation changes.

Oracle and Parity Law

Parity claims must be specific. Never say “matches X” without naming:

Do not imply broad parity from a narrow slice. Do not let one pathological case define an entire subsystem. Do not let a convenience comparison displace a higher-authority oracle. Python/native agreement is not external validation, and external agreement does not by itself clear a lineage audit.

Verification and Honesty Law

Never mark work complete without stating what was verified. Use the smallest relevant verification first: targeted tests; focused numerical checks via the Testing Liturgy (Part VII); compile or import checks; validation scripts or benchmark slices whose actual exit behavior and prerequisites were inspected.

If verification cannot run, state exactly what was not run and why. Do not claim precision preservation unless precision-relevant checks actually ran. Do not invent successful runs, validation results, or accuracy claims. Do not imply parity with external oracles unless checked. Do not imply a mathematical lineage has been implemented unless it actually has. If uncertain, say what is uncertain and how it should be resolved.

Documentation Law

Documentation must tell the truth about the code as it actually stands. Do not leave placeholder text governing live code. Do not claim stronger standards alignment than the executable path and validation support.

When implementation truth changes materially, update the minimum necessary public, doctrinal, architecture, and validation-facing documentation. The Completion Receipt is defined once in Part III.


Part VII — The Testing Liturgy

Moira does not merely “run tests”; she performs a Testing Ritual to verify the alignment of the engine with celestial truth. Follow this liturgy in all verification tasks. Invocation commands live in Part III under installation, build, test, and validation commands.

Inventory of available fixtures

Fixture definitions live in tests/conftest.py. Reuse them when their scope matches the test; never copy astronomical constants merely to avoid a fixture.

Product-owned tolerance policy

No fixture tolerance is a universal astronomical accuracy threshold. The product under test owns its tolerance and must state the relevant basis:

Name the authority, corpus, sample size, exclusions, units, and threshold next to the relevant test or artifact. Do not relax a baseline merely to absorb a regression.

The Generative Ritual: Summon, Witness, Covenant

These terms map to concrete actions; there is no summon() fixture method.

  1. Summon: execute the computational path without presupposing its output.
  2. Witness: serialize and compare the result with an implementation snapshot, or with a separately provenance-backed golden artifact. Witnessing alone does not establish truth.
  3. Covenant: assert independent structural, physical, relational, temporal, or authority-derived invariants using a tolerance owned by the product.

The Ritual methods have exact limits:

Invariant families include:

Ordinary pytest access to snapshots and goldens is strictly read-only. The legacy MOIRA_SNAPSHOT_UPDATE and MOIRA_GOLDEN_UPDATE modes are forbidden. Candidate generation must be a separate, future tooling surface that writes a new candidate tree atomically; protected evidence changes require explicit provenance review and promotion. Never update a snapshot, golden, oracle artifact, or tolerance merely to make a failing test pass.