What are the different upgradeability features in the BIP-Taproot (BIP 341) proposal? What are the different upgradability features in the BIP-Taproot (BIP 341) proposal?
Why are there so many upgradability paths? Is there something an annex can do that a leaf version can't?
This question was asked by James Prestwich on Twitter.
There is the annex, leaf version, ext_flag, OP_SUCCESS, unknown pubkey
types and you could probably include the existing witness version too.
I believe that list is exhaustive.
The ext_flag isn't so much an extension mechanism in itself; more a
structure that permits safely reusing the sighashing code (as opposed
to needing a new tag or other mechanism for collision avoidance).

Leaf versions: for revamping script semantics
OP_SUCCESSx: for new opcodes, without coordinating new version
Pubkey types: for new sighash flags/cryptography without needing an explosion of new opcodes
Annex: for effectively adding new fields like nLockTime

Leaf versions were really only added because we had a few bits to
spare in the control block, and it seemed wasteful to reserve them.
They're mostly a convenience, I think, as OP_SUCCESSx can achieve the
same (add an OP_V2 etc).
As the annex isn't committed to by the scriptPubKey, it's more a way
to extend witness possibilities than it is directly a way to add new
semantics.
So is there something an annex can do that a new leaf version can't? I
think they're orthogonal.
For example, a feature where you could restrict a tx to only be valid
in a chain that contains a certain block hash. It can't be done with a
leaf version, as it's a sign-time thing. I believe the annex can't be
used to introduce new script conditions. A new leaf version could
introduce its own annex-like thing, but that wouldn't be able to apply
to old leaf versions.
The motivating example for the annex is this. Imagine a new opcode is
added that needs few bytes but has high CPU cost. You'd want a high
weight budget per such opcode, but that may require actually stuffing
the witness with dummy data just to get the necessary budget. Instead,
it would be nice if there could just be a marker on the input that
says &quot;increment the apparent weight (and corresponding op budget) by
N&quot;, without taking N bytes. Logistically, it would be annoying if that
marker can only be parsed when the spent output is available. The
annex is recognizable without context, mostly by exploiting a thankful
coincidence about what set of witnesses is valid for v0 (first byte of
last witness stack item can only take on certain byte values). This, I
think, can't be accomplished with a new leaf version.

This question was answered by Pieter Wuille on Twitter.