Build Notes

Build Notes

Evaluating VSOP87 takes a few hundred lines, and it matched professional ephemerides on the first pass. The bugs worth writing up were all elsewhere, in the handling of timescales, reference frames, and geometry. None of them showed up in a spot check of a single chart, and all of them showed up once the golden suite compared thousands of values against a reference.

ΔT: textbook extrapolation vs Earth since 2016

Ephemerides are computed in TT, while civil time follows the rotation of the Earth, and ΔT is the quantity that bridges the two. The Espenak–Meeus (2006) polynomials, copied into decades of software, assume Earth's spin keeps slowing: they predict ΔT ≈ 158 s for 2080. Earth's rotation began accelerating around 2016; observed ΔT has sat near 69 s since 2020 and is drifting down. The textbook curve is already ~6 s high today and runs ~90 s high by 2080. The Moon moves 0.55″ per second of ΔT error, so a faithful implementation of the old formula misses the Moon by tens of arcseconds within a lifetime. Caelus interpolates IERS observations through 2025, continues the observed near-flat trend, and rejoins the slow tidal rise decades out: an 80-year ΔT forecast carries roughly ±37 s of uncertainty (Huber 2006), so a steeper slope would be false precision.

Node longitude: 11× frame sensitivity

The lunar nodes mark where the Moon's plane crosses the ecliptic, and the ecliptic of date drifts by about 47″ per century. Because the Moon is inclined by only 5.1°, an error in the reference plane is amplified in node longitude by a factor of 1/sin(5.1°), or roughly 11. Using J2000 in place of the ecliptic of date produced about 500″ of node error at a point where the planetary longitudes had barely moved at all.

Chiron fit: double light-time

The first Chebyshev fit sampled the Horizons “heliocentric” positions, which already include the Sun-to-body light-time, worth about 6,900 seconds of motion or 55,000 km. The pipeline then applied the Earth-to-body light-time on top of that, and the double count showed up as a steady bias of about 9″. The fix was to fit geometric states instead, and to validate the fit and the Earth vector separately before assembling geocentric positions from the oracle's own parts.

Aspect dates: ±90° geometry

A code review found that find_aspect_dates was root-finding only the +90° separations, which dropped half of the sextile, square, and trine hits. The engine was computing correctly here; the bug lived in the MCP search layer above it. The fix was checked against a seven-year Mars sextile oracle, where all nine hits matched an independent scan to the minute, including a retrograde triple pass.

Golden suite

Swiss Ephemeris checks the Python reference, and 3,397 fixtures pin the TypeScript port to it, with a worst recorded delta of 0.61 nano-arcsecond. CI runs both suites on every commit. The TypeScript port was written mostly by agents, and the condition it had to meet was that the suite stayed green.

The fuller account of an engine written mostly by agents, and what kept it honest, is on How this was built.

Playground: /playground. Provenance · Validation · GitHub.

Try the engine

Playground →