# Oya Domain — Technical Specifications

> Technical specifications for the Oya drone and autonomous aerial systems
> domain: the foundation type system, coordinate mathematics, physical
> constants, the error taxonomy, and the six published `@oya/*` packages. Every
> type, schema, enum value, constant, and function documented under
> "Implemented" exists in real source under `libs/oya/`. Sections marked
> `(planned)` trace to `docs/proposals/OYA_DOMAIN_PROPOSAL.md` and TODOS Phase
> 33 and are not yet implemented.

---

This document specifies the Oya domain at field-level precision. It begins with
the technology stack and package structure, then documents `@oya/core`'s
foundation layer (`types.ts`, `constants.ts`, `coordinate-transforms.ts`,
`math-utils.ts`, `validation.ts`, `errors.ts`) in full detail. It then catalogs
the 95 higher-level subsystem modules in `@oya/core` and the five sibling
readiness-evaluator packages. The `(planned)` section at the end describes
expansion that is scoped but not yet implemented.

All 101 `@oya/core` modules were confirmed adversarially clean of stub markers
in the V1-P2-2110 audit (`docs/releases/p2/oya-stub-audit.md`, 2026-05-04).

---

## Technology Stack

The table below describes the full technology stack for all six Oya packages.
Note that `@oya/core` has exactly one runtime dependency — `zod` — keeping the
library lightweight for consumers who only need the type and math layer.

| Layer      | Technology                                               |
| ---------- | -------------------------------------------------------- |
| Language   | TypeScript (ESM, `"type": "module"`)                     |
| Validation | Zod (`catalog:` pinned) — used by `@oya/core` foundation |
| Build      | Nx — `@nx/js:tsc` (core), `nx build` (sub-packages)      |
| Testing    | Vitest (`catalog:`)                                      |
| Bundling   | `tsup` (core ships a `tsup.config.ts`)                   |
| Docs       | TypeDoc (core ships `typedoc.json`)                      |

`@oya/core` is published as `@oya/core` version `0.1.0`, `private: true`, with
`main`/`types` pointing at `./src/index.ts`. Path mapping `@oya/*` →
`libs/oya/*/src/index.ts` is registered in `tsconfig.base.json`.

---

## Package Structure

The Oya domain ships **six** packages under `libs/oya/`. There is no `apps/oya/`
or `services/oya/`.

```
libs/oya/
├── core/                 → @oya/core               (101 source modules)
├── flight-control/       → @oya/flight-control      (readiness evaluator)
├── mission-planning/     → @oya/mission-planning    (readiness evaluator)
├── safety/               → @oya/safety              (readiness evaluator)
├── swarm-intelligence/   → @oya/swarm-intelligence  (swarm primitives + evaluator)
└── telemetry/            → @oya/telemetry           (readiness evaluator)
```

`@oya/core` is by far the largest: 101 TypeScript source modules in
`libs/oya/core/src/` (excluding `*.test.ts`), with an 8,265-line public barrel
`index.ts` that re-exports the named API of every module. The five sibling
packages are each a single-file `src/index.ts` (16–31 KB) with a focused
"readiness evaluator" or "swarm primitive" surface.

This specification documents the **foundation layer** of `@oya/core`
(`types.ts`, `constants.ts`, `coordinate-transforms.ts`, `math-utils.ts`,
`validation.ts`, `errors.ts`) at field-level depth, then catalogs the
higher-level `@oya/core` subsystem modules and the five sibling packages, then
documents the `(planned)` library expansion.

---

## `@oya/core` — Foundation Type System (`types.ts`)

`libs/oya/core/src/types.ts` (642 lines) is the root of the type vocabulary.
Every type below has both a TypeScript type and a corresponding Zod schema. The
TypeScript type is derived from the schema via `z.infer<...>` except where
noted. Zod schemas are the single source of truth: change the schema and the
static type updates automatically.

### Branded ID Types

Fleet management code routinely passes multiple ID categories — drone IDs,
mission IDs, waypoint IDs, swarm IDs — through the same data structures. Without
nominal typing these are all plain strings, and a copy-paste error silently
passes the wrong ID. Branded types make that a compile-time error instead.

IDs are nominal branded strings. The brand helper is:

```typescript
type Brand<T, B extends string> = T & { readonly __brand: B };
```

The four ID types are:

```typescript
export type DroneId = Brand<string, 'DroneId'>;
export type SwarmId = Brand<string, 'SwarmId'>;
export type MissionId = Brand<string, 'MissionId'>;
export type WaypointId = Brand<string, 'WaypointId'>;
```

Each ID has a Zod schema that validates the string against a **UUID v4** pattern
(`UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i`)
and is cast to `z.ZodType<...>` of the branded type:

- `DroneIdSchema` — message `'Invalid DroneId: must be a valid UUID v4'`
- `SwarmIdSchema` — message `'Invalid SwarmId: must be a valid UUID v4'`
- `MissionIdSchema` — message `'Invalid MissionId: must be a valid UUID v4'`
- `WaypointIdSchema` — message `'Invalid WaypointId: must be a valid UUID v4'`

The schemas reject non-UUID strings at service boundaries; the branded type
prevents passing (for example) a `MissionId` where a `DroneId` is expected at
compile time.

### 3D Math Types

All drone navigation and sensor data is three-dimensional. These types form the
mathematical substrate for every computation in Oya. Note that `Position3D` is
geodetic (latitude/longitude/altitude), not Cartesian — this is the standard for
outdoor drone operations where Earth curvature matters.

`Position3D` is **geodetic**, not Cartesian:

```typescript
export const Position3DSchema = z.object({
  latitude: z.number().min(-90).max(90), // decimal degrees
  longitude: z.number().min(-180).max(180), // decimal degrees
  altitude: z.number(), // meters above MSL
});
```

`Velocity3D` — `{ vx, vy, vz }`, each an unconstrained `z.number()` in m/s.
`Acceleration3D` — `{ ax, ay, az }`, each an unconstrained `z.number()` in m/s².

`Orientation` uses **Euler angles in radians**, Tait-Bryan ZYX intrinsic
convention, with bounded ranges:

```typescript
export const OrientationSchema = z.object({
  roll: z.number().min(-Math.PI).max(Math.PI), // [-π, π]
  pitch: z
    .number()
    .min(-Math.PI / 2)
    .max(Math.PI / 2), // [-π/2, π/2]
  yaw: z.number().min(-Math.PI).max(Math.PI), // [-π, π]
});
```

`Quaternion` — `{ w, x, y, z }`, each `z.number().min(-1).max(1)`, with a
`.refine()` that enforces unit norm (`|norm − 1| < 0.01`); the refinement
message is `'Quaternion must be a unit quaternion (norm approximately 1)'`.

`EulerAngles` is a literal alias: `EulerAnglesSchema = OrientationSchema` and
`type EulerAngles = Orientation`. It exists to emphasize the angle
representation at call sites.

### Coordinate Frame Types

Drone navigation involves three distinct spatial reference frames. Each is a
separate TypeScript type so that functions that require, say, a GPS coordinate
cannot accidentally receive a body-frame coordinate.

Three coordinate frames are defined as distinct object types:

- **`GPSCoordinates`** — `{ latitude, longitude, altitude }`, identical shape
  and bounds to `Position3DSchema`. WGS84 datum, altitude above MSL.
- **`LocalCoordinates`** — `{ north, east, down }`, all `z.number()` meters.
  Local North-East-Down (NED) frame relative to an origin; `down` positive =
  below origin.
- **`BodyCoordinates`** — `{ forward, right, down }`, all `z.number()` meters.
  Drone-body frame relative to the center of mass; `forward` positive = nose
  direction, `right` positive = starboard, `down` positive = below.

### Enumerations

All enums are TypeScript string enums (value === key string). They are consumed
in Zod schemas via `z.nativeEnum(...)`, which means Zod will reject any string
not present in the enum at runtime.

**`FlightMode`** — the complete set of flight control modes, from fully manual
to fully autonomous:

