Skip to content

Dependency Graph

Test User edited this page May 9, 2026 · 5 revisions

Workspace dependency graph

Generated from cargo metadata. Mermaid blocks render directly on the GitHub wiki; for local inspection paste into https://mermaid.live or any Mermaid-aware viewer.

xtask is omitted (no workspace deps; build-tooling only).

Layered architecture (regular deps only)

graph TD
    classDef foundation fill:#dfe3ee,stroke:#34495e,color:#000
    classDef physics fill:#e8f0d8,stroke:#27ae60,color:#000
    classDef gateway fill:#ffeaa7,stroke:#fdcb6e,stroke-width:2px,color:#000
    classDef consumer fill:#dceffb,stroke:#3498db,color:#000
    classDef verif fill:#f9d6d6,stroke:#c0392b,color:#000

    quantities[astrodyn_quantities]:::foundation

    math[astrodyn_math]:::physics
    time[astrodyn_time]:::physics
    planet[astrodyn_planet]:::physics
    ephemeris[astrodyn_ephemeris]:::physics
    frames[astrodyn_frames]:::physics
    atmosphere[astrodyn_atmosphere]:::physics
    dynamics[astrodyn_dynamics]:::physics
    gravity[astrodyn_gravity]:::physics
    interactions[astrodyn_interactions]:::physics

    astrodyn["<b>astrodyn</b><br/><i>gateway / root</i>"]:::gateway

    runner[astrodyn_runner]:::consumer
    bevy[astrodyn_bevy]:::consumer

    verif_jeod[astrodyn_verif_jeod]:::verif
    verif_parity[astrodyn_verif_parity]:::verif

    %% physics depends on foundation
    math --> quantities
    time --> quantities
    planet --> quantities
    ephemeris --> quantities
    frames --> quantities
    atmosphere --> quantities
    dynamics --> quantities
    gravity --> quantities
    interactions --> quantities

    %% physics inter-deps
    frames --> math
    dynamics --> math
    dynamics --> frames
    gravity --> math
    gravity --> dynamics
    interactions --> atmosphere
    interactions --> dynamics

    %% gateway pulls everything
    astrodyn --> atmosphere
    astrodyn --> dynamics
    astrodyn --> ephemeris
    astrodyn --> frames
    astrodyn --> gravity
    astrodyn --> interactions
    astrodyn --> math
    astrodyn --> planet
    astrodyn --> quantities
    astrodyn --> time

    %% consumers — gateway only
    bevy --> astrodyn
    runner --> astrodyn

    %% verification — gateway only (no direct physics edges)
    verif_jeod --> astrodyn
    verif_jeod --> runner

    verif_parity --> astrodyn
    verif_parity --> bevy
    verif_parity --> runner
    verif_parity --> verif_jeod
Loading

Every edge above is a direct dep the crate explicitly lists. Every non-foundation, non-gateway crate reaches the physics layer through astrodyn and only through astrodyn.

