Devlog
A dated data row, and the bug behind it
What happened: on Henri Toivonen and Sergio Cresto were killed on the Tour de Corse. Within hours FISA moved to ban Group B from the world championship for 1987 and cancelled the Group S rulebook that was to replace it. Group A became the top class. Everything below is about turning that into software without lying about it.
if (year >= 1987) { hide Group B }
It compiles, it looks right in a screenshot, and it is wrong in three separate ways. It bans the cars everywhere rather than from the championship that banned them. It has no source attached, so nobody can check it in two years. And it deletes entries from a start list, which quietly shrinks the field, as though the ban made 1987's competitors stay home.
They did not stay home. The same semi-works teams turned up in 1987 in Group A cars. That distinction is the whole design.
The ban is a row in a table, with a window and a citation, read by the entry-eligibility layer. Stripped of its type noise, it is this:
{
from: 1987, to: 2100, classes: ['groupB'],
source: 'FISA banned Group B from WRC for 1987 after Corsica 1986;
Group A premier from 1987',
}It is scoped to the series that banned it. A Group B car may not start a world-championship round from 1987. It can still start a national event, and it can still start a historic or period event that will take it. Weekends that score for two championships at once follow the more permissive rule and score where they are allowed to.
There is a matching table for the European championship, with different dates and a different subject. World Rally Cars and Rally1 are refused a European-only start from 2003, because that is a different rule made by different people at a different time. One shape, several rows, each dated.
This is the distinction the code makes, and it is the one that most games get wrong.
| A class ban | A period allow-list | |
|---|---|---|
| Example | Group B refused a world-round start from 1987 | A historic rally that takes 1970s and 1980s machinery and nothing else |
| What it means | The formula changed under an existing field | The start list is the rule: the event exists to be period |
| What happens to a crew that fails it | Keeps its tier, and turns up in legal machinery from the same tier | Drops a rung: a works entry that fails a period allow-list is not a works entry, and arrives in club metal |
| What happens to the field | Same size. Substituted, not thinned | Same size. Substituted, not thinned |
Substitution rather than deletion is the rule everywhere the game refuses an entry, and it applies to more than machinery. A Soviet-era round that will not admit a Western passport does not simply lose those crews and run a short field. It casts inside the rule in the first place, and draws replacements who are allowed to be there.
The rule above was written correctly and shipped. It was also, for months, only checked on one of the two code paths that build a start list. The path it was missing from was the world championship, the one place the rule was actually about.
When it was finally measured on :
Nobody had noticed, because the game looked right: the era pages were correct, the rulebook was correct, the sub-world branch was correct, and the one start list nobody had checked was the headline one. The fix put the gate on both paths, made the substitution step read the ban tables rather than only a historic allow-list, and added a standing test that fails the build if illegal starters reappear.
There is a measurement tool for it in the repository, because "it looks right" is not a test. The same week, an equivalent audit of the passport rule on Soviet-era events found 3,258 crews being cast and then deleted at the start line across 140 affected event-year cells. That went to zero the same way: refuse earlier, and fill the hole.
They are not confiscated and they do not vanish from the save. From 1987 they simply cannot be entered in a world round. They can run where they remain legal, they hold and then gain value over the decades, and a team that started in 1973 will eventually be sitting on a collection worth more than its operating budget.
One small display consequence, for the people who will notice: from 1987 the results screen lists Group A first among the classes present, even on an event where a Group B car started. The premier class is a property of the year, not of whoever turned up.
Because the modern sport is the one everybody pictures, and its rules feel like how rallying works. They are not. They are how rallying works now. Two examples this project caught in its own code, both of which had looked entirely reasonable:
The rule that came out of it: before implementing any limit, cost or availability, ask whether it was true in every era from 1973 to 2026. If the answer is no, or unknown, it is era data with a date and a citation, and not a constant in the code.