Hi Troy,
no apologies necessary. We did talk about it in Denver, but it's not rare that people "zone out" when processing that much information ;-)
Axon uses optimistic concurrency whatever the approach is. Aggregates emit events using a sequence number. If two different instances (on different nodes, for example) emit events simultaneously, they will use the same sequence number, causing a conflict.
However, this does not take into account that users look at data, spend some time thinking about the next action and then submit their decision in case of a command. This is where conflict resolution comes in. While this user was thinking, someone else might have made a decision as well. Let's call this user A, and the one that took too long thinking B.
When B's command arrives, it will carry an @TargetAggregateVersion annotated field. An aggregate is loaded. The version of that aggregate will be higher than @TargetAggregateVersion of B, because A has made a change in the meantime. Big question is: is that a problem. The conflict resolver will receive the events that A produced to make it's decision. If it's not a problem, B's events are just appended. Otherwise, an exception is thrown.
The remark I made about "not seeing the case" was rather that I personally didn't need this in any of the projects I was directly involved with. That's because conflict could be mapped to the current state, as opposed to "unseen" changes. That doesn't mean they aren't there. In fact, I've heard of some interesting cases where conflict resolution was a great means.
Hope this clarifies things for you.
Cheers,
Allard