In NodalArc, the file boundary is part of the experiment.
That is harder than it sounds.
A constellation is not just a list of satellites. It changes which interfaces can exist, how long links last, which ground stations matter, and what the router is forced to survive. If those choices are tangled together in one lab definition, every comparison comes out dirty. You think you changed the sky. You also changed the wiring, the exits, and the routing assumptions hiding underneath.
Now the result has fingerprints all over it.
The experiment has to stay clean
A lab earns its name by isolating one variable. That is the whole point of having one.
You can argue with anyone about whether IS-IS handles polar seams gracefully. Run IS-IS twice. Once across an Iridium-style polar shell. Once across a Starlink-style mid-inclination shell. If the numbers come back different, the argument stops being opinion and starts being measurement.
If you did both runs cleanly.
If the only thing that changed between the two runs was the sky, then the difference in numbers belongs to the sky. If you also rewired the addressing, moved the ground exits, swapped terminal counts, and quietly retuned the routing protocol, then the difference belongs to whatever combination of those things you happened to change. You can argue about which one mattered. You cannot prove anything.
That is the experimental honesty post 005 (The Lab Is a Network) enforced at the substrate layer. Post 006 is the same discipline at the file layer.
Think of the files as blocks if that helps. The important part is not that they snap together. The important part is that they do not melt into each other.
The satellite type is hardware
A satellite type says what a bird can physically do. It does not say where the bird flies, who its neighbors are, or what protocol runs inside it.
satellite_type:
name: iridium-next
description: "Iridium NEXT Ka-band ISL platform"
isl_terminals:
- type: rf
band: Ka
count: 2
role: intra-plane
max_range_km: 4400
bandwidth_mbps: 10
max_tracking_rate_deg_s: 4.0
field_of_regard_deg: 120
- type: rf
band: Ka
count: 2
role: cross-plane
max_range_km: 4400
bandwidth_mbps: 10
max_tracking_rate_deg_s: 2.5
field_of_regard_deg: 120
ground_terminals:
- type: rf
band: Ka
count: 1
bandwidth_mbps: 200
beam_falloff_exponent: 3.5
Two intra-plane ISL terminals at four degrees per second. Two cross-plane terminals at two and a half. One Ka-band ground terminal at two hundred megabits.
That second number, max_tracking_rate_deg_s: 2.5 on the cross-plane terminals, is the polar seam from post 002 (Addressing the Geometry Problem), sitting in the file. The geometry decides when the apparent motion across the antenna exceeds that limit. The file says what the geometry has to fight.
The file does not say how many of these birds exist. It does not say what altitude they fly. It does not say what protocol runs across them. Those are downstream decisions, and they belong in downstream files.
The sky is not routing
A constellation describes where the satellites fly. For this class of Walker run, a small set of values gives the platform the shape it needs: altitude, inclination, plane count, plane spacing, satellites per plane, and phase offset between planes. Add an optional polar_seam block when the geometry crosses where the satellite type can no longer track, and the file is complete.
mode: parametric
name: iridium-66
satellite_type: iridium-next
orbit:
altitude_km: 780
inclination_deg: 86.4
pattern: walker-star
planes:
count: 6
raan_spacing_deg: 31.6
sats_per_plane: 11
phase_offset_deg: 5.45
polar_seam:
enabled: true
latitude_threshold_deg: 70
Seven hundred eighty kilometers. Eighty-six point four degrees of inclination. Walker Star. Six planes of eleven satellites. The polar_seam block says cross-plane links are allowed to drop above seventy degrees latitude. That number does not come from the constellation. It falls out of the satellite type's max_tracking_rate_deg_s and the geometry the planes carry through the polar region. The constellation acknowledges the hardware. It does not invent it.
What the file does not contain is just as telling. There is no routing block. There is no ground-station list. There is no traffic profile. The constellation describes the sky and nothing else.
That is intentional. The same Iridium-style geometry can be tested under IS-IS, OSPF, NodalPath, or a router that has never seen orbital interfaces before. The sky decides which graph is even possible. It does not decide what runs across that graph.
Ground exits are policy
A ground station is not just a dot on a map. It is a place where the orbital network becomes reachable from Earth. What it advertises into the routing domain is what the orbital network knows about the world below.
ground_station:
name: ashburn
lat_deg: 39.04
lon_deg: -77.49
alt_m: 100
min_elevation_deg: 25
terminals:
- type: rf
count: 2
bandwidth_mbps: 1000
tracking_capacity: 1
terrestrial_prefixes:
- prefix: "172.16.2.0/24"
metric: 10
- prefix: "0.0.0.0/0"
metric: 100
Latitude, longitude, altitude. A minimum elevation the station will accept a satellite at. Two RF terminals with bandwidth and tracking capacity. And the part that makes a ground station behave like a PE router in an MPLS VPN: terrestrial_prefixes. A connected /24. A default route. The orbital routing domain learns those prefixes the same way it would learn any others.
Putting a station in Ashburn gives the orbital network a particular kind of exit. Putting one in Frankfurt gives it a different exit. Putting one in McMurdo gives the network reason to care about a part of the planet most terrestrial backbones never think about. Each station is a policy decision dressed in geographic coordinates.
A ground-station set names which exits belong to a given run.
ground_station_set:
name: polar-emphasis
stations:
- svalbard
- fairbanks
- mcmurdo
The station file describes one exit. The set chooses which exits belong to this run.
That is why ground stations live in their own files, and station sets in another. Swapping ground exits between two otherwise-identical runs should be one file pointer changing. The session points at a different set, and nothing else moves. If it requires editing the constellation, the experiment is tangled.
The session is the argument
The session file is where the four pieces come together for one run. It names a constellation, a ground-station set, a routing stack, a propagator, dispatch policy, and a clock cadence.
session:
name: iridium-66-isis-flat
constellation: configs/constellations/iridium-66.yaml
ground_stations: configs/ground-stations/sets/polar-emphasis.yaml
routing:
protocol: isis
extensions:
- traffic-engineering
- sr
area_assignment:
strategy: flat
time:
step_seconds: 1
The session is not just configuration. It is a controlled argument.
Iridium-style polar geometry. Polar-emphasis ground stations. IS-IS with traffic engineering and segment routing extensions. One flat area. One-second simulation steps. Every choice fixes a parameter so that the result means something specific. If the session is honest, the result is honest.
Change one line and the question changes. Change five lines and the question is gone, replaced by something nobody can name.
The session is also where the router-agnostic commitment becomes visible. Today the routing block names IS-IS as FRR speaks it. Tomorrow it could name a containerized Juniper cRPD, a Cisco XRd, an Arista cEOS, or a controller speaking over the emulated fabric. The session does not care which one. The session cares that the experiment can describe its question, run it, and produce a result that means what it appears to mean.
One deliberate change
A clean comparison is boring in the best possible way.
Same sky, different routing.
Same routing, different sky.
Same hardware, different ground exits.
Same everything except a single satellite-type field that just got slower.
One deliberate change. One result worth reading.
When two runs disagree, the diff between their sessions is the proof that the disagreement means something.
A one-line diff gives the disagreement a name.
A five-line diff gives you an argument.
That is what the files are for.
Not tidiness.
Honesty.
Writing a clean session by hand works, but it asks you to hold the whole experiment in your head. post 007 (The Session Builder) walks through the wizard NodalArc ships for the same job, and the phase that matters most: feasibility math before a bad idea becomes a deployed session.