The bits field must have the exact expected value, otherwise the block gets rejected (ignored) by the nodes.
Harder or lighter - doesn't matter, it would be still invalid.
That's what I assumed, but I hadn't taken the time to go find the lines of code in Core that make that comparison. Since you seem to have found it, can you link to it here please, and save me the time of searching for it?
I saw it long ago, needing to know how to implement it inside my shit.
It's moved all around the code base ever since, but look for the place where GetNextWorkRequired() is called from.
ATM it's in file validation.cpp:
{
const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
// Check proof of work
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work");