I believe you are saying:
1) `isinstance(X(), P)` succeeds when it should fail, because X doesn't have `protocol_member` defined.
2) Protocols are not ABCs at runtime when PEP 544 says they should be.
I'm not one of the authors of PEP 544, so I can't give insight into why things are so.
For 1:
As noted by Ken Jin in the bug you linked, PEP 544 is concerned with Protocols as a static type checking concept, not a runtime concept. One reason is that this is impossible in some cases, such as due to type erasure. For example, even though `complex` implements `__float__`, it does not implement the SupportsFloat protocol, because complex's `__float__` signature differs from the SupportsFloat signature. This cannot be checked at runtime, because the type annotations are erased.
Your example, with `P.protocol_member`, shows another case. Because `protocol_member` has no default value, it is never stored in `P`. (i.e. `hasattr(P, 'protocol_member') is False.) Therefore it cannot be checked at runtime. Static type checkers don't drop annotated values like this, so a static type checker can evaluate `isinstance(X(), P)` correctly.
As PEP 544
says:
"All structural subtyping checks will be performed by static type checkers, such as mypy [mypy]. No additional support for protocol validation will be provided at runtime."
That said, I am a little confused as to why `isinstance(X(), P)` succeeds at all, because PEP 544 says "The default semantics is that isinstance() and issubclass() fail for protocol types." P should need to be decorated with `@runtime_checkable` for this to work.
For 2:
Protocols aren't literally instances of abc.ABCMeta, but they're still abstract base classes: they can't be instantiated and they define an interface that subclasses should implement. Saying they aren't ABCs at runtime is splitting hairs.