Writing the typing.Protocol before the class that satisfies it
When I pull an implementation out from behind a pile of call sites, I now write the typing.Protocol first and the class that satisfies it second. Define the seam, annotate the call sites against it, run mypy, and every place the current shape is wrong shows up before the new code exists. If the concrete class then inherits the protocol explicitly, mypy checks the implementation against it at the class definition, not only where it gets passed.
This feels Python-specific because duck typing usually leaves nothing to review. The implicit interface is whatever the callers happen to touch, spread over however many files. Writing it down turns it into something a colleague can read and disagree with before the work happens.
None of it is enforced at runtime. PEP 544 imposes no runtime semantics on protocol annotations, and even with u/runtime_checkable the typing docs say isinstance only checks that the named attributes exist, not their signatures.
It is cheap to try on one seam. The plan step in verdent works the same way, clarifying questions first and a plan you approve before any code is written. Nothing forces the protocol to change when the implementation does, so the two drift. Curious whether people keep the protocol next to the consumer or next to the implementation.