Nyx is V1's sky, awe, calendar, event, and cosmic-perspective domain — the place a member opens to find out what is happening overhead tonight, whether it is worth going outside, what it means, and how to keep a record of what they saw. It serves the curious and the contemplative alike: a casual stargazer checking the next meteor shower, an enthusiast logging an aurora through binoculars, or someone who wants a Tara perspective meditation tied to the night sky. Nyx sits among the six customer-facing domains (Tara, Arete, Veritas, Nyx, Nisaba, Metis) hubbed at ../features.md. It is unusual among them in carrying a genuine astronomical compute core rather than a thin CRUD layer — see the companion architecture deep-dive Customer Domains.
This page is candid about what is real versus what is seam-mocked. The astronomy engine and the contract model are unambiguously real, in-repo, and test-pinned to known-correct published values. The live external data-source ingestion (actual NASA/IMO/NOAA fetches), the OAuth two-way calendar-provider sync, and cross-device observation sync are honestly partial / boundary-mocked / fail-loud, not passed off as shipped. Where a thing is planned or provider-gated, this page says so.
What Nyx is, at a glance#
Nyx covers five surfaces of one experience:
- A computed "tonight" core. A real Meeus-based ephemeris computes the Sun and Moon positions, the lunar illuminated fraction and phase, sidereal time, rise/transit/set, and observer-relative altitude/azimuth — entirely in-repo, with no external service dependency for the core figures.
- A canonical event model. Eleven event families and twenty-seven event types (meteor showers, eclipses, conjunctions, occultations, transits, comets, aurorae, satellite passes, supermoons, seasonal markers, deep-sky peaks), each with a family-specific detail schema, observation windows, and prediction-source provenance.
- An observe-loop. Forecasts say what should be visible; the
LoggedObservationcontract lets a member record what they actually saw — site, conditions, equipment, quality, attachments, sharing scope. - Calendar, save, follow, remind. Per-event calendar entries with location-aware peak times, reminder cadences, and provider sync state.
- Cross-domain companions. Tara perspective practices, Nisaba cosmology overlays, Veritas grounded explainers, assistant evening narration, and Living Scenes "Sky Briefing" tonight-only briefings.
The canonical contracts live in libs/contracts/src/nyx/index.ts, re-exported
from the contracts package barrel via export * from './nyx'
(libs/contracts/src/index.ts, "Nyx V1 canonical contracts"). The compute and
adapter logic lives in libs/oshun/domain-nyx/src, the BFF route prefix is
/v1/nyx/* (apps/oshun/bff/src/routes/nyx.ts), and the web surfaces are under
apps/oshun/web/src/app/nyx and .../app/domains/nyx.
Surfaces#
Consumer hub and first-class consumer routes#
The consumer hub is at /nyx (the Lilith-design-system NyxRoom). The real web
tree, however, is richer than a single hub: alongside /nyx there are
first-class consumer routes that the older feature copy did not enumerate.
apps/oshun/web/src/app/nyx/ contains, in addition to page.tsx (the room):
| Route | Purpose |
|---|---|
/nyx/events |
Upcoming sky-events list |
/nyx/observation |
Compact observation companion |
/nyx/sky-almanac |
The almanac surface driven by the depth modules |
/nyx/tonight |
The computed "tonight" view (Sun/Moon, phase, rise/set) |
These are consumer surfaces, not power-user tools, and they belong in any honest description of the Nyx surface area.
Power-user deep tools#
The deep tools live under apps/oshun/web/src/app/domains/nyx/. The full set:
analysis, catalogs, coordinates, events, events/[eventId], learning,
moon, neo, observation-log, observation-log-deep, renderer,
satellites, sky-conditions, solar, solar-system, sonification,
star-chart, telescope, time-travel, and widgets. The [eventId] dynamic
route is the per-event detail page; observation-log / observation-log-deep
back the observe-loop; renderer / star-chart / solar-system are visual
surfaces; time-travel and sonification are perspective tools.
A note on mobile#
Earlier architecture copy listed "mobile event cards" as a dedicated Nyx
surface. The code does not bear that out: apps/oshun/mobile/src has no nyx/
screen directory. Nyx appears on mobile only as cross-domain companion
components — for example TaraNyxPerspectiveCompanionCard.tsx — rather than
as a standalone Nyx mobile vertical. Treating "mobile event cards" as a shipped
Nyx surface tree is stale; the honest statement is that Nyx's mobile presence is
currently a companion card embedded in other domains.
The ephemeris engine — the real astronomy core#
The most impressive real asset in Nyx is
libs/oshun/domain-nyx/src/ephemeris.ts (~19.7 KB), a self-contained
astronomical computation module implementing the standard algorithms from Jean
Meeus, Astronomical Algorithms (2nd ed.). Its own header is explicit about why
it exists: an audit found that nyx/tonight had been served by a static
fixture and the web layer fabricated sky data on backend failure. This
module computes the real positions instead, so the "tonight" surface is grounded
in arithmetic rather than a hand-built payload.
Exported functions#
| Symbol | What it computes | Meeus reference |
|---|---|---|
toJulianDay(date) |
Julian Day for a UTC instant | ch. 7 (Gregorian) |
julianCenturies(jd) |
Julian centuries from epoch J2000.0 | — |
sunPosition(jd) |
Apparent geocentric solar position (RA/dec, ecliptic λ, distance in AU) | ch. 25, abridged |
moonPosition(jd) |
Apparent geocentric lunar position (principal periodic terms) | ch. 47 |
moonIllumination(jd) |
Phase angle, illuminated fraction, elongation, phaseName |
ch. 48 |
computeNightSky(date) |
Location-independent sky core (JD, Sun, Moon, and illumination) | — |
greenwichMeanSiderealTime(jd) |
GMST in degrees | eq. 12.4 |
localSiderealTime(jd, longitudeEast) |
LST for an east-positive longitude | ch. 12 |
equatorialToHorizontal(pos, jd, lat, lonEast) |
RA/dec → altitude/azimuth (from north, eastward) | ch. 13 |
riseTransitSet(pos, date, lat, lonEast, h0) |
Rise / transit / set plus circumpolar flags | ch. 15 |
computeTonight(date, location) |
Full observer-relative "tonight" (alt/az and rise/set for Sun and Moon) | — |
The module also exports the STANDARD_ALTITUDE constant — the apparent
disk-center altitudes used for rise/set: sun: -0.8333 (−0°50′, refraction plus
semidiameter), moon: 0.125 (a mean value incorporating horizontal parallax),
and star: -0.5667 (−0°34′ refraction only).
Why it is built this way#
A few design decisions are worth naming because they are deliberate and correctness-bearing:
- Longitude is east-positive throughout, the standard geographic/API convention. Meeus's formulae are west-positive, so the observer-relative conversions invert the sign — a single consistent convention that the tests pin against Meeus's worked examples.
- The lunar series keeps the principal (largest-amplitude) terms — good to a few arc-minutes, "ample for a naked-eye 'tonight' surface." This is a documented approximation with its tradeoff written down, not a stub: the solar terms reproduce Meeus's worked example to ~0.001°.
riseTransitSetuses the sidereal rate, not 360°/day. The code comment explains the subtlety: the target degree difference must be reduced mod 360 before dividing bySIDEREAL_RATE = 360.98564736629, because wrapping the day fraction instead would shift GMST by the rate and desync from the full GMST formula. It returnsalwaysUp/alwaysDownflags for circumpolar and never-rising bodies.
Known-answer tests (this is not a stub)#
libs/oshun/domain-nyx/src/ephemeris.test.ts pins every routine to Meeus's
published worked examples, so any coefficient-transcription error fails loudly:
toJulianDay(2000-01-01T12:00Z)is exactly 2451545.0 (the J2000.0 epoch), and Meeus example 7.a (Sputnik 1, 1957-10-04.81 UT) is 2436116.31.sunPositionfor 1992-10-13 reproduces ecliptic longitude ≈199.909°, declination ≈−7.78507°, distance ≈0.9976 AU (Meeus example 25.b).moonPositionfor 1992-04-12 reproduces ecliptic longitude ≈133.1627° (within 0.02°) and distance ≈368409.7 km (within 120 km) (example 47.a).moonIlluminationfor the same instant gives illuminated fraction ≈0.6786 (Meeus example 48.a), and reportsphaseName === 'new'/'full'at known new and full moons.greenwichMeanSiderealTimematches example 12.a (≈197.693195°), andequatorialToHorizontalreproduces example 13.b (Venus from Washington: altitude ≈15.12°, azimuth ≈248.03° from north).riseTransitSetis self-consistency-tested: a stationary body must sit ath0at its own computed rise and set, and circumpolar/never-rising cases are asserted.
These are real domain-correctness tests against published values; they would fail on random or hardcoded returns.
The Sky Almanac depth modules#
Under libs/oshun/domain-nyx/src/depth/ there are 41 files — twenty depth
modules, their tests, and the depth-page builder — that power the
/domains/nyx/* deep tools and the /nyx/sky-almanac surface. Each module is a
focused astronomical computation that composes the ephemeris core. They were
entirely unmentioned in the older feature copy.
| Module | Notable real exports |
|---|---|
lunar-phase-calendar |
PRINCIPAL_PHASE_ELONGATION, findNextPhaseInstant, lunarPhaseCalendar |
twilight-schedule |
TWILIGHT_ALTITUDE, TwilightWindow, twilightSchedule |
twilight-phase-now |
current twilight band for an observer |
astronomical-night |
astronomicalNight (the truly-dark window) |
equation-of-time |
equationOfTimeMinutes, equationOfTime |
solar-noon |
solarNoon |
solar-terms |
SOLAR_TERMS, solarTerms (the 24 traditional terms) |
solar-season-markers |
equinox/solstice instants |
daylight-extremes |
daylightExtremes (longest/shortest day) |
zodiac-position |
ZODIAC_SIGNS, zodiacPosition, sunZodiacPosition |
planetary-hours |
CHALDEAN_ORDER, WEEKDAY_RULER, planetaryHours |
lunar-nodes |
findNextLunarNode, lunarNodes |
moon-distance |
MOON_MEAN_RADIUS_KM, apparentLunarDiameterArcmin, findNextLunarApsis |
moon-phase-detail |
detailed phase readout |
sun-distance |
Earth–Sun distance over time |
chart-angles |
meanObliquityDeg, chartAngles |
object-transit |
transit of an arbitrary catalog object |
horizon-point / solar-horizon-points / lunar-horizon-points |
horizon azimuths for rise/set |
The depth-page module (depth-page.ts) assembles these into a presentational
structure — NyxDepthRow, NyxDepthSection, NyxDepthPage, and the
buildNyxSkyAlmanacPage builder — which is what the almanac surface renders.
The existence of a dedicated .test.ts next to every module is the diagnostic
that these are real computations, not placeholders.
The Nyx event and observation model#
The event model is the richest contract in the repo. It is built from a
family/type taxonomy, per-family detail schemas, observation windows, prediction
sources, calendar sync, and the logged-observation loop — all with cross-field
superRefine validation enforcing domain correctness.
Event taxonomy: 11 families, 27 types#
SkyEventFamilySchema is an 11-value enum:
meteor-shower · eclipse · conjunction · occultation · transit · comet
aurora · satellite-pass · supermoon · seasonal-marker · deep-sky-peak
SkyEventTypeSchema refines this into 27 concrete types, including
meteor-shower-peak; the eclipse subtypes
solar-eclipse-{partial,total,annular} and
lunar-eclipse-{partial,total,penumbral};
conjunction-planet-{planet,moon,star}; lunar/planetary/asteroid-occultation;
mercury/venus/exoplanet-transit; comet-apparition; aurora-forecast;
iss-pass and bright-satellite-pass; supermoon; the seasonal markers
march-equinox, september-equinox, june-solstice, december-solstice,
cross-quarter; and deep-sky-peak. A getSkyEventFamily(type) helper maps
every type to its family, and SkyEvent's superRefine enforces that the
declared family matches the type's expected family.
Per-family detail schemas#
Each family carries its own detail block (SkyEventDetailsSchema is a record of
nullable per-family details, and requiredDetailsKeyByFamily enforces that the
matching block is present). These are far richer than a flat "type and peak
time" bullet:
| Family | Detail schema | Representative real fields |
|---|---|---|
| meteor-shower | MeteorShowerEventDetailsSchema |
iauCode (regex /^[A-Z0-9]{3}$/), peakZenithalHourlyRate (int 1–1000), radiant (an AngularCoordinate), parentBody, activeStart/EndDate |
| eclipse | EclipseEventDetailsSchema |
body (solar/lunar), subtype, sarosSeries, magnitude (≤2), gamma (−2..2), contactTimes (first/second/maximum/third/fourth) |
| conjunction | ConjunctionEventDetailsSchema |
angularSeparationDegrees (0–10), elongationFromSunDegrees |
| occultation | OccultationEventDetailsSchema |
occultingBody/occultedBody, disappearance/reappearanceTimeUtc, maxDurationSeconds |
| transit | TransitEventDetailsSchema |
kind (mercury/venus/exoplanet), ingress/maximum/egress contactTimes |
| comet | CometEventDetailsSchema |
designation, perihelionDate, predictedMagnitude, ephemerisObjectId |
| aurora | AuroraEventDetailsSchema |
hemispheres (north/south), kpIndexMin/Max (0–9), geomagneticStormLevel (g1–g5), validForecastHours (≤168) |
| satellite-pass | SatellitePassEventDetailsSchema |
spacecraft (iss/bright-satellite), noradId, maxElevationDegrees, passStart/EndAt |
| supermoon | SupermoonEventDetailsSchema |
perigeeDistanceKm (≤500000), illuminationPercent, fullMoonAt |
| seasonal-marker | SeasonalMarkerEventDetailsSchema |
marker, hemisphereContext, traditionalName |
| deep-sky-peak | DeepSkyPeakEventDetailsSchema |
objectType (galaxy/nebula/open-cluster/globular-cluster/asterism), constellation, catalogRefs, recommendedApertureMm |
Beyond the family-match rule, validateSkyEventSubtypeDetails enforces
finer-grained consistency: a solar-eclipse-* type requires
eclipse.body === 'solar', an iss-pass requires
satellitePass.spacecraft === 'iss', and a *-equinox/*-solstice type
requires the seasonal-marker's marker to equal the event type.
The SkyEvent envelope#
SkyEventSchema ties it together: id, slug, type, family, title,
summary, peakTimeUtc, windowStartUtc/windowEndUtc, locationDependent,
visibilityScope (global/regional/local/not-visible), confidenceBand
(high/medium/low/stale/experimental), an array of bodies
(CelestialBodyRef), predictionSources, observationWindows, the per-family
details, and related-content arrays linking the concept graph, Tara content,
and Nisaba content. Its superRefine enforces timestamp ordering
(windowStart ≤ peak ≤ windowEnd), uniqueness of body/source/window ids, window
eventId consistency, and that each window's sourceRefIds actually reference
the event's predictionSources.
Observation windows and the quality band#
ObservationWindowSchema is the per-region visibility forecast for an event. It
carries the site (latitude, longitude, elevation, timezone, region, geohash),
startAt/peakAt/endAt, a qualityBand
(excellent/good/fair/poor/not-visible), a visibility block (visible
flag, limiting reason, peak altitude/azimuth, apparent magnitude),
recommendedEquipment, and a qualityInputs block: bortleClass (1–9),
astronomicalTwilight band, moonIlluminationPercent, cloudCoverPercent,
precipitationProbabilityPercent, windKph, seeing, transparency, and
weatherCondition.
The quality band is not a free label — it is validated. The superRefine
enforces that not-visible windows set visibility.visible === false and carry a
limitingReason, that an invisible window must use the not-visible band, and
critically that an excellent window requires dark enough skies:
bortleClass <= 4, cloudCoverPercent <= 25, and an astronomicalTwilight of
astronomical-twilight or night. This is a real domain rule — you cannot
label a bright, cloudy, twilit sky "excellent."
// excerpt of an ObservationWindow's qualityInputs that would PASS as "excellent"
{
"qualityBand": "excellent",
"qualityInputs": {
"bortleClass": 3, // ≤ 4 required
"cloudCoverPercent": 10, // ≤ 25 required
"astronomicalTwilight": "night", // must be astronomical-twilight or night
},
}
Prediction sources and the family-support matrix#
PredictionSourceKindSchema has 11 kinds — five more than older copy
listed. Each PredictionSourceRef carries kind, displayName, uri,
version, a license block (label/uri/attribution), a freshness block
(issuedAt/validThrough/maxAgeHours/status of
current/stale/superseded), a confidenceContribution, and a fetchedAt —
i.e. version, license, attribution, and freshness, exactly what a provenance
contract should carry. Its superRefine rejects a validThrough that is not
after issuedAt.
The 11 kinds and the families each may back (predictionSourceFamilySupport):
| Source kind | Backs families |
|---|---|
nasa-jpl-horizons |
eclipse, conjunction, occultation, transit, comet, supermoon, seasonal-marker, deep-sky-peak |
nasa-jpl-small-body-db |
comet, occultation |
imo-meteor-calendar |
meteor-shower |
iers-bulletin-a |
eclipse, occultation, transit, seasonal-marker |
noaa-swpc-geomagnetic-forecast |
aurora |
weather-provider |
(none — augments windows, never backs an event) |
bortle-light-pollution-atlas |
(none — augments windows) |
tle-provider |
satellite-pass |
minor-planet-center |
comet, occultation |
usno-astronomical-applications |
eclipse, supermoon, seasonal-marker |
gaia-catalog |
occultation, deep-sky-peak |
This matrix is enforced: SkyEvent.superRefine requires that at least one
prediction source supports the event's family
(predictionSourceSupportsEventType), so an aurora event with only a weather
provider attached is a validation error. The five sources older copy omitted are
nasa-jpl-small-body-db, tle-provider, minor-planet-center,
usno-astronomical-applications, and gaia-catalog.
The observe-loop: LoggedObservation#
Forecasts predict; LoggedObservationSchema records reality. Its module comment
states the intent plainly: "SkyEvent is the predicted phenomenon.
ObservationWindow is the visibility forecast for a region. LoggedObservation
closes the loop: the user reports what they actually saw … so that future
forecasts can incorporate ground-truth and so the user's lifetime observation
journal stays auditable."
A LoggedObservation carries eventId (nullable — you can log an unscheduled
sight), eventType, userId, observedAt, durationMinutes, the site, a
skyCondition (LoggedObservationSkyConditionSchema: bortle, seeing,
transparency, weather, cloud %, moon-phase %), equipment
(LoggedObservationEquipmentSchema: instrument kind, aperture, magnification,
exposure, notes), a qualityRating (the same quality band), a
visibilityScope, free-text notes, attachments
(photo/sketch/audio-note/video), a sharedScope of
private/household/public, and a sourceClient
(mobile-app/web-app/desktop-app/api). Its superRefine even catches an
inconsistency: a not-visible rating with clear-sky cloud cover (< 20%) is
rejected.
This contract is wired to the web observe-loop surfaces
(/domains/nyx/observation-log and observation-log-deep, backed by
NyxObservationLog.tsx). Per the run notes (v1-real-infra-run-2026-06-22.md
§8), local persistence is done via useNyxStore over
localStorage['oshun.nyx'], rendering rows tagged with
data-nyx-observation-event-id. What remains is the honest gap below.
Calendar integration: providers, cadences, sync state#
CalendarProviderSchema is ['google', 'apple', 'outlook', 'ics-file'] — note
the ics-file provider, which older copy omitted. It carries its own
special case: the CalendarSyncEntry.superRefine requires externalCalendarId
for every provider except ics-file (an ICS download has no external calendar
id). ReminderCadenceSchema is
['peak-only', 'evening-of', 'week-before', 'none'].
A CalendarSyncEntry models the per-event calendar row: provider,
external/provider event ids, a syncState
(pending/synced/conflict/disabled/deleted), location-aware peak time
(peakTimeUtc, peakTimeLocal, and an ObservationSite location), a
syncDirection (oshun-to-provider/provider-to-oshun/two-way), reminders,
and conflict reason. Its superRefine enforces that a synced entry has a
providerEventId and lastSyncedAt, that a conflict entry has a
conflictReason, and that reminderCadence === 'none' cannot carry reminders
(and a non-none cadence must carry at least one). Each CalendarReminder has a
cadence (excluding none), a channel
(push/email/sms/external-calendar), an offsetMinutesBeforePeak, and an
enabled flag.
How the data flows#
The BFF exposes the Nyx read/launch surface under /v1/nyx/*
(apps/oshun/bff/src/routes/nyx.ts):
- The domain-adapter family at
/v1/nyx/adapter/*:capabilities,availability,home-cards,continue-items,search,launch,nightly-highlights,object-search,saved-objects,event-reminders,observation-logs, andbridge-moments. /v1/nyx/event-actionsfor save/follow/remind state, and/v1/nyx/perspective/homefor the home perspective section.
Supporting modules sit beside the route (note these live under
apps/oshun/bff/src/ subdirectories, not all under routes/): the per-user
store apps/oshun/bff/src/nyx/nyx-member-stores.ts, the reminder delivery
bridge apps/oshun/bff/src/reminders/nyx-reminder-bridge.ts, the read adapters
apps/oshun/bff/src/adapters/nyx-read-adapters.ts, and the 3D/scene route
apps/oshun/bff/src/isis/nyx-3d-route.ts.
The reminder bridge is a good example of honest scoping. Its header makes clear
it does not create reminders — Nyx's own subsystem does that
(getEventReminders/setEventReminder/toggleEventReminder). The bridge
delivers the ones a user already opted into, through the BFF's in-app reminder
pipeline. Delivery is deduped by a stable per-(user, reminder) session id
(nyx-event:${userId}:${reminder.reminderId}), so re-emitting every tick is a
no-op. It is fail-soft per user: a Nyx read that throws skips that user and
never aborts the sweep. In-app delivery is explicitly additive to Nyx's own
push/email/sms/calendar channels.
A separate, sizeable libs/nyx library tree (~30 subdirectories incl.
catalogs/, constellations/, coordinates/, orbital/, positional/,
realtime/, renderer/, sky-clock/, time-travel/, and client-python/)
holds deeper astronomy machinery. Its libs/nyx/ephemeris package (cache,
generator, minor-bodies, visibility) is the @nyx ephemeris consumed
elsewhere in the platform — e.g. V9's
libs/v9/hephaestus/src/nyx-sky-explorable.ts and
libs/v9/aletheia/src/kernel-evaluators.ts.
Cross-domain companions#
Nyx is a hub for cosmic perspective, so it leans on its neighbors:
- Tara perspective recommendations — awe practices, perspective meditations,
and night-sky-themed reflections (the mobile
TaraNyxPerspectiveCompanionCardis the embedded surface). See Tara — Rituals and Contemplative Practice. - Nisaba cosmology overlays — cultural cosmology references and
cross-tradition mappings (e.g. the Pleiades across cultures), via the
nisaba-cosmology-overlaymodule. See Nisaba — Scholarly Study. - Veritas explainers — grounded explanations of phenomena with source-set citations and retracted-source handling. See Veritas — Grounded Stories and Claims.
- Assistant explainers — voice-mode evening narration for tonight's sky with location-aware visibility framing and accessibility audio description. See Assistant Experience.
- Concept-graph linking — phenomena ↔ named events ↔ teacher references ↔
practice prescriptions, threaded through the
relatedConceptGraphNodeIds,relatedTaraContentIds, andrelatedNisabaContentIdsarrays onSkyEvent. - Living Scenes integration — Nyx ships Sky Briefing Living Scenes: tonight-only briefings tied to the celestial-event clock, with Northern/Southern hemisphere parity. The score's camera/visual focus advances across visible objects as the narrator names them, time-aligned to ±60 ms. Observer location is opt-in per session; the briefing materializes once per location-bucket per night. See Living Scenes — Concept and Customer Promise.
Real vs. planned — the honest state#
This matters, and the docs are candid about it elsewhere; this page keeps that candor.
Real, in-repo, test-pinned:
- The ephemeris engine and its 41 depth modules — genuine Meeus-based computation with known-answer tests against published values. Not a stub by any diagnostic.
- The contract model — the richest in the repo, with cross-field
superRefinevalidation enforcing real astronomical and provenance rules. - Local observation persistence —
useNyxStoreoverlocalStorage['oshun.nyx'].
Partial / boundary-mocked / fail-loud (per V1/AUDIT_2026-06-24.md):
nyx-event-calendar-sync-reminderis partial: two-way provider sync is mocked at the boundary, and reminder dispatch/delivery plus the observation-log back-link remain. Live calendar-provider OAuth sync is not fully wired.nyx-tonight-observationis deep as of 2026-07-02: the browser journey now drives event-detail → observation-log handoff, local-first save,/v1/nyx/observationsPOST/GET read-back after local storage clear, Home Nyx support-card and current-week KPI increment, and the observation-log versus telescope-control equipment-profile boundary.nyx-to-tara-bridgeis URL-only telemetry at present.- Live external data-source ingestion — the actual NASA JPL / IMO / NOAA SWPC fetches — is seam-mocked / fail-loud rather than fully wired. The contracts model the provenance precisely; the live fetchers are planned work, not claimed as shipped.
In short: a real astronomy core and a real, validated contract model, with the external integrations honestly marked partial or planned. See Customer Domains for the architectural framing and ../features.md for the feature hub.
Related#
- Customer Domains — architectural deep-dive for the six verticals, including Nyx
- Tara — Rituals and Contemplative Practice — perspective and awe companions
- Nisaba — Scholarly Study — cosmology overlays and cross-tradition mappings
- Veritas — Grounded Stories and Claims — grounded explainers for phenomena
- Living Scenes — Concept and Customer Promise — the Sky Briefing template
- Assistant Experience — evening sky narration
- Product Surfaces — where Nyx sits in the surface map
- Subsystem Glossary — terminology