I agree. The reason we stick with OTP, is that OTP behaviors like gen_server handle two system-level concerns that "raw" Erlang code doesn't:
1. OTP behaviors integrate with the OTP supervisor lifecycle management system (i.e. the OTP framework offers the supervisors standardized hooks to start up and shut down your process, guaranteeing that the errors generated during such steps will be in a format the supervisor can use);
2. Processes that implement OTP behaviors will react to `sys` messages; and so can be debugged, hibernated, code-upgraded, etc. on a framework level, "between" the times the process runs developer-defined code, without the developer having to write such handlers into their module.
This is all accomplished by passing control over the receive loop to a framework — `proc_lib` in this case — which in turn passes any messages it doesn't recognize back to your process. It's an inversion-of-control: proc_lib "is" your process; gen_server or whatever is a delegate of proc_lib; and your module is the delegate for gen_server. It's like an OOP class hierarchy in a GUI system, where the base class handles some events, subclasses handle others, and then your module only has to handle the few it's interested in.
But, if there was a way to do exactly that — to specialize one receive statement, defined in some other function, with your own additional clauses — then we wouldn't need the inversion-of-control framework of OTP! We could just write a regular receive statement that "points to" another receive statement as its "parent" or "fallback" (sort of like a chain of firewall rules, each pointing to the next as "what to check next if this one didn't handle it.") Ideally, the compiled result would be one fused receive statement that has all the clauses from all its parents.
And if you think about it, that's totally possible, even if Erlang itself doesn't offer a fancy chainable receive statement like that... because, in a language like Elixir tht has hygenic macros, you can use macros to generate such "fused receive statements"!
I'm honestly really surprised nobody has yet tried. I realized the possibility of this a couple years back, and have been waiting with baited breath for somebody to attempt it. If it worked out, this "tech" could be used to build a wholly-different-feeling language.