I am fine either way and slightly prefer the softer approach of capping it to 100 instead of asserting that it is <=100. There was a discussion some time ago about crashing the program way too easily and reserving the assert/crash only for cases where the continuation of the program really does not make sense. I kind of agree with that.
Yes, Assume() is some middle ground between assert() and the softer approach. Assume() + cap in release builds looks reasonable to me too. Plus document it properly: "make sure you never pass >100 or you will crash the program" ... hmm, could this end up in all callers doing the cap at the call site before calling GetAddr() to make sure to avoid a crash?
Do you remember the bug number? "The reason max_pct exists is not to reveal the entire addrman", but then passing even == 100 is a bug?
If you will be touching this, there is this minor mostly theoretical thing: max_pct * nNodes could overflow and I guess max_pct * nNodes / 100 could end up with a lower value than nNodes for some very high input max_pct. So, if you will be touching this, maybe it is "safer" to implement the cap as:
max_pct = std::min(max_pct, 100);
nNodes = max_pct * nNodes / 100;
(this occurred to me just recently)