The variable redeclared in the outermost block of a substatement

No.

You're missing the block scope introduced by the else substatement:

[stmt.selected.general/2]: The substatement in a selection-statement (each substatement, in the else form of the if statement) implicitly defines a block scope ([basic.scope]). If the substatement in a selection-statement is a single statement and not a compound-statement, it is as if it was rewritten to be a compound-statement containing the original substatement. [..]

i.e. your code is really:

#include <iostream>

int main()
{
  int b = 2;
  if (int a = 0) {
  }
  else {
    if (b == 2) {
       int a;
    }
  }
}

Thus, the block you're looking at (the one introduced by the nested if) is not the "outermost" block in question. So, though a is in scope within that block, it can be shadowed.

This does mean you can't declare an a inside a "naked" else, i.e. the following is ill-formed:

#include <iostream>

int main()
{
  int b = 2;
  if (int a = 0) {
  }
  else {
    int a;
  }
}

/*
prog.cpp: In function ‘int main()’:
prog.cpp:9:9: error: redeclaration of ‘int a’
     int a;
         ^
prog.cpp:6:11: note: ‘int a’ previously declared here
   if (int a = 0) {
*/

The statement in stmt.stmt#stmt.pre-5 explicitly says:

[Note 2: A name introduced in a selection-statement or iteration-statement outside of any substatement is in scope from its point of declaration until the end of the statement's substatements. Such a name cannot be redeclared in the outermost block of any of the substatements ([basic.scope.block]). — end note]

The key term here is outermost block which is defined in stmt.block#1:

A compound statement (also known as a block) groups a sequence of statements into a single statement.

compound-statement:

{ statement-seq opt }

...

A compound statement defines a block scope.

So stmt.stmt#stmt.pre-5 is essentially saying:

if (int a = 0) 
{  // outermost block
  int a;  // so ill-formed  
} 

but

if (int a = 0) 
{  // outermost block 
 {  // inner block
   int a;  // so well-formed 
 }  
} 

The same rules apply in your example with the block introduced by the nested if statement.