Hi Justin,
Tamarin uses a specific type of reasoning about adversary knowledge to avoid infinite loops. The idea is the following: The adversary first collects all messages they received. Then, using „destruction rules“ (KD-related where D stands for „down“) they extract the smallest terms they can learn from these messages. For example, if the adversary receives a tuple <a, b>, they learn a and b. If they receive send(m, k), they only learn that term (unless they know k, then they also learn m). Finally, using „construction rules“ (KU-related where the U stands for „up“) the adversary combines all these smallest terms to larger terms which then make up the adversary knowledge. The coerce rule simply passes the boundary from KD to KU, and it only works this way to avoid loops.
The K fact simply expresses adversary knowledge, thus, it comes from KU. Tamarin’s built-in rules never use K facts (afaik), so K only appears when you reference it in a lemma yourself.
I hope this answers all your questions!
Cheers,