The "s", "f" and "e" descriptions in the Security section read as guarantees for every expression, but they only hold for expressions that meet the malleability requirements of the type system.
thresh is the clearest case: its rule is e=all are s, so thresh(2,or_i(pk(A),pk(B)),a:or_i(pk(C),pk(D))) is "e" even though each or_i child has two unconditional dissatisfactions, giving the threshold four; the opposite of the "unique unconditional dissatisfaction" the description promises. (Confirmed by spending or_d(thresh(...),pk(E)) through its second branch: all four witnesses, differing only in the two branch-selector bytes, are accepted by the script engine.)
Nothing is wrong with the rule. Such a threshold fails the "e" requirement that the malleability table imposes for non-malleability, and non-malleability is conjunctive, so the expression and everything containing it is malleable either way; the property value is a don't-care there. This just says so, so that implementations agreeing on those values are not read as contradicting the descriptions.
Prompted by bitcoin/bitcoin#36028 and the BIP 379 test vector PR, where the type of a malleable expression has to be agreed on as well.
I'm going to create a PR soon that updates rust-bitcoin to align with this change and bitcoin/bitcoin#36028 (and https://github.com/btcsuite/btcd/pull/2592 is updated as well).
cc @sipa, @apoelstra