The simulation engine
Suppose you want to test how a defense holds up against a hundred drones arriving at once, from three directions, with a radar blackout halfway through.
You cannot go and film that. Real saturation attacks are rare, expensive to stage, and impossible to repeat on demand, and the whole point of testing is repetition. This is the quiet problem at the center of building anything like DomeCommand: the data you most need is the data you can never collect. So you generate it instead.
We are putting a lot of time into the simulation engine for exactly this reason. It is where the synthetic data gets exercised in full, across combinations we could never stage: fleet laydowns against threat patterns, run and re-run until the failure modes show themselves.
Scenarios you can generate, not just author
If you cannot get real fights, you have to be able to generate them, precisely and repeatably. A scenario in DomeCommand is three things bundled together:
- a theater: where it happens, over real satellite imagery,
- a laydown: the fleet, what you are defending with, and where your sensors and effectors sit,
- a threat package: what is coming, how many, of what type, from where, in what waves.
Both halves come out of catalogs, so scenarios combine rather than get hand-built one at a time. On the fleet side: sensor types and their coverage, effector tiers (long-range area defence, short-range gun and missile, point defence at the high-value assets), the number of defender posts and where they sit. On the threat side: airframe types, wave sizes, attack vectors, timing, and faults injected mid-fight. Pick from each and you have a scenario, which means the interesting space is a product of the catalogs and not a list somebody wrote down.
A few from the current library, to make it concrete:
| Scenario | What it tests |
|---|---|
Baseline Saturation | 100-drone wave from three axes. The default benchmark. |
NE Surge | A 50-drone north-east wave stacked on top of the baseline. |
Changi Blackout | A sensor goes dark mid-engagement; the inner layer has to compensate. |
West Radar Down | Radar out for two minutes, right as an approach develops. |
Comms Loss | The mission-command channel drops mid-fight; effectors hold posture. |
SAM-C Down | The central long-range effector is unavailable for the whole engagement. |
EW Saturation | Compound electronic warfare: multiple sensor faults plus a surge. |
And you can author a new one in plain language. You describe the fight the way you would say it out loud, "a saturation swarm of 60 FPV drones from the north-west, with a two-minute radar blackout halfway through", and the engine parses it into the same structured parameters the catalog scenarios use: threat type, count, attack vectors, defender posts, difficulty, duration, faults. You get to review and correct the parameters before it runs.

That plain-language front door matters more than it looks. It is the difference between a simulator only its authors can drive and one an operator can use to ask "what if it came from the other direction?" and get an answer in seconds.
Then you run it, and watch the whole engagement play out: the threat tally, the rules of engagement in force, the priority queue, the plans the system is proposing, and what each one is predicted to cost you.

Determinism is the whole game
Here's the part I'd defend hardest. A simulator is only useful for learning from if it's deterministic: if the same setup plays out identically every single time.
We put real engineering into this. Every source of randomness in the sim funnels through one seam: a virtual clock, a seeded random-number generator per agent, and an event-logged command stream. The consequence is that a whole engagement becomes a pure function of the seed plus the ordered list of commands. Replay it and you get a byte-for-byte identical fight, even with reactive drones and even with an operator making live decisions in the middle, because those decisions get recorded as events too.
(If that sounds familiar, we borrowed the idea openly from deterministic-simulation testing in databases like TigerBeetle and FoundationDB. Funnel all nondeterminism through one place, and your entire system becomes reproducible.)
Why care so much? Because it turns the simulator into an instrument. Run a scenario, make one different decision partway through, run it again, and because nothing else could have changed, the difference in outcome is attributable to your decision and not to luck. That's the precondition for learning anything real from a simulation. Without it you're just watching fireworks.
Threats that behave, not dots that fly straight
The first version of any sim has threats that follow scripted paths: fly from A to B, ignore everything. That's useless the moment your defense does something, because a real adversary reacts.
So the threats are little agents with intent. A kamikaze drone terminates on its target; a payload-drop runs in, drops, and egresses; a recon drone loiters and watches. Each one senses only what it could actually see: an attacker notices an interceptor when it comes into camera range, and can feel a GPS jammer by the way its satellite fix diverges from its inertial one. Then it reacts: press the attack, break evasively, dead-reckon through the jam zone.
None of this is hand-waved. The maneuvers are grounded in the real guidance literature: proportional navigation (how missiles have pursued targets for decades), Dubins paths (the tightest turn a fixed-wing can make), vector fields for orbiting. The goal is an adversary that's hard for honest reasons.
One detail I find clarifying: the simulator holds two versions of the world. There's ground truth, exactly where everything is and what it intends, which only the sim knows. And there's the deduced picture, noisy observations run through sensor fusion into tracks, which is all the operator is allowed to see. Same data structure, opposite provenance. The gap between them is the fog of war, and being able to measure that gap is a large part of why you simulate at all.
Learning from the history
Every run leaves a record: the scenario, the picture the operator saw, the plans on offer, which one was approved, and what it cost. That history is a training set, and we are experimenting with two ways of using it.
The first is fine-tuning. Take the engagements that went well, and the human approvals and rejections attached to them, and tune a model on that trace so its next plan looks more like the ones that worked and less like the ones a person threw out. This is the cheaper, more direct path, and it learns the taste of an operator as much as the physics of the fight.
The second is reinforcement learning against the simulator itself. That is the more ambitious one, and it only works because of the determinism above: an episode you cannot reproduce is an episode you cannot learn from.
The AlphaZero-shaped bet
Now the part I'm most excited about building toward: this is a direction we're heading, and the groundwork for it is what we've been putting in place.
Think about how AlphaZero learned Go. It wasn't fed human games. It was given the rules (a closed, deterministic world where every move has a defined outcome) and it played itself, millions of times, getting better by grinding against its own improving opponent. The rules never changed, so every game was a clean experiment, and self-play could squeeze signal out of it indefinitely.
Look back at what we just built. A deterministic environment with fixed rules. Threats and defenders that are agents taking actions and getting outcomes. A reproducible result for any given setup. That is exactly the shape a self-play system needs. The simulator isn't just a test harness. It's a candidate training environment.
The experiment we're circling: wrap the deterministic sim as a reinforcement-learning environment. A scenario becomes an episode. The action space is a plan, the same structured mission format the system already emits. The reward is the outcome the sim already scores: leakers stopped, cost spent, coordination quality, rules-of-engagement compliance, robustness to comms loss. Then let a planner learn against that reward the way AlphaZero learned against a win. The adversary gets harder over iterations in ways grounded in real simulated outcomes, not hand-tuned difficulty knobs, and a human stays in the loop on what gets promoted.
Here's how the work stacks: the deterministic engine, the behavior model, the plain-English scenarios, and the replay-and-compare loop are the foundation we've built. The self-play / RL layer is what we're building toward on top of it. I'm writing it down now because the interesting thing about the architecture is that it was designed to make that possible. You build the fixed-rule world first. What you do with it is the next chapter.
The scenario-authoring screenshots are from the DomeCommand console. The determinism approach draws on publicly documented deterministic-simulation testing (TigerBeetle's VOPR, FoundationDB); the threat maneuvers on standard guidance literature. Nothing here reflects a specific site or operator.
