There is a point in every project where speed turns against you.
In the first months, moving fast was the right call. Each feature taught me something about the next. But by early summer the application had scenes, effects, 3D guides, overlays, transitions, stingers, scripting, outputs, NDI and the start of an audio engine. Every new feature touched three old ones. Bugs started to appear in places nobody had changed.
That is the moment to stop adding and start understanding. So I stopped, and drew a map.
Fog of war
The map borrows an idea from strategy games: fog of war. At the start you see only the area around you. The rest of the map is dark until you explore it.
Every capability of the product is a place on that map: scene composition, overlays, audio mixing, outputs, guests, scripting, plugins, and so on, down to smaller pieces such as metering or stinger playback. Today there are more than fifty of them.
Each place has a state that says how well we know it:
- Foggy: we know it should exist, not much more.
- Bounded: its edges are clear, what it owns and what it does not.
- Specified: exactly how it must behave is written down.
- Implemented: it is built and verified against that description.
The map makes two things visible that are easy to ignore. Where we are guessing, and what depends on what. Guests depend on the audio graph. Plugins depend on a stable public contract. A feature cannot honestly be built before the ground under it is solid.
Write it down before building it
The second change is simple to say and hard to keep: nothing important gets built until its behaviour is written down.
For each capability that means a clear statement of what it is for, who uses it, what it owns, the rules it must follow and the scenarios that prove it works, including what happens when things go wrong. A source disappears in the middle of a show. Two operators change the same thing at once. A plugin misbehaves.
It sounds like paperwork. In practice it is the cheapest place to find a mistake. Changing a sentence costs a minute. Changing a design that is already in a live show costs weeks.
One set of operations for everyone
Mapping the system also exposed a quiet problem. The interface, the scripts and the internals did not always use the same path to change things. Two ways to do the same thing means two places for bugs and behaviour that drifts apart.
So the code was reorganised around capabilities, each with a clear owner, and every change goes through one set of typed operations. The interface uses them. Lua scripts use the same ones. A future command line and AI agents will use the same ones too. If something is possible in the interface, it is possible from a script, with the same rules and the same safety checks.
Proof, not optimism
The last piece is verification.
Every requirement now has automated checks tied to it, not just a broad test suite that happens to pass. When a behaviour has several parts, each part has its own check: the normal case, the failure, the recovery, and that nothing else was disturbed.
For anything that touches rendering, audio, files or devices, a browser test is not enough. The checks run against the real application and its real outputs, because a picture that looks right in a test page and wrong on the output monitor is still wrong.
People still review the work, but for what people are good at: does it look right, does it feel right, does it make sense in a real show. Machines check that it works; humans judge whether it is good.
What it cost, and what it bought
Drawing the map meant weeks with few visible new features. That is uncomfortable when you want to show progress.
What it bought is the ability to build bigger things without breaking the smaller ones. The next chapters are the result: an audio engine designed as a real signal graph, live data for graphics, and a plugin platform built on public contracts. None of them would have been safe to attempt on the old foundations.
First up: audio.