Layer semantics (Three-Layer Architecture)

  • Foundationastrodyn_quantities (typed-quantities phantoms).
  • Physics layer — pure Rust, zero Bevy dep. Each astrodyn_* crate owns one slice of the JEOD port (math, frames, gravity, …).
  • Gatewayastrodyn is the single API surface. Every Bevy system, every mission crate, every published consumer, and the verification crates read the workspace through astrodyn and only through astrodyn.
  • Consumersastrodyn_bevy (ECS adapter, mission code's runtime) and astrodyn_runner (arena harness for batch propagation; no JEOD specifics).
  • Verificationastrodyn_verif_jeod owns JEOD parsers, fixtures, scenario rigs, and the JEOD trajectory cross-validation tests; astrodyn_verif_parity asserts bit-identical state between runner and Bevy. Both depend on the gateway only — they are gateway consumers like the runner and Bevy adapter.

A single CI lint (scripts/check_no_bypass_deps.sh) enforces the gateway-only invariant for astrodyn_runner, astrodyn_bevy, astrodyn_verif_jeod, and astrodyn_verif_parity. Owner-crate unit / Tier 2 / Tier 3 tests live inside their owning crate's tests/ directory and reach the crate under test through normal in-crate test access; they are not scanned.

Mission-path slice (what published consumers see)

graph TD
    classDef gateway fill:#ffeaa7,stroke:#fdcb6e,stroke-width:2px,color:#000
    classDef consumer fill:#dceffb,stroke:#3498db,color:#000
    classDef physics fill:#e8f0d8,stroke:#27ae60,color:#000

    bevy[astrodyn_bevy]:::consumer
    astrodyn[<b>astrodyn</b><br/>gateway]:::gateway
    physics["10 × astrodyn_*<br/>(physics + ephemeris)"]:::physics
    bevy_ext[bevy 0.18]

    bevy --> astrodyn
    bevy --> bevy_ext
    astrodyn --> physics
Loading

A mission crate that wants to ship code into Bevy depends on astrodyn_bevy and bevy; that's the entire surface. The 10 physics crates sit behind the gateway and only get pulled in transitively.

Full edge listing (regular + dev)

→ regular dep, ⇢ dev-dep.

astrodyn:
  → astrodyn_atmosphere
  → astrodyn_dynamics
  → astrodyn_ephemeris
  → astrodyn_frames
  → astrodyn_gravity
  → astrodyn_interactions
  → astrodyn_math
  → astrodyn_planet
  → astrodyn_quantities
  → astrodyn_time

astrodyn_atmosphere:
  → astrodyn_quantities
  ⇢ astrodyn_verif_jeod

astrodyn_bevy:
  → astrodyn
  ⇢ astrodyn_runner
  ⇢ astrodyn_verif_jeod

astrodyn_dynamics:
  → astrodyn_frames
  → astrodyn_math
  → astrodyn_quantities
  ⇢ astrodyn_gravity
  ⇢ astrodyn_planet
  ⇢ astrodyn_verif_jeod

astrodyn_ephemeris:
  → astrodyn_quantities

astrodyn_frames:
  → astrodyn_math
  → astrodyn_quantities
  ⇢ astrodyn_time
  ⇢ astrodyn_verif_jeod

astrodyn_gravity:
  → astrodyn_dynamics
  → astrodyn_math
  → astrodyn_quantities
  ⇢ astrodyn_frames
  ⇢ astrodyn_time

astrodyn_interactions:
  → astrodyn_atmosphere
  → astrodyn_dynamics
  → astrodyn_quantities
  ⇢ astrodyn_ephemeris
  ⇢ astrodyn_gravity
  ⇢ astrodyn_math
  ⇢ astrodyn_planet
  ⇢ astrodyn_time
  ⇢ astrodyn_verif_jeod

astrodyn_math:
  → astrodyn_quantities
  ⇢ astrodyn_ephemeris
  ⇢ astrodyn_planet
  ⇢ astrodyn_verif_jeod

astrodyn_planet:
  → astrodyn_quantities
  ⇢ astrodyn_math

astrodyn_quantities: (foundation — no workspace deps)

astrodyn_runner:
  → astrodyn

astrodyn_time:
  → astrodyn_quantities

astrodyn_verif_jeod:
  → astrodyn
  → astrodyn_runner

astrodyn_verif_parity:
  → astrodyn
  → astrodyn_bevy
  → astrodyn_runner
  → astrodyn_verif_jeod

The dev-dep edges from physics crates back to astrodyn_verif_jeod support the Tier 2 / Tier 3 unit tests that live in each owning crate's tests/ directory and use astrodyn_verif_jeod's JEOD fixture parsers (tier3_csv, body_init_fixtures, etc.). Cargo treats dev-deps as a separate compilation unit, so the back-edge is not a regular-dep cycle.

Verification of acyclicity

cargo build --workspace and cargo tree --workspace succeed — Cargo would refuse the build on any cycle in the regular-dep graph. The mission-path graph is a clean DAG: astrodyn_runner, astrodyn_bevy, astrodyn_verif_jeod, and astrodyn_verif_parity each have a single edge into the physics layer, and that edge goes through astrodyn.

Regenerate

# Quick text view (matches the "Full edge listing" above)
cargo metadata --format-version=1 --no-deps | jq -r '
  .workspace_members as $ws
  | .packages
  | map(select(.id as $id | $ws | index($id)))
  | map(select(.name != "xtask"))
  | sort_by(.name)
  | .[]
  | . as $pkg
  | (
      [.dependencies[] | select(.name | startswith("astrodyn"))]
      | group_by(.name)
      | map({
          name: .[0].name,
          rank: (if any(.kind == null) then 0 else 1 end),
          kind: (if any(.kind == null) then "normal" else "dev" end),
        })
      | sort_by([.rank, .name])
    ) as $deps
  | "\($pkg.name):" + (
      if ($deps | length) == 0 then " (no astrodyn_* workspace deps)"
      else "\n" + ($deps | map("  \(if .kind == "dev" then "⇢" else "→" end) \(.name)") | join("\n"))
      end
    )
'

# Or just inspect Cargo.toml files
for f in Cargo.toml crates/*/Cargo.toml; do
  echo "=== $f ==="
  awk '/\[(dev-)?dependencies\]/,/^\[/' "$f" | grep -E '^astrodyn_'
done

Clone this wiki locally