A few thoughts:

- Recall is, for most purposes, not a useful metric. So we are debating what color to paint not the bike shed, but the rubbish bin in the bike shed.
- If you are evaluating top-N recall where there are more than N good items, there is probably something fishy.
- If we really care, we could report NormalizedRecall as a third column, or report RecallLimit (`Math.min(N, items.size()) / items.size()`) and let users normalize.
- With the current formula, using `items.size()` as the denominator feels more straightforward to me.