The other is that each comment only enters the "archive process" once per lifetime.
That is not assumed. If there was double entry for migration of the same comment, during processing of the second entry comment would no longer exist in comment_index (deleted during processing of first entry), so the code would assume the comment was deleted and do nothing. But you correctly identified root problem:
the archive map has a stale entry for gtg (tied to the block number from chain1's reality)
If chain2 included gtg's deletion, the comment object would be removed by normal chain logic
I keep forgetting that fork switch can happen not only when there is second chain that is longer, but also by OBI confirmation transactions. The bug can be shown in single fork. I've already supplemented the test and the bug runs into Segmentation Fault during execution of "would be removed by normal chain logic" :o)
Here is the scenario with one fork: comment is to be cashed out in slot(N), that would normally be block(M). Our node experienced short network outage, so we did not receive two blocks . The node assumes they are missed and produces its own in slot(N), but the number is block(M-2) - that is the entry in ready-to-archive map. Now the node receives correct block(M-2) built for slot(N-2), followed by the wave of OBI confirmations. Finding itself in the minority, it abandons its version of block(M-2) and switches to received block(M-2), making it irreversible shortly after. It triggers comment migration due to dangling entry in ready-to-archive map, comment is removed from comment_index and written into archive index. However in reality of chain2 the comment was yet to be cashed out (after all its cashout time is slot(N) and we've moved back in time to slot(N-2) ). If we just continued with two more blocks not touching the comment, it would be put again in ready-to-archive map, this time with block(M) number, and once that block became irreversible, the comment would be processed again, not found in comment_index, so skipped with no problem. But reality of chain2 contains comment delete at slot(N-1) = block(M-1). That delete reaches for comment (and it is found - in archive) and tries to delete it from comment_index where it is no longer present which causes Segmentation Fault.
I'm not sure how it translates to actual node behavior (after all unit tests differ quite a lot from normal node), but in best case scenario it would mean our node turned down block(M-1) which rest of the network approved, so it is now permanently in minority fork (with only full replay as a remedy).
RE: Comment archive - for node operators and technical