| Member         | Value          | Meaning                                           |
| -------------- | -------------- | ------------------------------------------------- |
| `Manual`       | `Manual`       | Full manual control, no stabilization             |
| `Stabilized`   | `Stabilized`   | Attitude stabilized, throttle manual              |
| `Altitude`     | `Altitude`     | Altitude hold, horizontal manual                  |
| `Position`     | `Position`     | Full position hold                                |
| `Mission`      | `Mission`      | Autonomous mission execution                      |
| `ReturnToHome` | `ReturnToHome` | Autonomous return to launch/home point            |
| `Land`         | `Land`         | Autonomous landing                                |
| `Loiter`       | `Loiter`       | Hold position and altitude (circle)               |
| `Guided`       | `Guided`       | External guided control (e.g. companion computer) |
| `Acro`         | `Acro`         | Acrobatic mode, no angle limits                   |

**`DroneState`** — the full operational lifecycle of a drone: `Idle`,
`Preflight`, `Armed`, `TakingOff`, `Flying`, `Hovering`, `Landing`, `Landed`,
`Emergency`, `Disarmed`.

**`ConnectionStatus`** — the state of the communication link between ground
station and drone: `Disconnected`, `Connecting`, `Connected`, `Reconnecting`,
`Lost`, `Error`.

**`AirspaceClass`** — ICAO airspace classification, covering all regulated
categories plus special-use designations: `A`, `B`, `C`, `D`, `E`, `G`,
`Restricted`, `Prohibited`, `Danger`, `TemporaryFlightRestriction`.

**`GimbalMode`** — the four standard gimbal operating modes: `Free`, `Follow`,
`Lock`, `FPV`.

**`GeofenceBehavior`** — what the drone does when it approaches or crosses a
geofence boundary: `Warn`, `ReturnToHome`, `Land`, `Stop`.

**`GeofenceType`** — the supported geofence shapes: `Circle`, `Polygon`.

**`EmergencyType`** — the four emergency response actions ordered from safest to
most drastic: `ReturnToHome`, `Land`, `Hover`, `MotorKill` (motor kill is the
last-resort option).

**`FlightPlanStatus`** — the lifecycle stages of a flight plan: `Draft`,
`Approved`, `Active`, `Completed`, `Cancelled`, `Failed`.

**`WaypointAction`** — actions that can be executed when a drone reaches a
waypoint: `TakePhoto`, `StartVideo`, `StopVideo`, `SetGimbal`, `ChangeSpeed`,
`ChangeAltitude`, `Hover`, `OrbitPOI`.

**`WeatherResistance`** — hardware weather-resistance rating classes: `None`,
`Light`, `Moderate`, `Heavy`, `AllWeather`.

### Composite Types

These are the structured record types that combine the primitives above into the
objects passed across service boundaries and stored in the database.

**`BatteryState`** — the complete battery telemetry record:

```typescript
{
  voltage: number >= 0,                          // volts
  current: number,                               // amps (negative = charging)
  percentage: number 0..100,                     // state of charge
  temperatureCelsius: number -40..85,
  cellCount: integer 1..14,
  timeRemainingSeconds: number >= 0,
  isCharging: boolean,
  cycleCount: integer >= 0,
}
```

**`Telemetry`** — the complete real-time snapshot from one drone. This is the
canonical record for logging, dashboards, and mission replays:

```typescript
{
  droneId: DroneId,                              // DroneIdSchema
  timestamp: ISO-8601 string,                    // z.string().datetime()
  position: Position3D,
  velocity: Velocity3D,
  acceleration: Acceleration3D,
  orientation: Orientation,
  batteryState: BatteryState,
  gpsCoordinates: GPSCoordinates,
  signalStrength: number -120..0,                // dBm, higher is better
  satellites: integer 0..50,
  flightMode: FlightMode,                        // z.nativeEnum
  droneState: DroneState,                        // z.nativeEnum
  connectionStatus: ConnectionStatus,            // z.nativeEnum
}
```

`signalStrength` is in **dBm** (range −120…0), not a 0–100 percentage. There is
no separate `localPosition`, `gpsFix`, `gpsHdop`, or `motorRpms` field on
`Telemetry` — GPS fix quality, HDOP/VDOP, and motor RPM live in the higher-level
telemetry modules (`@oya/telemetry`, `core/src/telemetry-collection.ts`).

**`DroneCapabilities`** — hardware/software capability descriptor: `maxSpeed`
(m/s), `maxAltitude` (m), `maxFlightTime` (minutes), `hasCamera`, `hasGimbal`,
`hasRTK`, `hasThermal`, `hasLidar`, `maxPayloadGrams`, `obstacleAvoidance`
(boolean), `weatherResistance` (`WeatherResistance` enum).

**`CameraSettings`** — `resolution` (string, e.g. `"3840x2160"`), `fps` (integer
1..240), `codec` (string), `fov` (degrees 0..360), `whiteBalance` (Kelvin
0..10000, 0 = auto), `iso` (0..102400, 0 = auto), `shutterSpeed` (fraction
denominator, ≥0, 0 = auto), `format` (string).

**`GimbalState`** — `pan` (degrees −180..180), `tilt` (degrees −90..90), `roll`
(degrees −45..45), `mode` (`GimbalMode`).

**`PayloadInfo`** — `id` (string), `name` (string), `type` (string, e.g.
`"Camera"`, `"Sensor"`, `"Delivery"`, `"Sprayer"`), `weightGrams` (≥0),
`isActive` (boolean).

**`WeatherConditions`** — `windSpeedMs` (≥0), `windDirection` (degrees 0..360, 0
= North), `temperatureCelsius` (−60..60), `humidity` (% 0..100), `pressure` (hPa
870..1084), `visibility` (meters ≥0), `precipitation` (string).

**`GeofenceZone`** — `id`, `name`, `type` (`GeofenceType`), `center`
(`GPSCoordinates`, optional — for circles), `radius` (≥0, optional — for
circles), `vertices` (array of `GPSCoordinates`, min 3, optional — for
polygons), `minAltitude` (number), `maxAltitude` (number), `behavior`
(`GeofenceBehavior`).

**`WaypointActionEntry`** —
`{ action: WaypointAction, params?: Record<string, unknown> }`.

**`Waypoint`** — `id` (`WaypointId`), `position` (`GPSCoordinates`), `speed`
(m/s ≥0), `heading` (degrees 0..360), `holdTimeSeconds` (≥0), `actions` (array
of `WaypointActionEntry`), `radius` (acceptance radius in meters, ≥0).

**`MissionConstraints`** — `maxAltitude`, `minAltitude`, `maxSpeed`,
`minBatteryPercent` (0..100), `maxWindSpeed`, `allowedAirspace` (array of
`AirspaceClass`).

**`MissionMetadata`** — `createdBy`, `createdAt` (ISO-8601), `updatedAt`
(ISO-8601), `description`, `tags` (string array).

**`Mission`** — `id` (`MissionId`), `name` (non-empty string), `waypoints`
(array of `Waypoint`, min 1), `constraints` (`MissionConstraints`), `metadata`
(`MissionMetadata`), `estimatedDuration` (seconds ≥0), `totalDistance` (meters
≥0).

**`FlightPlan`** — links a mission to a drone: `id` (string), `missionId`
(`MissionId`), `droneId` (`DroneId`), `plannedAt`, `estimatedStartTime`,
`estimatedEndTime` (all ISO-8601), `weatherCheck`
(`{ passed: boolean, conditions?: WeatherConditions, warnings: string[] }`),
`airspaceCheck`
(`{ passed: boolean, airspaceClass?: AirspaceClass, authorization?: string, warnings: string[] }`),
`status` (`FlightPlanStatus`).

**`EmergencyProcedure`** — `type` (`EmergencyType`), `priority` (integer 1..10,
1 = highest), `conditions` (string array of triggering conditions),
`altitudeLimit` (meters ≥0, 0 = no limit).

---

## `@oya/core` — Physical Constants (`constants.ts`)

`libs/oya/core/src/constants.ts` (972 lines) defines physical, atmospheric,
hardware, and operational constants used throughout all Oya subsystems. Having
these as named constants rather than inline literals ensures algorithms agree on
the same values and makes them easy to audit for regulatory compliance.

### WGS84 Ellipsoid

These are the Earth ellipsoid model parameters used by all coordinate transform
algorithms. Using WGS84 ensures Oya's geodesy is consistent with GPS receivers
and mapping software worldwide.

`WGS84_A` = `6_378_137.0` m (semi-major axis); `WGS84_INVERSE_F` =
`298.257223563`; `WGS84_F` = `1/WGS84_INVERSE_F`; `WGS84_B` = `WGS84_A·(1−f)`
(semi-minor axis); `WGS84_E2` = `2f − f²` (first eccentricity squared);
`WGS84_E` = `√WGS84_E2`.

### Physical Constants

`STANDARD_GRAVITY` = `9.80665` m/s²; `EARTH_MEAN_RADIUS` = `6_371_008.8` m;
`SPEED_OF_SOUND_SEA_LEVEL` = `340.29` m/s; `EARTH_EQUATORIAL_RADIUS` =
`WGS84_A`; `EARTH_POLAR_RADIUS` = `WGS84_B`.

### Atmospheric Model (International Standard Atmosphere)

The ISA model provides altitude-dependent values for air density, pressure, and
temperature — used by propeller thrust models, range calculations, and fuel-cell
altitude compensation.

Constants: `AIR_DENSITY_SEA_LEVEL` = `1.225` kg/m³;
`STANDARD_PRESSURE_SEA_LEVEL` = `101_325.0` Pa; `STANDARD_TEMPERATURE_SEA_LEVEL`
= `288.15` K; `TEMPERATURE_LAPSE_RATE` = `−0.0065` K/m; `TROPOPAUSE_ALTITUDE` =
`11_000.0` m; `DRY_AIR_GAS_CONSTANT` = `287.058` J/(kg·K);
`DRY_AIR_SPECIFIC_HEAT_RATIO` = `1.4`; `DRY_AIR_MOLAR_MASS` = `0.0289644`
kg/mol; `UNIVERSAL_GAS_CONSTANT` = `8.31446` J/(mol·K).

Three ISA model functions (valid for the troposphere, 0–11 km, clamping their
input to that range):

- `airDensityAtAltitude(altitudeMeters)` → kg/m³, via the barometric formula
  `ρ = ρ₀·(T/T₀)^((−g/(L·R)) − 1)`.
- `atmosphericPressureAtAltitude(altitudeMeters)` → Pa, exponent `−g/(L·R)`.
- `temperatureAtAltitude(altitudeMeters)` → K, linear lapse-rate model.

### Drone Class and Wind Limits

Drone class determines the maximum wind speed at which operations are considered
safe. The `MAX_WIND_SPEED_BY_CLASS` map provides the per-class limit for
automated go/no-go decisions.

`DroneClass` enum: `Micro` (<250 g), `Mini` (250 g–2 kg), `Small` (2–25 kg),
`Medium` (25–150 kg), `Large` (>150 kg). `MAX_WIND_SPEED_BY_CLASS` maps each
class to a sustained-wind limit in m/s: Micro 5.0, Mini 10.0, Small 15.0, Medium
20.0, Large 25.0.

### Regulatory and Operating Limits

`FAA_MAX_ALTITUDE_AGL_FT` = `400`; `FAA_MAX_ALTITUDE_AGL_M` = `121.92`.
Operating temperature limits: consumer `MIN_OPERATING_TEMP_CELSIUS` = `−10`,
`MAX_OPERATING_TEMP_CELSIUS` = `40`; industrial
`MIN_OPERATING_TEMP_INDUSTRIAL_CELSIUS` = `−20`,
`MAX_OPERATING_TEMP_INDUSTRIAL_CELSIUS` = `50`.

### Battery Chemistry Tables

Accurate battery modeling requires chemistry-specific voltage curves and
discharge characteristics. Oya ships frozen constant objects for the three main
drone battery chemistries.

`BATTERY_LIPO`, `BATTERY_LION`, `BATTERY_LIHV` — each a frozen object with
`nominalVoltage`, `fullVoltage`, `minVoltage`, `cutoffVoltage`,
`storageVoltage`, `energyDensityWhKg`, `maxDischargeRateC`, `maxChargeRateC`,
`cycleLife`, and four temperature limits (`max`/`min` × `Discharge`/`Charge`).

The three chemistries in brief: LiPo is 3.7 V nominal / 4.2 V full / 3.3 V min,
180 Wh/kg, 25 C discharge, 300-cycle life; Li-ion is 3.6 V nominal, 250 Wh/kg,
500-cycle life; LiHV (high-voltage lithium polymer) is 3.85 V nominal / 4.35 V
full, 200 Wh/kg.

### Propeller and Motor Models

Real propeller and motor data — sourced from APC/UIUC propeller databases and
manufacturer KV curves — underpins Oya's thrust estimation and battery life
predictions.

`PropellerEfficiencyEntry` interface (`diameterInches`, `pitchInches`,
`thrustCoefficient`, `powerCoefficient`, `figureOfMerit`, `staticThrustGrams`,
`referenceRpm`). `PROPELLER_EFFICIENCY_TABLE` is a 10-entry readonly array
covering 5″ through 28″ propellers, sourced from APC / UIUC propeller data.

`MotorKvEntry` interface (`kvRating`, `propDiameterRange`, `recommendedCells`,
`typicalMaxThrustGrams`, `typicalMaxPowerWatts`, `useCase`). `MOTOR_KV_TABLE` is
an 8-entry readonly array from 2600 KV (3″ micro racing) down to 100 KV (28″+
VTOL/air-taxi propulsion).

### ESC and Control Constants

ESC (Electronic Speed Controller) protocol selection directly affects control
loop latency — a `dshot1200` ESC can respond 1,500× faster than a traditional
`pwm` ESC.

`ESC_RESPONSE_TIMES` — protocol response times in microseconds (`pwm` 20000,
`oneshot125` 250, `oneshot42` 84, `multishot` 25, `dshot150` 106.7, `dshot300`
53.3, `dshot600` 26.7, `dshot1200` 13.3, `bidirectionalDshot` 30).
`ESC_MIN_UPDATE_RATES` — minimum FC loop rates in Hz (`hover` 50, `acrobatic`
400, `autonomous` 100, `racing` 1000).

`PIDGains` interface (`kp`, `ki`, `kd`); `DronePIDProfile` interface (eight
`PIDGains` sets: roll/pitch/yaw rate, roll/pitch/yaw angle, altitude, position).
`PID_DEFAULTS` is a `Record<string, DronePIDProfile>` with five conservative
first-flight tuning profiles: `racing_5inch`, `consumer_photo`, `cinelifter`,
`agriculture`, `vtol`.

`MAX_ANGULAR_VELOCITY` — deg/s limits per mode (`normal`, `sport`, `cinematic`,
`autonomous`), each with `roll`/`pitch`/`yaw` values. `MAX_LINEAR_ACCELERATION`
— m/s² limits per class (`micro`, `consumer`, `industrial`, `heavyLift`,
`cinematic`), each with `horizontal`/`vertical`/`deceleration`.

### Noise and Communication

`NOISE_LIMITS` — regulatory dBA limits with measurement distance and regulation
name (`eu_c0`…`eu_c3`, `us_residential`, `faa_proposed`). `COMMUNICATION_RANGE`
— per-protocol
`rangeMeters`/`latencyMs`/`bandwidthKbps`/`frequencyGHz`/`protocol` for 8 links
(`rc_2_4ghz`, `rc_900mhz`, `video_5_8ghz`, `dji_ocusync`, `cellular_4g`,
`cellular_5g`, `lora`, `mavlink_wifi`).

### Battery, Telemetry, Speed, Geofence, and Navigation Defaults

These defaults are used when an application does not override them, providing
safe conservative starting values that match regulatory limits.

Battery thresholds: `BATTERY_CRITICAL_PERCENT` = `10`, `BATTERY_LOW_PERCENT` =
`20`, `BATTERY_WARNING_PERCENT` = `30`, plus `BATTERY_MAX_TEMP_CELSIUS` = `60`,
`BATTERY_MIN_TEMP_CELSIUS` = `0`, `BATTERY_MIN_CELL_VOLTAGE` = `3.3`,
`BATTERY_NOMINAL_CELL_VOLTAGE` = `3.7`, `BATTERY_FULL_CELL_VOLTAGE` = `4.2`.

