111 Commits

Author SHA1 Message Date
ce59a5ce72 Add message 006: v0.11.0 integration confirmed
Constructors and galilean_equatorial() deployed to both environments.
Zero NULL RA/Dec remaining. Ready to tag v0.11.0.
2026-02-23 14:20:13 -07:00
7c76ffc76c Track astrolock message 004: v0.10.0 comet RA/Dec + proximity queries 2026-02-23 14:07:56 -07:00
9158c7c55a Add v0.11.0: make_orbital_elements constructors + moon equatorial functions
6 new SQL functions (114 -> 120):
- make_orbital_elements(): construct from 9 floats, angles in radians
- make_orbital_elements_deg(): same with angles in degrees, matches
  text I/O convention and typical catalog column layouts
- galilean_equatorial(): geocentric RA/Dec for Io/Europa/Ganymede/Callisto
- saturn_moon_equatorial(): geocentric RA/Dec for Mimas through Hyperion
- uranus_moon_equatorial(): geocentric RA/Dec for Miranda through Oberon
- mars_moon_equatorial(): geocentric RA/Dec for Phobos/Deimos

Constructors requested by astrolock-api to replace fragile
format(9 args)::orbital_elements cast pattern. Moon equatorial
functions fill the last NULL RA/Dec gaps in their unified sky query.

All 20 regression suites pass.
2026-02-23 14:07:39 -07:00
be7e28e2b6 Update docs for v0.10.0: benchmarks, Skyfield parity, LLM references
- Add timing numbers for equatorial, aberration, angular distance,
  refraction, and star proper motion+parallax to benchmarks page
- Update From Skyfield page: v0.10.0 now has light-time + aberration
  parity; remaining gap narrowed to nutation (~9 arcsec) and polar motion
- Update llms.txt and llms-full.txt for 114 functions, new DE apparent
  variants, equatorial spatial operators, and aberration/parallax notes
2026-02-21 22:00:52 -07:00
db1f478e4f Update CLAUDE.md for v0.10.0, gitignore bench catalogs, add roadmap
- CLAUDE.md: 106 -> 114 functions, 18 -> 19 test suites, add aberration
  suite, DE apparent variants, equatorial spatial domain to tables
- .gitignore: ignore downloaded TLE catalogs in bench/ (alpha5, celestrak,
  satnogs, spacetrack, supgp, mega/merged, cookies)
- docs/TODO-v0.10.0.md: rewrite as post-v0.10.0 roadmap with next version
  candidates (make_orbital_elements, galilean_equatorial, equatorial GiST
  index, nutation, Delta T, rise/set)
- Track bench/build_catalog.py and agent thread message 001
2026-02-21 21:52:05 -07:00
b0741c553b Add v0.10.0: aberration, DE apparent, angular separation, stellar parallax
Annual stellar aberration (~20 arcsec) added to all 6 existing _apparent()
functions via classical first-order v/c projection (Ron & Vondrak). Earth
velocity sourced from VSOP87 xyz[3..5] (analytic) or DE numerical
differentiation.

New functions (106 -> 114):
- eq_angular_distance(): Vincenty formula, stable at 0 and 180 deg
- eq_within_cone(): cosine shortcut for fast cone-search predicate
- <-> operator on equatorial type
- 6 DE apparent variants with VSOP87 fallback:
  planet/sun/moon_observe_apparent_de(),
  planet/moon_equatorial_apparent_de(),
  small_body_observe_apparent_de()

Stellar parallax now functional in star_observe_pm() and
star_equatorial_pm() — Green (1985) Eq. 11.3 displacement using
Earth heliocentric position from VSOP87.

All 19 regression suites pass (18 existing + new aberration suite).
v0.10.0
2026-02-21 21:47:42 -07:00
3a378f572a Reply to v0.9.0 thread: integration complete on both servers 2026-02-21 21:43:46 -07:00
e15428d610 Update CLAUDE.md and docs reference pages for v0.9.0
- CLAUDE.md: 82→106 functions, 8→9 types, 16→18 test suites, new file listings
- New functions-refraction.mdx: Bennett refraction, P/T correction, apparent elevation, refracted passes
- types.mdx: add equatorial type (24 bytes, apparent RA/Dec/distance of date)
- functions-satellite.mdx: add eci_to_equatorial, eci_to_equatorial_geo, predict_passes_refracted
- functions-solar-system.mdx: add 7 equatorial + light-time apparent functions
- functions-stars-comets.mdx: add proper motion, equatorial, apparent functions
- functions-de.mdx: add planet_equatorial_de, moon_equatorial_de
- astro.config.mjs: add refraction page to sidebar
v0.9.0
2026-02-21 18:23:59 -07:00
0863b0e08c Fix cache headers: force revalidation on content, correct _astro path
- Add Cache-Control: no-cache as default so browsers revalidate via ETag
  instead of heuristic caching stale llms.txt and HTML pages
