It sounds to me like the return-path header should be added when the message is delivered to its final resting place. When sieve is looking at the message, it hasn't been delivered yet. A sieve script may decide to redirect the message or generate a bounce. In that case, the return-path should not be added to the message because it has not reached its final destination.
When lmtpd writes the message to disk, it is *delivered*.
Yes. Exactly.
But where does return-path come from? Somehow lmtpd knows how to generate that header, but it's not clear to me how it does it.
What I'm getting at is, maybe it is possible to filter on some other header that is equivalent to return-path.
It gets it from the envelope. Hence the envelope extension to sieve; which allows testing not only of that value but of the envelope recipient as well.
-Pat