> Make's semantics are to invoke the shell at EVERY LINE. This is slow [...]
I assume you mean commands here? Actually, how slow is it? Ever measured it? I am sure me writing this line took more time than they could save by a rewrite over the course of a few years of using the performance optimized version.
> Shell also has local variables for modularity, and better constructs for conditionals and iterations
And variables in make that you set for a command are only visible to it. Besides - wasn't your point that the OP should not use make because s/he does not use its features?
> 'set -o errexit' makes bash fail on errors
Indeed it does, it was just missing from your better version.
> Another pattern I find useful is to have the actions take more arguments [...] The arguments to Make are actually TARGETS/files and not functions, so I don't think you can do this.
Yes, one communicates with make through variables, not through arguments.
Over the last 20 or so years I've done my fair share of shell scripting and of writing makefiles. Maybe I am just too old and boring to get excited over this, but let me recap: The OP happens to be using make, s/he used an elegant hack to have the file document itself and its usage. S/He wrote about the latter. No, I am not impressed by the post - I used a similar technique in 2003 or 2004 to bootstrap the documentation of a very complex build system - and I'm sure others have before and after me. But I like the concise article.
Debating whether make is "better" than "sh" is completely off-topic here - if there was a universal truth we'd not have seen tools like psh, scsh and the rest of language-specific shell substitutes nor would we have the myriad of language-specific build tools. Back then, when I was young and naive, I've implemented a few of those myself. But now I am not young anymore. And now I naively believe that people should use what they are most productive with. Or everybody come to their senses and just use lisp.