Telemetry intervals (ms): `TELEMETRY_INTERVAL_HIGH_FREQ_MS` = `20`,
`_MED_FREQ_MS` = `100`, `_LOW_FREQ_MS` = `1000`, `_GPS_MS` = `200`,
`TELEMETRY_HEARTBEAT_INTERVAL_MS` = `500`, `TELEMETRY_HEARTBEAT_TIMEOUT_MS` =
`3000`.

`SPEED_LIMITS` — a `Record<FlightMode, number>` of m/s caps per mode: Manual 30,
Stabilized 25, Altitude 20, Position 15, Mission 15, ReturnToHome 10, Land 3,
Loiter 0, Guided 20, Acro 35.

Geofence defaults: `DEFAULT_GEOFENCE_RADIUS` = `500` m,
`DEFAULT_GEOFENCE_MAX_ALTITUDE` = `120` m, `DEFAULT_GEOFENCE_MIN_ALTITUDE` =
`0`, `REGULATORY_MAX_ALTITUDE` = `120` m. `DEFAULT_GEOFENCE` is an
`Omit<GeofenceZone, 'id' | 'name'>` circle with `ReturnToHome` behavior.

`DEFAULT_EMERGENCY_PROCEDURES` — a readonly array of four `EmergencyProcedure`
entries ordered by priority: priority 1 `MotorKill`, priority 2 `Land`, priority
3 `ReturnToHome`, priority 4 `Hover`, each with realistic triggering conditions.

Navigation defaults: `DEFAULT_WAYPOINT_RADIUS` = `2.0` m,
`DEFAULT_LOITER_RADIUS` = `30.0` m, `DEFAULT_CRUISE_SPEED` = `10.0` m/s,
`DEFAULT_LANDING_SPEED` = `1.0` m/s, `DEFAULT_TAKEOFF_SPEED` = `2.0` m/s,
`DEFAULT_RTH_ALTITUDE` = `50.0` m, `MIN_SAFE_AGL` = `5.0` m.

Communication: `GCS_SYSTEM_ID` = `255`, `GCS_COMPONENT_ID` = `0`,
`DEFAULT_DRONE_SYSTEM_ID` = `1`, `MAX_SWARM_SIZE` = `256`.

---

## `@oya/core` — Coordinate Transforms (`coordinate-transforms.ts`)

`libs/oya/core/src/coordinate-transforms.ts` (379 lines) implements the frame
transforms and geodesy primitives. Every navigation algorithm in Oya ultimately
calls these functions to move sensor data between the GPS geodetic frame, the
local NED planning frame, and the drone's body frame.

**Angle utilities:** `degreesToRadians(degrees)`, `radiansToDegrees(radians)`,
`normalizeAngle(radians)` (wraps to `[−π, π]`).

**GPS ↔ NED:** `gpsToLocal(gps, origin)` and `localToGps(local, origin)` use a
flat-Earth approximation with WGS84 radii of curvature — the prime-vertical
radius `N = a/√(1 − e²·sin²lat)` and the meridian radius
`(a·(1−e²))/(1 − e²·sin²lat)^1.5`. Accurate to ~1 m within ~10 km of the origin.

**NED ↔ Body:** `localToBody(local, orientation)` and
`bodyToLocal(body, orientation)` apply the ZYX Tait-Bryan rotation matrix (yaw →
pitch → roll) and its transpose. Body convention: forward = +X, right = +Y, down
= +Z.

**Quaternion ↔ Euler:** `quaternionToEuler(q)` returns `EulerAngles` in radians
and explicitly clamps pitch at ±90° to handle gimbal lock;
`eulerToQuaternion( euler)` returns a unit `Quaternion`. Both use the ZYX
convention.

**Distance and bearing:**

- `haversineDistance(a, b)` — great-circle horizontal distance in meters
  (ignores altitude), using `EARTH_MEAN_RADIUS`.
- `distance3D(a, b)` — Haversine horizontal distance combined with altitude
  difference by the Pythagorean theorem.
- `bearing(from, to)` — initial bearing (forward azimuth) in radians, 0 = North,
  normalized to `[0, 2π)`.
- `destinationPoint(start, bearingRad, distanceMeters)` — forward geodesic on a
  sphere; altitude is copied from `start`.

---

## `@oya/core` — Math Utilities (`math-utils.ts`)

`libs/oya/core/src/math-utils.ts` (1,842 lines) is the numeric toolkit used by
every estimator and planner in the domain. It is the largest foundation file and
covers geodesy, linear algebra, interpolation, signal processing, control
theory, and geometry.

**High-precision geodesy:** `vincentyDistance(a, b)` — geodesic distance via the
Vincenty inverse formula, accurate to ~0.5 mm on the WGS84 ellipsoid; falls back
to Haversine for non-converging antipodal points.

**Rotation matrices:** `RotationMatrix` type (a readonly 9-tuple);
`eulerToRotationMatrix`, `rotationMatrixToEuler`, `multiplyRotationMatrices`,
`transposeRotationMatrix`, and the `IDENTITY_MATRIX` constant.

**Interpolation:** `slerp(q0, q1, t)` (quaternion spherical linear
interpolation), `lerp`, `inverseLerp`, `remap`, `clamp`, `cubicSpline` (returns
an interpolating function), `bsplineEval` / `bsplineEvalND`, `bezierQuadratic`,
`bezierCubic`, `bezierCubicND`.

**Signal filters (classes):** `MovingAverageFilter`,
`ExponentialMovingAverageFilter`, `KalmanFilter`, `ExtendedKalmanFilter`,
`ComplementaryFilter`, `MadgwickFilter` (AHRS orientation filter),
`LowPassFilter`, `HighPassFilter`, `BandPassFilter`, `RateLimiter`,
`DeadBandFilter`.

**Controllers:** `PIDConfig` interface; `PIDController` class (with
anti-windup); `CascadedPIDController` class.

**Geometry / collision:** `isInsideCircle`, `BoundingBox3D` interface,
`createBoundingBox`, `isInsideBoundingBox`, `boundingBoxesIntersect`,
`sphereCollision`, `pointInSphere`.

**Time and data integrity:** `TimestampSynchronizer` class; `UnitConversion`
object (imperial ↔ metric helpers); `crc8`, `crc16`, `crc32` checksum functions.

---

## `@oya/core` — Runtime Validation (`validation.ts`)

`libs/oya/core/src/validation.ts` (356 lines) provides higher-level validation
that goes beyond Zod schema parsing. Where `types.ts` schemas enforce structural
correctness (right fields, right types), the functions here enforce semantic
correctness — a battery at 5% is structurally valid but semantically dangerous.

- `validateGPSCoordinates(coords)` → `boolean` — `safeParse` against
  `GPSCoordinatesSchema`.
- `validateBatteryState(battery)` → `string[]` — returns human-readable warnings
  for percentage thresholds (critical / low / warning), temperature out of
  `[BATTERY_MIN_TEMP_CELSIUS, BATTERY_MAX_TEMP_CELSIUS]`, per-cell voltage below
  `BATTERY_MIN_CELL_VOLTAGE`, negative current without the `isCharging` flag,
  and percentage/time-remaining inconsistency.
- `validateFlightPlan(plan, capabilities)` → `string[]` — checks the weather and
  airspace clearance flags, that end time is after start time, that planned
  duration does not exceed `capabilities.maxFlightTime`, and warns on terminal
  plan status (`Failed`/`Cancelled`).
- `validateGeofence(zone)` → `boolean` — verifies altitude ordering, and that
  circle zones have a valid center + positive radius / polygon zones have ≥3
  valid vertices.
- `isWithinGeofence(position, zone)` → `boolean` — altitude-bounds check, then
  Haversine-distance test for circles or ray-casting point-in-polygon for
  polygons (the internal `isPointInPolygon` casts an eastward ray and counts
  edge crossings).
