After fixing some smaller bugs, I returned to the problem of distributions still being added to the database even when the admin or maintainer rejects them in the queue.
I decided to address the problem in smaller steps this time rather than trying to fix it all at once. The first step was to submit the patch that did at least separate the test report from the invalid distribution when it was changed in the queue. Even though it didn't fully fix the problem, it made things much easier for admins, in that all we had to do now was delete the distribution that shouldn't have been added, whereas before we had to first track down the incorrect test report and change the distribution in it again before being able to delete the invalid one.
I then shifted my focus to why users were entering invalid distributions in the first place. I found a number of problems with the UI that made user errors more likely.
The first was the word "distribution" itself. That's a Linuxism that makes no sense for users of other operating systems, (Wine has a lot of macOS users), and many new Linux users don't understand the term either. A lot of the invalid "distributions" I saw submitted in test reports were actually names of distributors. So I changed "distribution" to "operating system" in areas visible to users, and rephrased the help text to make it clearer that users should look for theirs in the dropdown list first and only add a new one if it is not found.
The next thing I looked at was the notice presented in the queue to admins/maintainers when a user had added a new operating system: it simply wasn't noticeable enough. I added a warning icon and background color to make it stand out more against the rest of the form.
After that I took another look at stopping rejected items from being added to the database. The real problem is that there is one submit button at the bottom of the queued form, and pressing that leads to everything in the form being accepted. There was nothing in the code that explicitly rejected a submitted operating system when it was replaced with one in the dropdown list, and that's what needed to be added.
The code already had a check for whether the operating system had been changed from the original submission, though all it did was add a message that x had been changed to y. That seemed the logical place to force the system to delete the submitted operating system if it had been changed and the original one wasn't accepted, but finding the right way to do it proved a bit tricky. Simply checking the state of the submitted operating system turned out to be a bad idea because the state was changed to accepted as soon as that submit button was clicked. I eventually got it to work as it should by checking the count of test reports attached to the operating system, and forcing a delete it if there was no more than one.
It's now working as it should, but I'm not entirely happy with it. I've patched up the visible problems, but IMO the underlying design is still flawed.