icmp6 would only appear over inet6, so it's not really necessary
It is possible to send ICMP over IPv6 or ICMPv6 over IPv4 to your firewall. If that happens you really want the firewall to block it and not send any ICMP or ICMPv6 error back to the sender.
Packets where IP and ICMP versions don't match are not standards compliant. So dropping them and logging that fact is a sensible treatment.
Using the above log, it looks like PF is blocking the ICMP packets while they're still encapsulated (before they even get to gif0). My next guess is going to try allowing all "proto encap" traffic to see if that works, but does anyone have any other thoughts?
I don't know the specifics of that firewall implementation. But the most obvious implementation would have such a packet go through the firewall rules multiple times.
First pass will treat the tunnelled packet as an incoming IPv4 packet. At this stage you'd expect the rules to only look at the IPv4 header. The contents of the IPv6 header would not be inspected unless you enable some degree of deep-packet-inspection in the firewall. If the packet is permitted at the first pass it proceeds to the next pass.
The second pass will treat the packet as an incoming IPv6 packet, which is likely a packet intended to be forwarded through the firewall. At this stage the IPv4 header may no longer be available to the filtering rules, but an implementation could keep the encapsulation headers available at this stage, just like it could make MAC addresses available to IP filtering rules.
A packet going the other direction would first be treated as a forwarded IPv6 packet, and next as an outgoing IPv4 packet. If you were to forward between two tunnels, one packet could go through filtering rules three times. First as an incoming IPv4 packet, then as a forwarded IPv6 packet, finally as an outgoing IPv4 packet.
A firewall might like to allow for rules that correlate IPv4 and IPv6 addresses to allow rejecting packets with unacceptable combinations of addresses. This could be done with DPI on the IPv4 packet or by making IPv4 headers available to the IPv6 filtering, or both.
Why would the first 3 seemingly work fine, but all the others fail?
Sounds like rate limiting. Can you figure out the numbering of the rules? I don't see how rule numbers 1 and 14 match up with your config.