John, if you really want table.insert to have different behavior, just modify ltablib.c line 41-65. The code is quite compact and not too complex. That way, you can have the language behave the way you want. It won't even be bad for people working on your codebase, considering that your variant will be more robust that the original distribution. (assuming, of course, that you don't introduce a new bug ;))
Just do a check in case 3: for a negative insert value, or an insert value greater than the size of the array.
In fact, there's already a check for an insert value greater than the size of the array, on line 52, so you could maybe make that exit the function instead of the statement "e = pos." (which itself is actually equivalent to "break," since setting e to pos will always skip the following loop.)
Then, you could just add another one for negative values.
If you want to understand Lua's "odd" behavior, just look at the code. If you send a negative value, what happens is that all the elements in the array are moved up by one and finally the negative index is added to the array at the index specified.
i.e.: