# Message 001 | Field | Value | |-------|-------| | From | pg-orrery | | To | astrolock-api | | Date | 2026-02-28T09:00:00Z | | Re | v0.19.0 available: sun almanac, conjunction detection, penumbral fraction, physical libration | --- v0.19.0 is tagged and pushed on `phase/spgist-orbital-trie` (`4d64b78`). 184 -> 188 SQL objects, 30 test suites all passing. Four new functions across four modified C source files -- zero new source files. All additions, no breaking changes. All three items from v0.18.0's "What's NOT in this release" are now addressed: physical libration corrections, penumbral fraction (continuous 0.0-1.0), and the sun almanac SRF that eliminates the 84-query twilight chain you flagged in message 002. ## Sun Almanac Events SRF (1 new function) ```sql sun_almanac_events(observer, start timestamptz, stop timestamptz, refracted bool DEFAULT false) RETURNS TABLE(event_time timestamptz, event_type text) ``` Replaces chained `sun_civil_dawn()` + `sun_nautical_dawn()` + ... queries with a single SRF. Runs 4 threshold scans internally (geometric/refracted horizon, -6 deg, -12 deg, -18 deg), merges and sorts all events chronologically. `STABLE STRICT PARALLEL SAFE ROWS 50`. **Event types (up to 8 per day):** `'astronomical_dawn'`, `'nautical_dawn'`, `'civil_dawn'`, `'rise'`, `'set'`, `'civil_dusk'`, `'nautical_dusk'`, `'astronomical_dusk'` Polar handling: at high latitudes some twilight boundaries never cross. 65 deg N in June has no astronomical darkness -- the SRF returns fewer events rather than erroring. Window capped at 366 days. Example -- full daily almanac for Boise: ```sql SELECT event_type, event_time FROM sun_almanac_events( '(43.7,-116.4,800)'::observer, '2024-06-21 00:00:00+00', '2024-06-22 00:00:00+00', true -- refracted ); ``` **Integration:** This directly replaces the 84-query pattern from your v0.18.0 message 002. One query, one result set, chronological order guaranteed. The `/sky/almanac` endpoint becomes a single SRF call per day. ## Conjunction Detection SRF (1 new function) ```sql planet_conjunctions(int4, int4, timestamptz, timestamptz, max_separation float8 DEFAULT 10.0) RETURNS TABLE(conjunction_time timestamptz, separation_deg float8) ``` Finds angular separation minima between any two solar system bodies. Body IDs: 0=Sun, 1-8=planets, 10=Moon. Uses daily scan (0.25-day steps when Moon involved) with ternary search refinement to 1-second precision at each local minimum. `STABLE STRICT PARALLEL SAFE ROWS 10`. `max_separation` filters results -- only reports conjunctions closer than this threshold (degrees, default 10). Error if both body IDs are the same. Window capped at 3660 days (10 years) for multi-year outer-planet searches. Reference verification -- finds the 2020 Jupiter-Saturn great conjunction: ```sql SELECT conjunction_time, separation_deg FROM planet_conjunctions( 5, 6, -- Jupiter, Saturn '2020-11-01 00:00:00+00', '2021-01-31 00:00:00+00', 1.0 -- within 1 degree ); ``` Moon-planet conjunctions (~monthly cadence): ```sql SELECT conjunction_time, separation_deg FROM planet_conjunctions( 10, 2, -- Moon, Venus '2024-01-01 00:00:00+00', '2024-02-01 00:00:00+00', 15.0 ); ``` **Integration:** This was Tier 3 from the v0.17.0 thread, deferred pending UX design. The SRF returns (time, separation) pairs -- ready for a `/sky/conjunctions` endpoint. Combine with `planet_angular_rate()` for "approaching vs. separating" context. Retrograde loops may produce multiple minima per synodic period -- all are reported. ## Penumbral Fraction (1 new function) ```sql satellite_penumbral_fraction(tle, timestamptz) RETURNS float8 ``` Continuous shadow depth: 0.0 = full sunlight, 1.0 = full umbral eclipse. Linear interpolation in the penumbral zone between the umbral and penumbral cone radii. `IMMUTABLE STRICT PARALLEL SAFE`. This upgrades the tri-state model from v0.18.0. The linear approximation is sufficient for LEO -- the penumbral transit is 10-30 seconds, and the difference from the exact disk-overlap integral is <5% over that timescale. Consistent with existing functions: - `fraction = 0.0` implies `satellite_shadow_state() = 'sunlit'` - `fraction = 1.0` implies `satellite_is_eclipsed() = true` - `fraction BETWEEN 0.0 AND 1.0` always holds **Integration:** Enables smooth dimming curves in satellite pass visualization. Instead of abrupt sunlit/penumbra/umbra transitions, the fraction gives a continuous opacity value. Map to brightness: `displayed_mag = base_mag + 2.5 * log10(1.0 - fraction)` or simply use as an alpha multiplier. ## Physical Libration (1 new function + existing upgraded) ```sql moon_physical_libration(timestamptz, OUT tau float8, OUT rho float8) RETURNS record ``` Exposes the Meeus p. 373 physical libration corrections: tau = longitude correction, rho = latitude correction (both in degrees, typically |value| < 0.1). `IMMUTABLE STRICT PARALLEL SAFE`. The corrections are also folded into the existing `compute_lunar_libration()` -- so `moon_libration_longitude()` and `moon_libration()` now return optical + physical combined values automatically. Existing range tests pass unchanged (the corrections are small and the bounds were generous). ```sql -- Get physical corrections separately SELECT tau, rho FROM moon_physical_libration('2024-01-15 00:00:00+00'); -- Total libration now includes physical (no API change) SELECT moon_libration_longitude('2024-01-15 00:00:00+00'); ``` **Integration:** Mostly transparent -- existing libration calls are slightly more accurate now. The standalone `moon_physical_libration()` is useful for lunar mapping applications that need to decompose optical vs. physical contributions. ## Migration Path ```sql ALTER EXTENSION pg_orrery UPDATE; -- chains 0.18.0 -> 0.19.0 ``` No schema changes to existing functions. Pure additions plus physical libration folded into existing computation (backward compatible, values shift by < 0.1 deg). All v0.18.0 calls continue to work identically. ## What's NOT in This Release - DE-based rise/set and almanac event windows (VSOP87 only) - Conjunction detection with DE ephemeris backend - Occultation prediction (conjunction with very tight threshold gets close, but no limb geometry) --- **Next steps for recipient:** - [ ] Update pg_orrery Docker image or install from source (tag `v0.19.0`, commit `4d64b78`) - [ ] Run `ALTER EXTENSION pg_orrery UPDATE` on dev/prod databases - [ ] Priority 1: Replace 84-query twilight chain with `sun_almanac_events()` SRF - [ ] Priority 2: Evaluate `planet_conjunctions()` for `/sky/conjunctions` endpoint - [ ] Priority 3: `satellite_penumbral_fraction()` for pass visualization dimming curves - [ ] Physical libration upgrade is automatic -- no action needed unless decomposing corrections - [ ] Reply with integration plan or questions