- `validateMission(mission, geofences)` →
  `{ valid: boolean; violations: string[] }` — checks every waypoint for GPS
  validity, against `REGULATORY_MAX_ALTITUDE`, against the mission's own
  altitude/speed constraints, and against every supplied geofence; also verifies
  non-zero total distance for multi-waypoint missions and non-zero estimated
  duration.

---

## `@oya/core` — Error Taxonomy (`errors.ts`)

`libs/oya/core/src/errors.ts` (1,702 lines) defines the structured error system.
Every error in Oya carries a machine-readable code, a severity level, recovery
suggestions, and optional drone/swarm context — rather than plain `Error`
strings that a catch block can only log and discard.

**`ErrorSeverity`** enum — `Info`, `Warning`, `Error`, `Critical`, `Fatal`.

**`OyaError`** — base class extending `Error`. Carries a structured `code`
(`OyaErrorCode`), `severity`, ISO-8601 `timestamp`, optional `droneId`,
`recoverySuggestions` (string array), and a `details` record. Methods:
`serialize()` → `SerializedOyaError`, static `deserialize(data)`, and the
`isEmergency` getter (true for `Critical` or `Fatal`).

`OyaErrorCode` is a template-literal union of 24 prefixes —
`OYA_CONN_${string}`, `OYA_AUTH_…`, `OYA_CMD_…`, `OYA_TIMEOUT_…`, `OYA_BATT_…`,
`OYA_GPS_…`, `OYA_IMU_…`, `OYA_MOTOR_…`, `OYA_ESC_…`, `OYA_COMPASS_…`,
`OYA_BARO_…`, `OYA_CAM_…`, `OYA_GIMBAL_…`, `OYA_GEOFENCE_…`, `OYA_ALT_…`,
`OYA_SPEED_…`, `OYA_COLLISION_…`, `OYA_WEATHER_…`, `OYA_MISSION_…`,
`OYA_SWARM_…`, `OYA_COMM_…`, `OYA_PAYLOAD_…`, `OYA_REG_…`, `OYA_EMERGENCY_…`.

**Error subclasses** (each derives severity from its sub-type and ships
context-aware `recoverySuggestions`). The table below documents every subclass
and the discriminant union it carries:

| Class                 | Discriminant sub-type union                                                                                                                                                                                           |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ConnectionError`     | carries `connectionStatus`, `signalStrength`, `reconnectAttempts`                                                                                                                                                     |
| `AuthenticationError` | SDK/API auth failure                                                                                                                                                                                                  |
| `CommandError`        | `CommandRejectionReason` — `INVALID_STATE` / `NOT_ARMED` / `GEOFENCE_VIOLATION` / `BATTERY_TOO_LOW` / `WEATHER_UNSAFE` / `NO_GPS_FIX` / `MOTORS_BUSY` / `PERMISSION_DENIED` / `INVALID_PARAMETERS` / `HARDWARE_FAULT` |
| `TimeoutError`        | carries `operation`, `timeoutMs`                                                                                                                                                                                      |
| `BatteryError`        | `BatteryErrorType` — `LOW` / `CRITICAL` / `FAILURE` / `OVERTEMP` / `UNDERTEMP` / `CELL_IMBALANCE` / `SWOLLEN`                                                                                                         |
| `GPSError`            | `GPSErrorType` — `NO_FIX` / `POOR_ACCURACY` / `SPOOFING_DETECTED` / `JAMMING_DETECTED` / `ANTENNA_FAULT`                                                                                                              |
| `IMUError`            | `IMUErrorType` — `CALIBRATION_NEEDED` / `DRIFT_DETECTED` / `FAILURE` / `VIBRATION_EXCESSIVE` / `CLIPPING`                                                                                                             |
| `MotorError`          | `MotorErrorType` — `OVERHEAT` / `BLOCKED` / `FAILURE` / `DESYNC` / `OVERCURRENT`; carries `motorIndex`                                                                                                                |
| `ESCError`            | `ESCErrorType` — `OVERHEAT` / `OVERCURRENT` / `COMMUNICATION_FAILURE` / `FIRMWARE_ERROR`; carries `motorIndex`                                                                                                        |
| `CompassError`        | `CompassErrorType` — `INTERFERENCE` / `CALIBRATION_NEEDED` / `FAILURE` / `INCONSISTENCY`                                                                                                                              |
| `BarometerError`      | `BarometerErrorType` — `FAILURE` / `DRIFT` / `BLOCKED` / `NOISE_EXCESSIVE`                                                                                                                                            |
| `CameraError`         | `CameraErrorType` — `CONNECTION_LOST` / `STORAGE_FULL` / `ENCODING_FAILURE` / `OVERHEATING` / `LENS_OBSTRUCTION`                                                                                                      |
| `GimbalError`         | `GimbalErrorType` — `CALIBRATION_NEEDED` / `MOTOR_FAILURE` / `LIMIT_REACHED` / `OVERLOAD` / `COMMUNICATION_LOST`                                                                                                      |
| `GeofenceViolation`   | `GeofenceViolationType` — `BREACH` / `APPROACHING_BOUNDARY` / `ALTITUDE_EXCEEDED` / `ALTITUDE_TOO_LOW`; carries `zoneId`, `zoneName`, `currentPosition`, `distanceToFenceMeters`                                      |
| `AltitudeLimitError`  | `limitType` `MAX` / `MIN`; carries `currentAltitude`, `limitAltitude`                                                                                                                                                 |
| `SpeedLimitError`     | carries `currentSpeed`, `maxSpeed`                                                                                                                                                                                    |
| `CollisionWarning`    | carries `distanceMeters`, `direction` (`{azimuth, elevation}`), `source` (`ObstacleSource` — `LIDAR` / `STEREO_CAMERA` / `ULTRASONIC` / `TOF` / `RADAR` / `ADS_B`), `closingSpeedMs`                                  |
| `WeatherError`        | `WeatherErrorType` — `HIGH_WIND` / `LOW_TEMPERATURE` / `HIGH_TEMPERATURE` / `PRECIPITATION` / `LOW_VISIBILITY` / `LIGHTNING`                                                                                          |
| `MissionError`        | `MissionErrorType` — `INVALID_WAYPOINT` / `UNREACHABLE` / `PLANNING_FAILURE` / `EXECUTION_FAILURE` / `ABORT`; carries `missionId`, `waypointIndex`                                                                    |
| `SwarmError`          | `SwarmErrorType` — `COORDINATION_FAILURE` / `LOST_DRONE` / `COLLISION_RISK` / `FORMATION_BREAK` / `COMMUNICATION_FAILURE`; carries `swarmId`, `affectedDroneIds`                                                      |
| `CommunicationError`  | `CommunicationErrorType` — `SIGNAL_LOSS` / `INTERFERENCE` / `BANDWIDTH_EXCEEDED` / `PROTOCOL_ERROR` / `ENCRYPTION_FAILURE`                                                                                            |
| `PayloadError`        | `PayloadErrorType` — `OVERWEIGHT` / `IMBALANCED` / `CONNECTION_LOST` / `MALFUNCTION` / `RELEASE_FAILURE`; carries `payloadId`                                                                                         |
| `RegulatoryError`     | `RegulatoryErrorType` — `AIRSPACE_VIOLATION` / `NO_AUTHORIZATION` / `FLIGHT_RESTRICTION` / `ID_BROADCAST_FAILURE`; carries `airspaceClass`                                                                            |
| `EmergencyError`      | always `Fatal`; carries `emergencyType` and `suggestedProcedure` (both `EmergencyType`)                                                                                                                               |

**Cross-cutting error functions:**

- `getRecoverySuggestions(error, context?)` — augments an error's suggestions
  using runtime context (`batteryPercent`, `altitude`, `distanceFromHome`,
  `isAutonomous`).
- `SwarmErrorSummary` interface and
  `aggregateSwarmErrors(errors, totalDrones, abortThresholdPercent = 25)` —
  aggregates errors across a swarm, grouping by severity and by code-prefix
  category, and computes a `shouldAbort` flag (true if any fatal error, or if
  the fraction of drones with critical errors meets the abort threshold).
- `ERROR_SEVERITY_TO_LOG_LEVEL` — maps `ErrorSeverity` to a logger level string.
- `formatErrorForLogging(error)` — produces a structured JSON-Lines log entry
  (`logger: 'oya.drone'`).
- `createErrorTelemetryPayload(errors, maxErrors = 50)` — sorts errors
  most-severe-first and serializes up to `maxErrors` of them for transmission.

---

## `@oya/core` — Subsystem Modules

Beyond the foundation, `@oya/core` contains 95 further subsystem modules. They
are real, fully-implemented TypeScript (verified clean by the V1-P2-2110
stub-indicator audit, `docs/releases/p2/oya-stub-audit.md`, 2026-05-04). Each
ships a matching `*.test.ts`. They are re-exported by name through
`core/src/index.ts`. The sections below group them by domain area.

### Kinematics, Dynamics, and Flight Control

The flight control stack runs from low-level 6-DOF rigid body dynamics and motor
mixing all the way up to trajectory-level path planning and gimbal coordination.

- `kinematics.ts` — `Vec3`/`Quat` types and a vector/quaternion algebra (`vec3`,
  `vec3Add`, `vec3Sub`, `vec3Scale`, `vec3Dot`, `vec3Cross`, `vec3Mag`,
  `vec3Normalize`, `quatIdentity`, `quatNormalize`, `quatMultiply`, …) plus
  rigid-body dynamics and rotor-mixing models.
- `physics-simulation.ts` — physics-based flight simulation.
- `attitude-control.ts` — cascaded PID and SO(3) geometric attitude control.
- `velocity-position-control.ts` — velocity and position control loops.
- `path-planning.ts` — trajectory generation (minimum-snap, Dubins, B-spline
  smoothing).
- `obstacle-avoidance.ts` — potential-field and occupancy-grid avoidance.
- `gimbal-control.ts`, `camera-gimbal-api.ts` — 3-axis gimbal stabilization and
  the camera/gimbal command API.
- `shot-planning.ts`, `cinematography-trajectory.ts` — cinematic shot library
  and keyframed flight-path generation.

### Sensors, Navigation, and State Estimation

State estimation combines data from multiple sensors — each with different
update rates, failure modes, and accuracy profiles — into a single unified
estimate of position, velocity, and attitude.

- `gps-navigation.ts` — GNSS navigation, RTK corrections, u-blox UBX parsing.
- `imu-orientation.ts` — IMU fusion (Madgwick / Mahony AHRS).
- `lidar-integration.ts`, `depth-sensors.ts` — LiDAR point clouds and depth
  sensing.
- `multi-sensor-fusion.ts` — EKF fusion of GPS / IMU / barometer / optical flow
  / UWB.
- `indoor-positioning.ts` — GPS-denied indoor positioning.
- `visual-slam.ts`, `advanced-slam-vio.ts`, `event-camera-navigation.ts` — SLAM
  and visual-inertial odometry.
- `ikd-tree.ts`, `gtsam-bridge.ts`, `scene-change-detector.ts` — spatial index,
  factor-graph bridge, and scene-change detection helpers.
- `coordinate-transforms.ts`, `math-utils.ts` — see foundation sections above.

### Computer Vision and AI

The vision pipeline covers detection, pose estimation, segmentation, tracking,
and edge inference — the full stack required for applications from search-and-
rescue to precision agriculture.

- Detection: `yolov12-integration.ts`, `rtdetr-integration.ts`,
  `uavdetr-integration.ts`.
- Pose / human analysis: `pose-detection-2d.ts`, `advanced-pose-estimation.ts`,
  `detrpose-integration.ts`, `sapiens-integration.ts`,
  `body-reconstruction-3d.ts`, `form-analysis.ts`, `human-aware-navigation.ts`.
- Segmentation / tracking: `sam-integration.ts`, `subject-tracking.ts`,
  `temporal-tracking.ts`, `multi-view-fusion.ts`,
  `multi-camera-coordination.ts`.
- Models / inference: `pretrained-models.ts`, `model-optimization.ts`,
  `model-inference.ts`, `edge-deployment.ts`.

### Swarm Coordination

Swarm modules add distributed intelligence on top of the single-drone control
primitives — from leader election and formation geometry to graph-neural-network
collective behavior and inter-drone mesh communication.

- `swarm-api.ts`, `swarm-coordination.ts`, `formation-flying.ts` — swarm API,
  coordination, and formation flight.
- `consensus-algorithms.ts`, `gnn-swarm-intelligence.ts` — distributed consensus
  and graph-neural-network swarm intelligence.
- `task-allocation.ts` — distributed task assignment (contract-net / Hungarian).
- `swarm-collision-avoidance.ts` — ORCA multi-agent avoidance.
- `inter-drone-communication.ts` — multi-agent MAVLink messaging and mesh
  networking.

### Mission, Geofencing, and Safety

Mission execution is a state machine that takes a validated `Mission` object and
drives a drone from waypoint to waypoint while monitoring geofences, battery
state, and emergency conditions at each step.

- `mission-execution.ts` — the mission state machine: `MissionUploader`,
  `MissionValidator` (with `ValidationSeverity` / `ValidationIssue` /
  `MissionValidationResult`), `WaypointSequencer`,
  `WaypointNavigationStateMachine` (`NavigationState` enum),
  `WaypointAcceptanceChecker`, `StraightLineNavigation`,
  `CurvedWaypointTransition`, `StopAndTurnMode`, `FlythroughMode`, and the
  `totalMissionDistance` helper.
- `geofencing.ts` — geofence shapes and enforcement: `PolygonGeofence`,
  `CircularGeofence`, `CylindricalGeofence`, `CorridorGeofence`,
  `AltitudeFloorCeiling`, `NoFlyZoneManager`, `DynamicGeofence`,
  `GeofenceImporter`, `MultiZoneManager`, `NestedGeofenceManager`,
  `BreachDetector` (`BreachSeverity`), `GraduatedWarningSystem`,
  `ContainmentActionExecutor` (`ContainmentAction`), `ReEntryDetector`,
  `GeofenceVisualizer`.
- `emergency-procedures.ts`, `health-check.ts` — failsafe procedures and
  pre-flight health checks.

### Protocols, Autopilots, and Simulation

This group covers the wire protocol layer (MAVLink v2), the autopilot
integration layers (PX4, ArduPilot), hardware abstraction (DJI, Pixhawk-family,
2025-generation compute boards), and the simulation backends.

- `mavlink-protocol.ts` — MAVLink v2 (heartbeat, COMMAND_LONG/INT, mission,
  parameter, FTP, logging, camera, gimbal v2 protocols; message signing;
  router).
- `protocol-sender.ts` — protocol message transport helper.
- `px4-autopilot.ts`, `ardupilot.ts` — PX4 and ArduPilot integration layers.
- `dji-sdk.ts`, `generic-hardware.ts`, `hardware-platforms-2025.ts` — DJI SDK,
  generic autopilot hardware abstraction, and 2025-generation hardware profiles.
- `camera-systems.ts`, `camera-discovery-providers.ts` — camera subsystem and
  discovery.
- `audio-systems.ts`, `whisper-asr-bridge.ts` — onboard audio and an ASR bridge.
- Simulation: `sitl-integration-framework.ts`, `gazebo-integration.ts`,
  `airsim-integration.ts`, `jmavsim-integration.ts`,
  `modern-simulation-platforms.ts`.

### Regulatory, Power, Enterprise, and Data

The remaining modules cover the business and operational layers: regulatory
compliance, next-generation power systems, enterprise fleet management, spatial
data, observability, logging, and the database access layer.

- `regulatory-compliance.ts`, `faa-bvlos-compliance.ts` — airspace / LAANC /
  Remote ID / BVLOS compliance.
- `nextgen-power-systems.ts` — solid-state BMS, hydrogen fuel cells, energy
  harvesting, charging infrastructure.
- `enterprise-platform.ts` — DaaS, fleet management, UTM, drone-in-a-box, AI
  mission agent, and industry-specific solution templates.
- `gaussian-splatting-integration.ts`, `spatial-data.ts` — photogrammetry into
  3DGS, and GeoJSON spatial data management.
- `telemetry-collection.ts`, `timeseries-storage.ts` — telemetry aggregation and
  time-series storage.
- `flight-logging.ts`, `post-flight-analysis.ts`, `observability.ts` — flight
  logs, post-flight analysis, and metrics.
- `realtime-streaming.ts`, `video-streaming.ts` — low-latency telemetry and
  video streaming.
- `database-schema.ts`, `data-access-layer.ts` — typed DB schema and the
  repository layer.
- `natural-language-control.ts` — natural-language drone/mission control.

### SDK and Cross-Domain Integration

The SDK layer is the consumer-facing surface. The cross-domain adapter modules
define the typed boundaries toward other Oshun domains; the concrete runtime
wiring to event-bus, storage, and metrics is part of the planned expansion.

- `sdk-core.ts` — the SDK kernel: `SdkConfig`, `DEFAULT_SDK_CONFIG`, `SdkCore`,
  `ConnectionManager`, `SdkAuthenticator` (`SdkAuthMethod` —
  `apikey`/`token`/`certificate`/`none`), `SdkEventBus`, plus middleware,
  plugin, feature-flag, health, and diagnostic types.
- `drone-control-api.ts`, `telemetry-api.ts` — high-level command API and the
  typed telemetry subscription stream.
- Cross-domain adapters: `isis-integration.ts`, `lilith-integration.ts`,
  `sophia-integration.ts`, `aja-integration.ts`, `aphrodite-integration.ts`,
  `yemaya-integration.ts`, `bellona-integration.ts`.

---

## Sibling Package — `@oya/flight-control`

`libs/oya/flight-control/src/index.ts` (16 KB) is a **flight-control readiness
evaluator**: it scores whether a fleet's flight controllers are production-ready
for remote drone operation. It is not the low-level control loop itself (that
lives in `@oya/core`'s `attitude-control.ts` / `velocity-position-control.ts`).
The evaluator produces a structured report with coverage ratios and `blocking`
or `warning` issues that a pre-flight checklist UI or CI gate can consume
directly.

**Status / readiness types.** `OYA_FLIGHT_CONTROL_STATUS` constant
(`READY`/`NEEDS_ATTENTION`/`BLOCKED`) with derived `OyaFlightControlStatus`;
`OyaControlReadiness` = `'ready' | 'needs-attention' | 'blocked'`.
`OyaFlightMode` =
`'manual' | 'stabilized' | 'altitude' | 'position' | 'mission' | 'guided' | 'loiter' | 'rth' | 'land'`.
`OyaGpsFix` = `'none' | '2d' | '3d' | 'dgps' | 'rtk_float' | 'rtk_fixed'`.
`OyaVec3` = `{ x, y, z }` readonly.

**Model interfaces.** `OyaFlightControlLoop` (per-loop tuning gates:
`updateRateHz` vs `targetUpdateRateHz`, `rmsError` vs `maxAllowedRmsError`,
`saturationPct` vs `maxAllowedSaturationPct`, `failsafeHookReady`);
`OyaFlightNavigationRoute` (planner/obstacle/GPS/velocity/position-hold/
replanning/geofence-clamp readiness flags and a cross-track error gate);
`OyaFlightControllerNode` (a single drone's controller: `flightMode`, `armed`,
firmware/parameter sync, GPS fix, sensor health, motor health, battery, and the
three nested loops `attitudeLoop`/`velocityLoop`/`positionLoop` plus
`navigation`); `OyaFlightControlScenario` (a labelled set of controllers with
minimum coverage ratios).

**Evaluation outputs.** `OyaFlightControlIssue` (typed `issueType` —
`controller-missing` / `low-level-low` / `stabilization-low` / `navigation-low`
/ `safety-low` / `battery-low` / `required-controller-blocked` — with
`'warning' | 'blocking'` severity); `OyaFlightControllerEvaluation`,
`OyaFlightControlScenarioEvaluation`, `OyaFlightControlReport`,
`OyaFlightControlRunResult`.

**Functions.** `evaluateOyaFlightControlScenario(scenario)`,
`createOyaFlightControlReport(scenarios)`, `runOyaFlightControl(scenarios)`. The
evaluator computes four coverage ratios per controller — low-level (arming,
command-ack, firmware, parameter sync, GPS fix ≠ `none`/`2d`, ≥10 satellites,
IMU/baro/mag health, motor health), stabilization (the three loops within
tolerance plus a non-manual flight mode), navigation, and safety — escalates
issues to `blocking` when the scenario and controller are both `required`, and
rolls scenario results into a report with averaged ratios, a `status`, and a
deduplicated `nextActions` list. The report also embeds a JSON `exportPayload`.

---

## Sibling Package — `@oya/telemetry`

`libs/oya/telemetry/src/index.ts` (18 KB) is a **telemetry readiness
evaluator**: it scores whether real-time drone telemetry feeds are
production-ready for remote capture. It evaluates six coverage dimensions per
feed and aggregates them into a single typed report.

**Status / readiness.** `OYA_TELEMETRY_STATUS` constant + `OyaTelemetryStatus`;
`OyaTelemetryReadiness`; `OyaGpsFix` (same six-value union as
`@oya/flight-control`).

**Snapshot interfaces.** `OyaTelemetryBatterySnapshot` (voltage, current,
percent remaining vs minimum, temperature vs max, per-cell voltages, cell
imbalance, estimated flight time vs minimum); `OyaTelemetryGpsSnapshot`
(`fixType`, satellites vs minimum, HDOP/VDOP vs maxima, RTK availability,
position validity); `OyaTelemetryImuSnapshot` (accel/gyro/mag health, vibration
RMS vs max, temperature vs max); `OyaTelemetryMotorSnapshot` (`motorId`, RPM vs
expected minimum, ESC temperature, current, `faultCode`);
`OyaTelemetryTemperatureSnapshot` (flight-controller / payload / airframe
temperatures vs maxima); `OyaDroneTelemetryFeed` (one drone's feed:
latency/sample-rate/link-quality/timecode/redundancy gates plus the five nested
snapshots).

**Evaluation outputs.** `OyaTelemetryScenario`, `OyaTelemetryIssue` (`issueType`
— `feed-missing` / `realtime-low` / `battery-low` / `gps-low` / `imu-low` /
`motor-low` / `temperature-low` / `required-feed-blocked`),
`OyaTelemetryFeedEvaluation`, `OyaTelemetryScenarioEvaluation`,
`OyaTelemetryReport`, `OyaTelemetryRunResult`.

**Function.** `runOyaTelemetry(scenarios)` — evaluates six coverage ratios per
feed (realtime, battery, GPS, IMU, motor, temperature), escalates blocking
issues for required feeds, and produces an aggregate report with averaged
ratios, status, `nextActions`, and a JSON `exportPayload`.

---

## Sibling Package — `@oya/mission-planning`

`libs/oya/mission-planning/src/index.ts` (18 KB) is a **mission-planning
readiness evaluator** for pre-programmed waypoints, actions, triggers, and
mission-upload gates. It answers the question: is this mission plan ready to
upload and execute?

**Status / readiness.** `OYA_MISSION_PLANNING_STATUS` +
`OyaMissionPlanningStatus`; `OyaMissionPlanningReadiness`.
`OyaMissionActionType` and `OyaMissionTriggerType` are string-literal unions
enumerating mission action and trigger kinds.

**Model interfaces.** `OyaMissionPosition`; `OyaMissionWaypoint`;
`OyaMissionAction`; `OyaMissionTrigger`; `OyaMissionPlan` (a plan with
waypoints, actions, triggers and upload gates); `OyaMissionPlanningScenario`.

**Evaluation outputs.** `OyaMissionPlanningIssue`, `OyaMissionPlanEvaluation`,
`OyaMissionPlanningScenarioEvaluation`, `OyaMissionPlanningReport`,
`OyaMissionPlanningRunResult`.

**Function.** `runOyaMissionPlanning(scenarios)` — evaluates mission plans for
planning/upload readiness and produces an aggregate report.

---

## Sibling Package — `@oya/safety`

`libs/oya/safety/src/index.ts` (16 KB) is a **safety readiness evaluator** for
geofencing, emergency procedures, and regulatory compliance. It evaluates
whether a drone's complete safety posture — geofence rules, emergency
procedures, and regulatory framework compliance — meets the required standard
before a flight is authorized.

**Status / readiness.** `OYA_SAFETY_STATUS` + `OyaSafetyStatus`;
`OyaSafetyReadiness`. `OyaEmergencyProcedureType` is a string-literal union of
emergency-procedure kinds. `OyaRegulatoryFramework` =
`'faa-part-107' | 'easa-open' | 'caa' | 'local-film-permit'`.

**Model interfaces.** `OyaGeofenceRule`; `OyaEmergencyProcedure`;
`OyaRegulatoryComplianceGate`; `OyaSafetyCase` (a drone's combined geofence,
emergency-procedure, and regulatory posture); `OyaSafetyScenario`.

**Evaluation outputs.** `OyaSafetyIssue`, `OyaSafetyCaseEvaluation`,
`OyaSafetyScenarioEvaluation`, `OyaSafetyReport`, `OyaSafetyRunResult`.

**Function.** `runOyaSafety(scenarios)` — evaluates safety cases for geofence /
emergency / regulatory readiness and produces an aggregate report.

---

## Sibling Package — `@oya/swarm-intelligence`

`libs/oya/swarm-intelligence/src/index.ts` (31 KB) is the largest sibling
package. It has two distinct layers: concrete **swarm-control primitives** that
are used directly in application code, and a **swarm-intelligence readiness
evaluator** that scores whether a swarm configuration is production-ready for
autonomous multi-drone operation.

### Swarm-Control Primitives

These are the building blocks for implementing swarm behavior: leader election,
formation geometry, task allocation, and kinematic simulation.

String-literal unions:

- `AllocationStrategy` — `nearest` / `load_balanced` / `capability_match` /
  `priority`.
- `ElectionStrategy` — `highest_battery` / `closest_to_center` / `manual` /
  `round_robin`.
- `FormationType` — `line` / `v_formation` / `grid` / `circle` / `diamond` /
  `custom`.
- `MsgPriority` — `low` / `normal` / `high` / `critical`.

Interfaces: `SwarmPos` (`{ x, y, z }`), `SwarmDroneInfo` (`id`, `role` —
`leader`/`follower`/`scout`/`relay`/`standby` — `position`, `batteryPct`,
`online`, `capabilities`), `SwarmConfig` (`name`, `maxDrones`, `separationM`,
`communicationRangeM`, `formationType`, `electionStrategy`), `FormationSlot`,
`SwarmMissionWaypoint`, `SwarmSimResult`, `SwarmTask` (`id`, `description`,
`assignedTo`, `priority`, `status` — `pending`/`assigned`/`in_progress`/
`completed`/`failed` — `position`).

Implemented control classes:

- `SwarmCreationAPI` — allocates swarm IDs.
- `DroneRegistrationAPI` — a drone registry keyed by drone ID.
- `LeaderElectionAPI` — implements all four `ElectionStrategy` variants:
  highest-battery reduce, closest-to-centroid, round-robin, and manual fallback.
- `FormationControlAPI` — computes per-drone `FormationSlot` offsets with real
  geometry for line, V, grid, circle, diamond, and custom formations.
- `TaskAllocationAPI` — creates `SwarmTask`s and allocates them by
  nearest-by-distance or first-available strategy.
- `SwarmMissionAPI` — loads and starts a waypoint mission across the swarm.
- `SwarmSimulationAPI` — steps a proportional-pursuit kinematic simulation,
  counts pairwise collisions, and reports formation accuracy.

### Swarm-Intelligence Readiness Evaluator

`OYA_SWARM_INTELLIGENCE_STATUS` + `OyaSwarmIntelligenceStatus`;
`OyaSwarmReadiness`; `OyaSwarmMissionSegmentPriority` =
`Extract<MsgPriority, 'normal' | 'high' | 'critical'>`. Interfaces:
`OyaSwarmIntelligenceDrone`, `OyaSwarmFormationPlan`, `OyaSwarmMissionSegment`,
`OyaSwarmIntelligenceScenario`, `OyaSwarmIntelligenceIssue`,
`OyaSwarmCommandModel`, `OyaSwarmIntelligenceEvaluation`,
`OyaSwarmIntelligenceReport`, `OyaSwarmIntelligenceRunResult`.

Functions: `buildOyaSwarmCommandModel(...)`,
`evaluateOyaSwarmIntelligenceScenario(scenario)`,
`createOyaSwarmIntelligenceReport(scenarios)`,
`runOyaSwarmIntelligence(scenarios)` — evaluates whether a swarm's formation
plans, mission segments, and command model are ready for autonomous multi-drone
operation.

---

## Integration Points

`@oya/core` ships TypeScript cross-domain adapter modules (`*-integration.ts`)
that define the typed boundary toward other Oshun domains. The boundary exists
because Oya owns aerial autonomy primitives and not the downstream processing.
For example, Oya captures geotagged imagery but Maya owns 3DGS reconstruction;
Oya estimates human poses from footage but Aja owns motion-capture archiving.
The adapter modules define the exact types passed at each boundary.

| Module                              | Direction       | Purpose                                                              |
| ----------------------------------- | --------------- | -------------------------------------------------------------------- |
| `gaussian-splatting-integration.ts` | oya → maya      | Feed geotagged drone capture into the 3D Gaussian Splatting pipeline |
| `isis-integration.ts`               | oya → isis      | Route generation jobs (orthophoto / 3D-asset) to Isis                |
| `lilith-integration.ts`             | oya → lilith    | Natural-language mission intent from the Lilith layer                |
| `sophia-integration.ts`             | oya → sophia    | Regulatory / weather / equipment knowledge into mission planning     |
| `aja-integration.ts`                | oya → aja       | Pose-estimation and motion-capture data handoff                      |
| `aphrodite-integration.ts`          | oya → aphrodite | Live aerial video streaming into the creator platform                |
| `yemaya-integration.ts`             | oya → yemaya    | Mission/capture metadata in the creative studio                      |
| `bellona-integration.ts`            | oya → bellona   | Drone inspection data into the build/quality pipeline                |

`observability.ts`, `flight-logging.ts`, `database-schema.ts`, and
`data-access-layer.ts` define the typed surfaces for metrics export, structured
logging, and persistence. The concrete platform-level wiring to
`@oshun/storage`, `@oshun/event-bus`, `@oshun/metrics`, and `@oshun/database` is
part of the planned expansion below.

---

## Planned Library Expansion `(planned)`

The following are **not implemented**. They trace to
`docs/proposals/OYA_DOMAIN_PROPOSAL.md` and TODOS Phase 33 ("Oya — AI-Controlled
Drone & Swarm Management Platform"), which scopes Oya as a platform capability
domain consumed by Lilith, Yemaya, and Aphrodite.

- **Application / service tier `(planned)`** — there is currently no `apps/oya/`
  or `services/oya/`. A ground control station, fleet dashboard, and mission
  planner front-end, plus any long-running telemetry ingestion service, are
  planned consumers of `@oya/core`.
- **Platform-bus wiring `(planned)`** — concrete runtime integration of the
  `*-integration.ts` adapter surfaces with `@oshun/storage`, `@oshun/event-bus`,
  `@oshun/metrics`, and `@oshun/database` (telemetry archive, mission history,
  drone registry, captured-imagery storage, event publication).
- **Gaia weather/cyclone consumption `(planned)`** — per `features.md`, Phase
  175 plans for Oya to consume Gaia cyclone, wind, precipitation, lightning, and
  severe-weather products as inputs to mission planning (no-fly cones,
  hurricane-hunter swarm tasking, outdoor mission gating). No Gaia adapter
  exists in `libs/oya/` today.
- **Rust performance tier `(planned)`** — high-frequency telemetry processing
  and MAVLink framing are candidates for Rust crates exposed to TypeScript via
  WASM (`wasm-pack`) or native bindings (`napi-rs`), as noted in
  `architecture.md`'s technology considerations.
