Okay, I dove into this and things are pretty much working as they should so I've resoved this bug BY DESIGN. I won't claim it's the best design, there are certainly things that could be improved here and I have plans to do so some day, but it is by design for the moment.
Soem explanation. The code for insertion mutations kind of goes like this:
First, it extends the genome by some random length (a length whose mean is initially defined by the human in the mutation dialog) at some random position in the genome and sets the type and value of the new base pairs to -1 (VOID). In the case of this bot, it extended the DNA by 1 base pair at location 35.
Second, it randomly picks a new type and value for each of the newly inserted VOID base pairs. This order (type first and then value) is important. Picking the type first insures that the new value lies within the range of valid values for the specific type.
There is a lot of code re-use going on here. The code to mutate the type and value is shared with other mutation types, so the verbage that gets put in the mutation details is a little confusing. Below are the two (two!) lines in the details that refer to this mutation. Note that the order of occurance is bottom up.
Insertion changed number from-222 to-223 at position 35 during cycle 24878326
Insertion changed the : to the number: .up at position 35 during cycle 24878326
The first line (bottom line) is the change of the new BP's type. The code that parses base pairs into human readable strings has some interesting special cases. In this case, for reasons I won't go into, suffice it to say that it the way the mutation code calls the parse routine is making it think that it should parse the value into a sysvar regardless of type. Since the value is -1 and we do an ABS MOD 1000 on such values, it maps to .up. This is just a display issue for the mutations details. The actual underlying bp is still type 0, value -1 (the number -1) at this point.
The second line (upper line) is the change of the base pair's value. In the case of insertion mutations, the code elects to first choose a valid-for-the-type random value and then mutate off of that using the specified mutation distribution. Remember, the old value of non-insertion mutations, particularly for numbers, does matter as the new value will be only so distant from the old (whether this is a good thing is a separate topic) but for insertions, there is no old value, so the code has to pick one first. So, the number it picked was -222 and then it (unnecessarily) mutated that based on the defined distribtuion and got -223.
There's lots of room for improvement here. There should only be one line in the mutation details for a sinlge logical mutation like an insertion. The parse code should say VOID or similar where appropriate. The value should not be mutated twice. But the code is touchy. It relies on the fact for example that invalid base pairs parse to an empty string (as displayed above in the bottom line) instead of "VOID". Changing this would be involved and not something I'm going to bite off today.
Bottom line, insertion mutations do appear to be working as they should, it's just that the mutation details are a little convuluted.
BTW, I have verfied that the discrprecy between total bots and vegs mentioned by Nums is indeed due to corpses. There were in fact 25 corpses in that sim at the time of the screen shot.