my point was there's more going on, on other threads, that's how KVO works; when the notification transaction is complete ("did" change) another thread is spawned on -observe which then reads the EDID and generates the DDC objects which are what cause the KP.
at any rate, it doesn't matter anymore, PJALM very graciously set up an NVidia MacPro for me to test remotely, and we managed to get it working on NVidia. There are definitely some more features to add, namely enumerating the I2C interfaces in IOReg to get their data before making requests, but that shouldn't matter much right now. Interestingly, NVidia cards support a second, private communications flag which I can't find anywhere in the documentation. At the very least it helps identify NVidia cards within the app.
The biggest issue is NVidia seems to interpret minReplyDelay differently; where a value of 30 * kMillisecondScale is appropriate for ATI/AMD and doesn't require running the same request several times, 30 is a more appropriate value for NVidia, and 0 still returns a garbage response. If true, this means that DDC Panel never actually KPed an NVidia machine, the kernel was simply waiting 1000 * 1000 times longer for the DDC/CI reply.
Timing is very important for I2C buses as I've been reading, so a "good" value here is critical. If the reply is taken too early, the data will be garbage and fail to checksum, too long and it may mimic a Kernel Panic. Running several successful requests in series is the only real test. Feel free to try different values and report back.
I've also started polishing the app, removing unnecessary entries, and following code guidelines.
--edit
For reference, I tried a very large delay on my AMD 6570 and the result was very much like a KP, except for the time() output i placed around the request call. 30 * kSecondScale does produce a 30sec delay per-request (calculated using time()), and during the delay there was no activity except my CPU fan spun up. In fact, there appears to be a gap in my system log.