cargo build # build workspace
cargo test # run all tests
cargo clippy --workspace -- -D warnings # lint (must pass)
cargo doc --workspace --no-deps # generate docsIgnored tests. 23 tests in rpo-nyx/src/validation/ are #[ignore]d because they
require MetaAlmanac ephemeris data. Run them with cargo test -p rpo-nyx -- --ignored;
the first run downloads SPICE kernels (outbound network required) and caches them under
the anise default path. Subsequent runs hit the cache.
- Clippy pedantic enforced (
#![warn(clippy::pedantic)]);#![warn(missing_docs)]on all public items - f64 everywhere — never
f32, never compare floats with==, use named epsilon constants - Angles in radians, distances in km, velocities in km/s
- Single-char variable names (
a,e,i,u,n,r,v,h) are acceptable for standard orbital mechanics quantities
Unit suffixes are mandatory on public fields with physical units:
| Suffix | Meaning | Suffix | Meaning |
|---|---|---|---|
_km |
kilometers | _s |
seconds |
_km_s |
km/s | _rad |
radians |
_km2 |
km² | _kg |
kilograms |
_m2 |
m² | _deg |
degrees (avoid in math) |
Frame tags are mandatory on state-like geometric vectors (position_eci_km, dv_ric_km_s, dcm_eci_to_ric). Be precise with terminology: mean vs osculating, chief vs deputy, ECI vs RIC.
All tolerances must be named constants with documented justification — no anonymous 1e-8 literals. Categorize as geometry, convergence, singularity, or test tolerances.
Result<T, E>for all failure paths — nounwrap/expectin library code- Structured error enums with diagnostic fields, not strings
- No
assert!for input validation — returnErr(...)instead
- Struct-based public APIs — no raw scalar argument lists at API boundaries
- Enums over boolean flags for algorithm regimes
- Separate classification from execution in solvers
- Explicit
forloops in iterative algorithms (no recursion), no heap allocation in solver loops
Astrodynamics code must cite source equations (Koenig, D'Amico). Cross-check against reference PDFs in docs/ before modifying formulas.
- Cover nominal cases, edge conditions, degenerate geometries, and regression against published data (cite exact table/figure)
- Include invariant tests: roundtrip transforms, STM identity at dt=0, covariance symmetry, DCM orthonormality, energy/momentum conservation
- Test tolerances must be documented with justification
| Crate | Purpose |
|---|---|
rpo-core |
Library: orbital mechanics, planning, propagation, mission orchestration |
rpo-cli |
Binary: CLI tool exercising the pipeline |
rpo-api |
Binary: WebSocket server wrapping the pipeline |
The dependency graph is rpo-core <- rpo-cli and rpo-core <- rpo-api. The two binaries never depend on each other.
Shared orchestration primitives (execute_mission_from_transfer, replan_from_transfer) live in rpo-core/src/pipeline/. The server-side Lambert-inclusive wrappers (execute_mission, compute_transfer) live in rpo-nyx/src/pipeline/; the CLI and API call them.
-
Define the command in
rpo-cli/src/cli.rs. Add a variant to theCommandenum with clap attributes. Porcelain commands (human-readable output) take--json; plumbing commands always output JSON. -
Create a handler in
rpo-cli/src/commands/. Add a new file (e.g.,commands/mycommand.rs). The handler function signature ispub fn run(...) -> Result<(), CliError>. Re-export it fromcommands/mod.rs. -
Wire it into
main.rs. Add a match arm in thematch cli.command { ... }block that calls your handler. -
Add output formatting (porcelain only). If your command has human-readable output, add a formatter in
rpo-cli/src/output/and re-export fromoutput/mod.rs.
-
Add the message variants in
rpo-api/src/protocol.rs. Add a variant toClientMessage(withrequest_idand any fields) and a corresponding variant toServerMessage. -
Create a handler in
rpo-api/src/handlers/. Add a new file (e.g.,handlers/myhandler.rs). Handlers are pure functions that take references and returnResult<T, ApiError>. Re-export fromhandlers/mod.rs. -
Wire it into
rpo-api/src/ws.rs. Add a match arm inhandle_text_message(). Inline handlers call the function directly and send the response. Background handlers usetokio::task::spawn_blockingwith progress/result channels. -
Add an integration test. Add a test to
rpo-api/tests/integration.rs. Tests connect via WebSocket, send aClientMessage, and assert on theServerMessageresponse.
Error types flow from rpo-core through both the CLI and API.
-
Define the error in
rpo-core. Add a variant to the relevant error enum (e.g.,MissionError,PropagationError). Use structured fields, not strings — see the Coding Standards section above. -
Add a
Fromimpl inrpo-api/src/error.rs. Map the new error to anApiErrorvariant. Implementextract_code_and_detail()to produce a machine-readableErrorCodeand optionaldetailJSON. -
Add a
Fromimpl inrpo-cli/src/error.rs. Map the new error to aCliErrorvariant (usually viaPipelineError). -
If it is a new top-level error enum, also add:
- A variant to
PipelineErrorinrpo-core/src/pipeline/errors.rs Fromimpls inpipeline/errors.rs,rpo-api/src/error.rs, andrpo-cli/src/error.rs
- A variant to
Before submitting, verify:
-
cargo buildsucceeds -
cargo testpasses (all existing + new tests) -
cargo clippy --workspace -- -D warningsis clean -
cargo doc --workspace --no-depsgenerates without warnings - All public items have doc comments (
#![warn(missing_docs)]) - Errors use structured enums with diagnostic fields, not strings
- Astrodynamics changes cite the source equation (Koenig, D'Amico, or other reference)
- Numerical tolerances are named constants with documented justification
- Unit suffixes on public fields with physical units (
_km,_rad,_km_s, etc.) - Frame tags on state-like geometric vectors (
_eci_,_ric_) - Tests cover nominal cases, edge conditions, and regression against published data