After searching, I have not found any resolution for this problem. Is there one?
In the meantime, for my own purposes I have altered the plugin to so that "optional=true" works recursively, simply by checking for existence of optional artifacts in the dependency trail of all resolved artifacts.
This finally gives me what I consider desired (at least tolerable) behavior:
scope:compile = classpath and WEB-INF/lib (though cp is not necessary, it doesn't hurt)
scope:provided = no classpath, no WEB-INF/lib
optional = transitively resolved artifacts on classpath, no WEB-INF/lib
I know this is just furthering a hack, but I'm not sure how else to do it since there seems to be an inherent containment issue where war shouldn't know about the ear. Where I work, we use what we consider a "best practice" approach where ear, war, sar, etc. projects are siblings, with a parent "server" pom project providing all container-based scope=provided dependencies. This primarily filters all container-provided compile dependencies used by core components, greatly simplifying the poms of the container-based components. I know it may be a stretch, but perhaps such a "container" parent project could be somehow formalized, at least to provided a way to formally put the ear before the war? Just a thought...