- Fix hashed asset path from /docs/_astro/* to /_astro/* (root is /srv)
- _astro/* immutable rule still applies for hashed Vite bundles
2026-02-21 15:36:41 -07:00
b33d63034b Add v0.9.0 apparent position features: equatorial type, refraction, proper motion, light-time
New equatorial type (24 bytes: RA/Dec/distance) captures apparent coordinates
of date — what the observation pipeline computes at precession step 3 but was
discarding before hour angle conversion. Matches telescope GoTo mount conventions.

24 new SQL functions (82 → 106 total):
- equatorial type I/O + 3 accessors (eq_ra, eq_dec, eq_distance)
- Satellite RA/Dec: eci_to_equatorial (topocentric), eci_to_equatorial_geo (geocentric)
- Solar system equatorial: planet/sun/moon/small_body_equatorial
- Atmospheric refraction: Bennett (1982) with domain clamp at -1 deg
- Refracted pass prediction: predict_passes_refracted (horizon at -0.569 deg)
- Stellar proper motion: star_observe_pm, star_equatorial_pm (Hipparcos/Gaia convention)
- Light-time correction: planet/sun/small_body_observe_apparent, *_equatorial_apparent
- DE equatorial variants: planet_equatorial_de, moon_equatorial_de

Also includes v0.8.0 orbital_elements type (MPC parser, small_body_observe),
GiST 0-based indexing fix, llms.txt updates, and doc improvements.

All 18 regression suites pass. Zero build warnings (GCC + Clang).
2026-02-21 15:31:46 -07:00
b79f6948c6 Add llms.txt and llms-full.txt for LLM-friendly project reference
Per the llms.txt spec — standard index at /llms.txt linking all 44 doc
pages, plus /llms-full.txt with all 82 function signatures, 8 types,
body ID tables, operators, and runnable query patterns inline (~18KB).
2026-02-21 11:33:13 -07:00
b6c5149cd7 Add Cosmic Queries Cookbook guide — 9 cross-domain SQL recipes
New guide combining multiple pg_orrery function families with
PostgreSQL analytical functions: Kirkwood gap histograms, Kepler
regression, asteroid family taxonomy, universal sky report, planetary
alignment detection, ISS eclipse timing, PostGIS ground tracks,
solar system dashboard view, and satellite shell census.
2026-02-18 16:45:25 -07:00
53733daeba Update docs for v0.8.0 orbital_elements type and MPC parser
Add orbital_elements (72-byte Keplerian element type) to types reference,
three new function sections (oe_from_mpc, small_body_heliocentric,
small_body_observe) to the functions reference, MPC catalog loading
workflow to the comets/asteroids guide, and update CLAUDE.md with
v0.8.0 version numbers, 82 functions, 8 types, 16 test suites.
2026-02-18 14:22:39 -07:00
1adab6e136 Update docs with 66k benchmark results, honest SP-GiST framing
- benchmarks.mdx: Add GiST conjunction screening and KNN sections,
  update all numbers to 66,440-object catalog, PG 17→18, show SP-GiST
  slower than seqscan at this scale with explanation of why
- operators-gist.mdx: Real 66k performance tables for GiST and SP-GiST,
  rewrite KNN example with scalar subquery pattern, add CTE warning
- conjunction-screening.mdx: Update catalog size, candidate counts,
  add KNN scalar subquery note, verified performance numbers
2026-02-18 12:23:47 -07:00
de742fc3aa Fix pg_tle sizeof/INTERNALLENGTH mismatch, exact leaf recheck
The pg_tle struct has been 104 bytes since v0.1.0, but INTERNALLENGTH
is 112.  The size comment claimed "11 doubles (88 bytes)" — there are
10 (80 bytes).  Every palloc(sizeof(pg_tle)) across the codebase
allocated 104 bytes while PostgreSQL's datumCopy/heap_form_tuple
copied 112, causing an 8-byte overread.

Fix: add _reserved[8] to pg_tle, making sizeof(pg_tle) == 112.
This is backward compatible — existing on-disk tuples already have
112 bytes allocated (from typlen), with zeros in the trailing 8.

Also in gist_tle.c:
- Remove TLE_TYPLEN band-aid, use sizeof(pg_tle) everywhere
- Set recheck = false for leaf entries in consistent: the orbital
  key is computed identically to the SQL operator, so the GiST
  leaf check is exact (eliminates unnecessary heap fetches)
2026-02-18 11:48:49 -07:00
347acf0906 Fix GiST union 0-based indexing and palloc size, add 66k benchmark
Two bugs in gist_tle.c caused the && (overlap) operator to return
zero results through the GiST index while sequential scan worked:

1. gist_tle_union read from vector[FirstOffsetNumber] (index 1),
   skipping vector[0] which holds the accumulated union key.
   Every internal node collapsed to a single-entry bounding box.
   Fixed: seed from vector[0], loop from 1.

2. All GiST key allocations used sizeof(tle_orbital_key) (32 bytes)
   or sizeof(pg_tle) (104 bytes), but INTERNALLENGTH is 112.
   index_form_tuple() copies typlen bytes, causing buffer overread.
   Fixed: TLE_TYPLEN constant (112) for all index datum allocations.

The <-> (KNN distance) operator was unaffected because it uses
gist_tle_distance, not gist_tle_consistent.

Verified against 66,440-object catalog:
- && consistency: 9 seqscan == 9 GiST (ISS conjunction)
- <-> KNN: 10 nearest in 2.1ms via index-ordered scan
- All 15 regression tests pass
2026-02-18 11:22:07 -07:00
eadbb45a3b Fix function names and argument order in catalog guide 2026-02-18 10:28:26 -07:00
89ea0246b6 Rewrite load_bench.sh to use pg-orrery-catalog with curl fallback
Three-tier discovery: pg-orrery-catalog in PATH, sibling dev
checkout, or original build_catalog.py + curl. Indexes use
IF NOT EXISTS for idempotent re-runs.
2026-02-18 10:26:00 -07:00
26ae80d340 Add Building TLE Catalogs guide, cross-reference pg-orrery-catalog
New guide: guides/catalog-management.mdx covering the full
download/merge/load pipeline with pg-orrery-catalog CLI.

Updated tracking-satellites.mdx to reference the companion tool
instead of "No TLE fetching". Added cross-reference in benchmarks
setup instructions.
2026-02-18 10:19:13 -07:00
747b7ae60a Fix L1 inclination pruning for HEO orbits, add 66k benchmark
Bug: inner_consistent used sma_low for footprint calculation, but
ground footprint grows with altitude. High-SMA bins (GTO, HEO)
need sma_high to compute the maximum footprint — using sma_low
caused 453 false negatives at high-latitude observers (Tromsoe).

Fix: use sma_high (not sma_low) in L1 inclination pruning.

Added regression test: GTO-debris (inc 5 deg, e=0.73) at Tromsoe
must return identical results from seqscan and index scan.

Benchmark on 65,886-object catalog (full Space-Track including
decayed): 80-92% pruning, zero false negatives across 7 query
patterns. SP-GiST beats seqscan for high-latitude observers.
2026-02-17 23:05:49 -07:00
13d49c1072 Add 30k Space-Track catalog and benchmark results
Space-Track USSPACECOM catalog: 29,784 objects from full GP query.
Benchmark shows SP-GiST index reaches parity with seqscan at 30k:
  - Delta: +1.6ms (14k) -> +0.9ms (20k) -> +0.0ms (30k)
  - Planner voluntarily chooses Index Only Scan at this scale
  - Zero heap fetches (all data served from index pages)
  - 75.9% candidate pruning on 2h/10deg query

Archive includes TLEs from Space-Track, TLE API, and SatNOGS.
2026-02-17 22:22:58 -07:00
5e5588fddb Update docs for v0.7.0: types, operators, test count, performance framing
- types.mdx: "seven" → "seven base types + one SQL composite",
  add observer_window section with field table and usage example
- operators-gist.mdx: "three operators" → "four operators", reframe
  SP-GiST performance as scalability feature (honest about seqscan
  being faster at 14k catalog size, index helps at 100k+)
- installation.mdx: "14 test suites" → "15 test suites", list all
  suites including od_fit, spgist_tle, vallado_518
- design-principles.mdx: clarify observer_window is SQL composite
  (variable-length, query-time only), base types still STORAGE=plain
- pass-prediction.mdx: lead with operator value (80-90% elimination),
  SP-GiST index framed as optional for large catalogs
2026-02-17 21:51:26 -07:00
845aeee3a5 Add pass prediction guide, operator reference, and benchmarks
New docs:
- guides/pass-prediction.mdx: two-stage workflow (SP-GiST filter
  then SGP4 propagation), query window comparison tabs, GiST/SP-GiST
  coexistence example
- reference/operators-gist.mdx: &? operator signature and description,
  observer_window type reference, SP-GiST operator class docs with
  eccentricity/HEO limitation aside

Benchmarks on 14,376 CelesTrak active satellites:
- SP-GiST index: 2,344 kB, builds in 19 ms
- GiST index: 2,904 kB, builds in 45 ms
- Consistency: 0 false negatives, 0 false positives
- At 14k catalog size, seqscan (~6 ms) still beats index scan (~8 ms)
  due to low page count; cross-over expected at ~100k objects
2026-02-17 21:30:57 -07:00
e1c22cb873 Fix GiST picksplit crash and SP-GiST operator argument order
GiST: entryvec->vector[] uses 1-based indexing (FirstOffsetNumber),
not 0-based. Reading vector[0] hit uninitialized memory, causing
SIGSEGV on large catalogs (14k+ satellites). Fixed in gist_tle_union
and gist_tle_picksplit.

SP-GiST: PostgreSQL requires the indexed column as the LEFT argument
of the operator to form a ScanKey (skey.h:23-26). Flipped &? from
(observer_window, tle) to (tle, observer_window) so inner_consistent
receives scankeys for tree-level pruning.

Removed L0 altitude pruning from inner_consistent — SMA bins don't
carry eccentricity, so HEO satellites (e.g. CLUSTER II, e=0.88,
SMA ~70000 km, perigee ~2000 km) were falsely pruned. L0 now only
narrows SMA range for L1 footprint computation.

All 15 regression tests pass. Consistency check on 14,376 satellites
confirms 0 false negatives, 0 false positives.
2026-02-17 21:30:28 -07:00
2a7240e739 Harden SP-GiST orbital trie after Hamilton review
Fix M2: clamp picksplit nBins to nTuples to prevent out-of-bounds
read on the entries array when called with a single tuple.

Fix H2: use WGS72_AE as effective bin_low for the first bin in L0
inner_consistent, preventing false negatives when objects with lower
SMA than the first label are inserted after index creation.

Fix H3: reject degenerate TLEs (mean_motion <= 0) early in the
visibility filter rather than propagating nonsensical values.

Fix L1: extract shared tle_passes_visibility_filter() to eliminate
duplicated 3-stage filter logic between leaf_consistent and the
standalone tle_visibility_possible operator.

Add boundary tests: degenerate TLE, polar observer, zero-duration
window, and post-insert index-vs-seqscan consistency check.
2026-02-17 20:36:47 -07:00
6f9be428f9 Add SP-GiST orbital trie index for satellite pass prediction (v0.7.0)
2-level SP-GiST index on TLE data: SMA at L0, inclination at L1, with
query-time RAAN filter via J2 secular precession.  New &? operator
(observer_window &? tle) returns true when a satellite might be visible
from a ground observer during a time window.

Index prunes by altitude band, inclination+footprint vs observer
latitude, and RAAN alignment against local sidereal time.  Operator
class tle_spgist_ops is opt-in (not default), coexists with existing
GiST tle_ops.  Equal-population picksplit with sqrt(n) bins.
2026-02-17 20:27:54 -07:00
bb235f51fa Add SP-GiST orbital trie design spec for satellite pass prediction index
Evolved from the original KTrie custom AM proposal (preserved as
KTRIE-SPEC-ORIGINAL.md). Key design decisions: 2-level trie (SMA +
inclination) instead of 5, SP-GiST framework instead of custom AM,
query-time RAAN filter instead of trie level, propagation-aware cost
estimation via traversalValue.
2026-02-17 19:53:42 -07:00
3ea4e2bf53 Add OD documentation and workflow translation pages for v0.4.0-v0.6.0
New pages:
- OD function reference (tle_from_eci, tle_from_topocentric,
  tle_from_angles, tle_fit_residuals)
- OD guide (ECI, topocentric, angles-only, range rate, weights,
  multi-observer, covariance interpretation)
- From find_orb to SQL (OD workflow comparison)
- From Poliastro to SQL (Lambert/Kepler comparison)

Updated pages:
- Corrected stale "No orbit determination" claim
- Updated function counts and test suite counts
- Added v0.4.0-v0.6.0 upgrade paths
- Added OD to capabilities table, theory-to-code mapping,
  constants/accuracy reference
- Added OD examples to Skyfield comparison and SQL Advantage
- Fixed stale version references across workflow pages
2026-02-17 18:43:13 -07:00
adfb6949e1 Add range rate fitting, weighted observations, and Gauss angles-only IOD (v0.6.0)
Range rate: topocentric residuals now include an optional 4th component
(dot(Δr, v_ecef) / |Δr|) with OD_RR_SCALE=10.0 for unit balancing.
Controlled via fit_range_rate parameter on tle_from_topocentric().

Weighted observations: per-observation weights applied as √w scaling
to both residuals and Jacobian rows, producing the weighted normal
equations H'WH without explicit W construction. Weights parameter
added to tle_from_eci, tle_from_topocentric, and tle_from_angles.

Gauss angles-only IOD: Vallado Algorithm 52 implementation for
seed-free orbit recovery from 3+ RA/Dec observations. New RA/Dec
residual function with cos(dec) scaling and wrap-around handling.
New tle_from_angles() and tle_from_angles_multi() SQL functions
accepting RA in hours [0,24), Dec in degrees [-90,90].

New standalone test suite: test_od_gauss (17 assertions).
New regression tests: Tests 18-25 covering range rate, weights,
angles-only with/without seed, and error cases.
2026-02-17 17:48:13 -07:00
6e17513885 Merge rename/pg-orrery: v0.5.0 OD solver enhancements 2026-02-17 17:09:14 -07:00
bca8b3e7eb Add covariance output and condition number to OD solver (v0.5.0)
Computes formal covariance (H^T·H)^{-1} via LAPACK dpotrf_/dpotri_
after DC convergence. Returns upper-triangle array (21 elements for
6-state, 28 for 7-state with B*), condition number from SVD, and
nstate count. Covariance is computed even for perfect-seed fits.

Bumps extension to v0.5.0 with full install SQL and migration path.
2026-02-17 16:15:44 -07:00
6e57071970 Add Gibbs IOD bootstrap for seed-free orbit determination
Eliminates the seed TLE requirement for topocentric fitting by
computing an initial orbit estimate from 3 well-spaced observations
using the Gibbs method. ECI fitting retains the single-observation
r,v approach (exact for two-body) with Gibbs as fallback.
2026-02-17 16:06:05 -07:00
59fd8ba743 Add multi-observer support for topocentric fitting
Extend od_observation_t with observer_idx so each observation can
reference a different ground station. Config now holds an array of
observers instead of a single pointer. The existing single-observer
tle_from_topocentric() is unchanged (sets observer_idx=0 for all obs).

New overload: tle_from_topocentric(topo[], ts[], observer[], int4[], ...)
accepts parallel observer_ids array indexing into the observers array.
PG function overloading resolves by argument types.

Tests 9-11: two-station fit converges, single-station via multi-observer
API matches, out-of-range observer_id raises error.
2026-02-17 15:59:11 -07:00
9b0634725b Add adaptive step limiting to DC solver
Scale step limits by a trust-region factor that halves on divergence
(RMS increases > 1%) and relaxes toward full step on good convergence
(RMS decreases > 10%). Prevents oscillation with poor initial guesses
without affecting well-seeded fits. Also stores SVD condition number
for diagnostic use in upcoming covariance output.

Existing 8 OD regression tests + 67 standalone math tests unaffected
(adaptive_factor starts at 1.0, round-trip tests never trigger
divergence).
2026-02-17 15:55:20 -07:00
87ab81e7d0 Add observation-to-TLE fitting (orbit determination) for v0.4.0
Batch weighted least-squares differential correction using equinoctial
elements, LAPACK dgelss_() for SVD solve, vendored SGP4/SDP4 as the
propagation engine. Per Vallado & Crawford (2008) AIAA 2008-6770.

New SQL functions:
  - tle_from_eci(): fit TLE from ECI position/velocity ephemeris
  - tle_from_topocentric(): fit TLE from az/el/range observations
  - tle_fit_residuals(): per-observation position residuals diagnostic

Solver features: 6-state (orbital) or 7-state (+ B*) fitting,
equinoctial elements for singularity-free optimization, tiered step
limiting, Brouwer/Kozai Newton-Raphson conversion, auto initial guess
from first ECI observation when no seed TLE provided.

Tested: 8 regression tests (LEO/MEO/near-circular round-trips,
B* recovery, topocentric, seedless, error handling, diagnostics),
67 standalone math unit tests, all 14 suites pass.
2026-02-17 15:44:48 -07:00
b18cded4c2 Add PG version test matrix (14-18)
Shell script drives the Dockerfile builder stage across PG versions,
capturing pass/fail + timing per version. Makefile targets: test-matrix,
test-pg%, test-matrix-clean. Also runs standalone DE reader test in the
builder stage to catch compiler-version regressions.

Fix pork chop grid test: add ORDER BY to CROSS JOIN (optimizer chooses
different join nesting across PG versions, reordering rows).
2026-02-17 14:53:32 -07:00
4f8ad7cea1 Add docs and source links to README header
Production site link was buried at line 193. Move it to the
top where visitors actually look.
2026-02-17 14:05:11 -07:00
3915d1784f Rename pg_orbit to pg_orrery
An existing product called PG Orbit (a mobile PostgreSQL client)
creates a naming conflict. pg_orrery — a database orrery built from
Keplerian parameters and SQL instead of brass gears.

Build system: control file, Makefile, Dockerfile, docker init script.
C source: GUC prefix, PG_FUNCTION_INFO_V1 symbol, header guards,
ereport prefixes, comments across ~30 files including vendored SGP4.
SQL: all 5 install/migration scripts, function name pg_orrery_ephemeris_info.
Tests: 9 SQL suites, 8 expected outputs, standalone DE reader test.
Documentation: CLAUDE.md, README.md, DESIGN.md, Starlight site infra,
36 MDX pages, OG renderer, logo SVG, docker-compose, agent threads.

All 13 regression suites pass. Docs site builds (37 pages).
2026-02-17 13:36:22 -07:00
cd338c3c64 Vendor SGP4/SDP4 as pure C, drop g++ dependency
Replace the sat_code git submodule (lib/sat_code/) with vendored
sources in src/sgp4/. The upstream .cpp files are renamed to .c —
the code is valid C99 with zero C++ features. This eliminates the
g++ and -lstdc++ build dependencies.

Adds 518 Vallado test vectors (AIAA 2006-6753-Rev1) as a 13th
regression suite to verify byte-identical numerical output.

Updates all documentation (CLAUDE.md, DESIGN.md, 11 MDX pages,
Dockerfile) to reflect the new layout and pure-C compilation.
2026-02-17 12:45:39 -07:00
27a6e7106f Custom OG image renderer with pg_orbit branding
Replace generic blackAndWhite preset with custom renderer using
site colors (#0a0e17 dark background, #f59e0b amber accents),
decorative orbital rings watermark, branded footer with pg_orbit
name and site URL. Inter font in 400/700 weights.
2026-02-17 03:53:07 -07:00
86a2e386b7 Add tagline and docs SEO infrastructure
Hero tagline: "It's not rocket science. (It's celestial mechanics.
But now it's just SQL.)" across README, index.mdx, and meta description.

Add astro-icon with Lucide icon set, astro-seo-meta, and
astro-opengraph-images (blackAndWhite preset, Inter font). Override
Starlight Head component to inject og:image and twitter card tags
with auto-generated 1200x630 PNG images for all 37 pages.
2026-02-17 03:48:14 -07:00
bcf460a6ff Add standalone DE reader unit test and aliasing safety docs
Standalone test (test/test_de_reader.c): generates a synthetic 12KB
DE binary with known Chebyshev coefficients, exercises header parsing,
polynomial evaluation at 5 domain points, Earth derivation via
center=99, Moon geocentric, layout validation, range/body error paths,
NAN sentinel, and garbage file rejection. 55 tests, no PG dependency.

Makefile: add `make test-de-reader` target; also includes the earlier
sat_code C++ -> pure C sgp4 migration that was missed from prior commits.

astro_math.h: document that ecliptic_to_equatorial/equatorial_to_ecliptic
are NOT safe for aliased (in-place) calls — equ[1] is written before
equ[2] reads ecl[1]. The vendored sgp4/sdp4.c has separate in-place
versions using a temp variable.
2026-02-17 01:56:44 -07:00
9e420a1fc9 Harden DE reader: layout validation, Chebyshev clamping, FD safety
Three independent reviews (manual, failure-mode analysis, JPL spec
cross-reference) confirmed the mathematical core is correct. This
commit addresses defensive coding and operational behavior:

- Fix header byte-offset comments (12 groups = 144 bytes, not 156)
- Add layout validation before Chebyshev interpolation (prevent
  buffer underread for bodies absent from a DE edition)
- Clamp Chebyshev argument to [-1,+1] with debug assertion for
  values beyond 1e-10 tolerance (catches structural normalization
  errors vs normal FP boundary rounding)
- Add O_CLOEXEC to prevent FD leaks to child processes
- Change GUC from PGC_SIGHUP to PGC_BACKEND to match actual
  one-shot initialization behavior
- Fix provider consistency: planet_velocity_de() now accepts a
  use_de flag to match the provider used for positions (rule 7)
- Optimize eph_de_moon() to use raw geocentric Moon (center=-1)
  instead of computing Earth just to subtract it back out
- Pre-compute obliquity trig constants (verified to full precision)
- Tighten canary check from 0.9-1.1 AU to 0.97-1.04 AU
- Return NAN for missing constants (0.0 was ambiguous)
- Add _Static_assert for sizeof(double) == 8
- Remove unused HDR_* macros
- Zero Datum values before setting null flags in ephemeris_info
- Replace magic numbers with DE_MOON/DE_SUN constants

All 13 regression tests pass. Zero compiler warnings.
2026-02-17 00:20:31 -07:00
15fa553c0e Add optional JPL DE440/441 ephemeris support (v0.3.0)
Clean-room DE binary reader (~400 lines C) with Chebyshev/Clenshaw
evaluation — no GPL dependency on jpl_eph. Per-backend lazy
initialization preserves PARALLEL SAFE. Existing VSOP87/ELP82B
functions stay IMMUTABLE; new _de() variants are STABLE with
automatic fallback to compiled-in ephemerides on any DE failure.

Implementation:
- de_reader.c: header parse, record seek, Clenshaw recurrence
- eph_provider.c: GUC (pg_orbit.ephemeris_path), lazy init,
  ICRS-to-ecliptic frame rotation, on_proc_exit cleanup
- de_funcs.c: 11 new SQL functions (_de variants + diagnostics)
- Constant chain of custody rules 6-8 (frame rotation,
  same-provider, AU consistency)

Extract observe_from_geocentric() to astro_math.h for shared use
by planet_funcs.c, moon_funcs.c, and de_funcs.c.

57 → 68 functions, 11 → 12 regression test suites, all passing.
2026-02-16 19:54:48 -07:00
0e09975e08 Add repo and docs links to CLAUDE.md header 2026-02-16 08:05:30 -07:00
a8c6e98bdb Add hero image: PostgreSQL elephant orbiting a planet 2026-02-16 07:52:15 -07:00
f67af5f55d Document production deployment process in CLAUDE.md 2026-02-16 07:50:00 -07:00
1c8cf27d36 Fix docs domain: pg-orbit.warehack.ing v0.2.0 2026-02-16 07:34:44 -07:00
a78e8eb27c README v0.2.0 rewrite and docs deployment infrastructure
README covers all 57 functions across 9 domains with quick-start
examples, capability matrix, body ID tables, and performance benchmarks.
Links to Starlight docs site for detailed reference.

Adds Docker Compose deployment for docs site behind caddy-docker-proxy
with dev/prod modes and Vite HMR support through reverse proxy.
2026-02-16 07:09:37 -07:00
76767c2909 Update CLAUDE.md for v0.2.0
Reflects the full solar system expansion: 57 functions, 7 types,
11 test suites, 36 source files, body ID tables, error handling
patterns, astronomical constants, and the Starlight docs site.
2026-02-16 03:19:16 -07:00