Q:

How does JS variable override work?

This code works fine:
const a = 1;
{
  const b = a; // let's use "a" in a sub-scope
}
{
  const a = 2; // let's override "a" in another sub-scope
}

... but this code fails with a is not defined at line 3:
const a = 1;
{
  const b = a; // let's use "a" in a sub-scope <<< CRASH!! >>>
  const a = 2; // let's override "a" in the same sub-scope
}

I tested this on node 7.7.4. It may be related to V8 only, I'm curious how Firefox would handle this.
Is it related to the way variable declaration is defined in the JS spec? const/let are not hoisted, but "something" (some metadata?) still seems to be hoisted, else we would have no issues.

A:

Hoisting refers to the notion that variable declarations are hoisted  a to the top of the variable scope.
More accurately, it is a side effect of the  a fact that JavaScript builds it's execution environment  in two passes. 
The first pass sets up all function and variable declarations​. At this stage, variables are declared but not defined, function declarations are declared and defined (that's function declarations: function fnName(){...} not variable function expressions: var fnName = function (){...}).
The second pass then executes the code with the available declared functions and variables (which currently are unassigned and therefore have the value undefined).
var is function scoped and not block scoped.
 Although let andconst allow the declaration of block scoped variables, the code is built using the two execution passes. The difference being that block scope should be considered in the first pass within their own scope (block scope or otherwise).
To illustrate this point, consider your second snippet.
The code throws an error in your second case because after the first pass it could be re-written as:
// const 'a' declared in this outer scope
const a:
a = 1; 

{ 
  // separate const 'a' declared in this block scope
  // Declarations still hoisted for this block scope
  const b, a
  b = a; // a undefined here
  a = 2;
}

