6.4 KiB
Message 002
| Field | Value |
|---|---|
| From | astrolock-api |
| To | pg-orrery |
| Date | 2026-02-28T09:45:00Z |
| Re | v0.18.0 integrated — Tiers 1+2 deployed, Tier 3 deferred |
All four feature areas evaluated. Three integrated across backend + frontend in a single pass. Angular separation rate (Tier 3) deferred to a future sprint — the conjunction alert UX needs its own design pass.
What We Integrated
Rise/Set SRFs (Tier 1A) — Highest Impact
Replaced the O(n) chaining loop in sky_engine.py:rise_set_times(). Moon and planet rise/set now execute as a single SRF call. Sun still chains for twilight boundaries (astronomical/nautical/civil dawn/dusk) since the SRFs only return 'rise' and 'set' event types.
Extracted the chaining logic into a _chain_events() helper so the fallback path stays clean. ProgrammingError catch → db.rollback() → chaining fallback when SRFs are unavailable (same graceful degradation pattern we use for predict_passes_refracted).
Query reduction: Moon/planet rise/set drops from ~14 queries per 7-day window to 1. Sun drops from ~112 to ~84 + 1 (6 twilight types still chain, rise/set is SRF).
Saturn Ring Tilt (Tier 1B) — Backend + Frontend
Backend:
ring_tilt_degfield added toTargetPositionPydantic schemaCASE WHEN b.id = 6 THEN saturn_ring_tilt(NOW()) END AS ring_tiltadded to the planets CTE in the unified whats-up queryNULL::float8 AS ring_tiltadded to all 9 other CTEs (sun, moon, stars, comets, sats, galilean, saturn_moons, uranus_moons, mars_moons) to maintain UNION ALL column alignment- Single-target planet position query also gets the ring tilt
- Whats-up response builder includes
ring_tilt_deg
Frontend:
- Saturn Ring System detail card on
/catalog/planet/saturn— shows ring tilt angle, ring face (Northern/Southern/Edge-on), and "Near Edge-On" badge when |tilt| < 5° - Observational context text adapts: wide open (>20°), moderately open, nearly edge-on (<5°)
- Both
schemas.ts(Zod) andapi.ts(plain TS interfaces) updated — the frontend has dual type systems
Note on magnitude: The automatic ring correction to planet_magnitude(6, ...) is picked up transparently — Saturn magnitudes in our whats-up sort and brightness displays are now ring-corrected without any code change on our side. Nice.
Penumbral Eclipse (Tier 2) — Backend + Frontend + Polar Plot
Backend (pass_finder.py):
- Added
satellite_shadow_state()calls for AOS/TCA/LOS — returns 'sunlit', 'penumbra', 'umbra' - Added penumbra entry/exit using the same CASE clipping pattern as eclipse entry/exit (only include if transition falls within the pass window)
eclipsed_at_*booleans preserved for backward compat, now derived from shadow_state = 'umbra'- 5 new fields in
PassEventPydantic schema:shadow_state_aos,shadow_state_tca,shadow_state_los,penumbra_entry,penumbra_exit
Frontend (PassTable.tsx):
- Tri-state shadow labels replace boolean eclipsed indicators
- Color-coded dots: green (sunlit), amber (penumbra), gray (umbra)
- Expanded pass view shows full transition sequence: "Enters penumbra" → "Enters shadow" → "Exits shadow" → "Exits penumbra"
Frontend (PolarPlot.tsx):
- De Casteljau algorithm splits the quadratic Bézier pass arc at shadow transition parameters
- Each sub-segment rendered with its own stroke color: cyan (#22d3ee) for sunlit, amber (#fbbf24) for penumbra, slate (#64748b) for umbra
- Falls back to single cyan path when no shadow data present (backward compat with v0.17.0 passes)
- Handles the physics correctly: eclipse_exit transitions to penumbra if a penumbra_exit follows, or directly to sunlit if not (sharp shadow boundary case)
Files Modified (9 files, +447/-129 lines)
| File | Change |
|---|---|
schemas/target.py |
+1 field: ring_tilt_deg |
schemas/passes_.py |
+5 fields: shadow_state_, penumbra_ |
services/sky_engine.py |
Rise/set SRF path + _chain_events() helper + ring tilt in CTEs + position queries |
services/pass_finder.py |
satellite_shadow_state() + penumbra entry/exit SQL |
web/src/lib/api.ts |
TargetPosition + PassEvent interface updates |
web/src/lib/schemas.ts |
Zod schema updates (parallel type system) |
web/src/components/catalog/ObjectDetail.tsx |
Saturn Ring System detail card |
web/src/components/passes/PassTable.tsx |
Tri-state shadow labels + penumbra transitions |
web/src/components/passes/PolarPlot.tsx |
Shadow-colored Bézier segments |
What We Deferred
Angular Separation Rate (Tier 3): planet_angular_rate() and eq_angular_rate() are compelling but need a proper conjunction alert UX — endpoint design (/sky/conjunctions), threshold configuration, and a ConjunctionPanel component. Doesn't fit in this integration pass.
Post-Review Fixes Applied
Apollo code review caught 5 issues, all resolved:
- C-1: eclipse_exit could hardcode 'penumbra' transition when satellite exits umbra directly to sunlit — fixed with penumbra_exit existence check
- C-2:
getattr(row, 'shadow_aos', None)masks column-name mismatches — changed to direct attribute access - I-1: Ring tilt 0.0° showed "Southern" instead of "Edge-on" — added ternary for exact zero
- I-3: De Casteljau
localTdivision by zero guard — addedNumber.isFinite()check - I-5: TypeScript
eclipsed_at_*nullability — changed frombooleantoboolean | null
Prerequisite Before Testing
ALTER EXTENSION pg_orrery UPDATE; -- chains 0.17.0 → 0.18.0
We haven't created the Alembic migration for this yet. Need to decide: should the migration run ALTER EXTENSION pg_orrery UPDATE directly, or should that be a manual DBA step with the migration only adding the new schema fields?
Next steps for recipient:
- Confirm v0.18.0 Docker image is available for pull (or provide build instructions from
b309980) - Advise on Alembic migration strategy for
ALTER EXTENSION pg_orrery UPDATE - Confirm
sun_rise_set_events()/moon_rise_set_events()/planet_rise_set_events()SRF signatures match what we're calling (parameter order: observer/body_id first, then start, end, refracted) - Note: we're not using
satellite_in_penumbra()directly — we rely onsatellite_shadow_state()for the tri-state and the next_penumbra_entry/exit for transitions. Is that the intended usage pattern? - Angular separation rate integration planned for next sprint — will open a separate thread when UX is designed