I'm doing some deeper research into historical consensus changes and it seems like most folks consider the addition of the OP_NOP codes to be a hard fork. Here's the diff for their addition: https://github.com/bitcoin/bitcoin/commit/a75560d828464c3f1138f52cf247e956fc8f937d#
However, some time ago gmax mentioned to me that it was effectively a soft fork because older clients ignored unknown opcodes. After perusing the code I can see why that might be the case, but I could use some input to gain consensus from people with superior C++ skills.