The check you are thinking of is envelope-only. mustMatchSender runs at MAIL FROM and compares that address against what you authenticated as; it returns a 501 if they disagree and never looks at the From: header in the message body. Keeping those separate is deliberate, because forwarding and list resending legitimately need a From: that differs from the envelope.
The addresses that count as yours are: your own address, every enabled alias on your domains, and the addresses of any Group you belong to. A mailing list is not a group in that sense. A MailingList object holds bare addresses with no link back to an account, and it only rewrites the recipient side, so being on one never authorizes you to send as it. If the address you can send as belongs to a Group you are a member of, that explains it; if it is a MailingList, it should not be accepted as an envelope at all.
Now the part that ties your three cases together: DKIM signs with the envelope domain, not the header domain. So whatever ends up in MAIL FROM decides both the domain SPF is checked against and the d= on the signature, and the receiver’s DMARC check then asks whether either of those lines up with the From: header it sees. Your case 1b passes because the envelope is still your own address on the same domain as the spoofed From:, so everything aligns. So does the reply case. The one that fails has to be a case where the From: domain aligns with nothing that was authenticated, which usually means the list address is on a domain this server does not treat as local, so it goes out unsigned and SPF for that domain does not list your IP.
To say which of those it is for your setup I need headers: Return-Path, From, the DKIM-Signature d= and Authentication-Results from one rejected message and one accepted reply, plus whether that list is a MailingList or a Group and which domain it is on.
On knowing who replied: Stalwart does not add a Sender: header, rewrite From: for list posts, or seal with ARC. A client can set Sender: itself and most will show “on behalf of” when it is present, but nothing on the server side will do it for you. If you want the From: header policed as well as the envelope, that is a DATA-stage filter comparing the header against env.authenticated_as.