D166 - A test asserted the opposite of what sceKernelClearEventFlag does, and the stub agreed

015-sync/event-flag-round-trip asserted the opposite of what sceKernelClearEventFlag does, and the host build agreed with it because the host stub had been written to the same misreading.

Two implementations failed it with the same message - "a cleared bit still polls as set" - while the host alone passed. They were right.

// shadPS4, event_flag.cpp
void Clear(u64 bits) { m_bits &= bits; }
// PS5PCEM, kernel_runtime.zig
// The PS5 ABI supplies the bits to retain, not the bits to remove.
object.bits &= mask;

The argument is a mask of what to keep. clear(BIT_A) retains BIT_A and clears everything else, so a bit that was set and then "cleared" is correctly still set. The check called that a failure.

Why the host build did not catch it

Because the host stub was written the same day, to the same misreading, and its comment named the correct semantics before implementing the opposite:

The vendor call clears the bits not named - it is a mask of what to keep […] Here it does the reading a caller would expect from the name, because a host stub is a known-good implementation of the obvious semantics.

That reasoning is backwards. Principle 5 says a check that has not passed a known-good implementation is not evidence - and its force comes entirely from the implementation being correct. A known-good implementation of the wrong contract is worse than none: it manufactures exactly the confidence the rule exists to supply. The check passed on the host, looked validated, and was wrong.

Fixed to &= bits, and all three now agree.

The check now distinguishes the two readings, which it could not before

Clearing a single bit cannot tell them apart. Set A, clear A: under keep-mask semantics A survives; under clear-mask semantics A goes. One bit changes state either way, so a check watching one bit sees a plausible answer whichever contract is true. That is how this survived.

So the sequence sets two bits and keeps one: A stays, B goes. Then an empty retain mask clears everything, which is the strongest single statement of what the argument means and is nonsense under the other reading.

The provenance was the highest in the suite, and it was the wrong one

This was the only check of 146 carrying OBS_FROM_DOCUMENTED - "vendor interface documentation describes this behaviour specifically". The one check claiming a document described it had it backwards.

Downgraded to OBS_FROM_ASSUMED, and that is not a comfortable fit either. What supports it now is two independent open-source implementations agreeing, one commenting explicitly on the convention. The ladder has no rung for that, and it is the same gap the sibling project raised about measured - a value that covers "somebody actually established this, just not from the authority the grade names". We declined to add one for measurement on the argument that the origin field carries it as data; there is no equivalent escape hatch on the documentation axis, and this is the second time that has cost something. Worth reopening rather than settling here.

ASSUMED understates the evidence. DOCUMENTED overstates it by claiming a citation nobody here can produce. Overstating is what went wrong, so it understates, with both sources named in the comment.

What actually found it

Three-way consensus, and it only became legible today. The host stubs for event-flag set/clear/poll were added this morning (D-relational-host-stubs work); before that the host skipped this check, so consensus saw two opinions rather than three and had no majority to report. Adding a third implementation turned an unreadable comparison into host alone says pass.

That is the substitute-oracle argument working exactly as BACKLOG §12 describes it - with the uncomfortable detail that the outlier was us.