A. Is this a wallet rule or a protocol/daemon rule?
It's a wallet / daemon rule. The number of blocks is defined as a pre-compiler constant
B. Does the rule only apply to spending one's own output, or are new/locked outputs also excludable from a ring signature even as decoys/mixins?
Generally, it applies to all outputs. So if you change the constant for both the daemon and the wallet, then you could have both the real one and the decoy of the age younger than usual.
In my experiment, I used a normal daemon and modded wallet. Since the daemon was using the usual setting of 10, and the daemon gives fake outputs to the wallet via RPC, it means that only the real one could be younger than 10. If I ran the daemon with the mod, they could (in theory) all be younger than 10.
C. If someone clones the Monero repository and removes the 10-block lock requirement...
I just did that to test and successfully sent 3 TX-es in succession, all using the
CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE of 1.
So yeah, it can easily be done by changing that one line of code, and transactions made with the modded wallet will stick unless some reorg happens.
It's the same for both 1. and 2. because the network can't know whether the 1-block-old output is a decoy or the real one.
Note that by making such TX-es you'd stand out from the crowd, and it would probably be easy to tell that the same person did a few TX-es in a row if they're all spaced <10 blocks.
One could ask, but why isn't it set to 1 then?
Problem is, the input one-time keys are referenced using an offset. If a re-org would swap the order of transactions, then the transaction referencing any one-time key at the wrong offset would become invalid and would never confirm.