$() preserva o status de saída; você só precisa usá-lo em uma declaração que não tenha status próprio, como uma atribuição.
output=$(inner)
Depois disso, $? conterá o status de saída de inner e você poderá usar todos os tipos de verificações para ele:
output=$(inner) || exit $?
echo $output
Ou:
if ! output=$(inner); then
exit $?
fi
echo $output
Ou:
if output=$(inner); then
echo $output
else
exit $?
fi
(Nota: Um exit sem argumentos equivale a exit $? - ou seja, ele sai com o status de saída do último comando. Eu usei o segundo formulário apenas para clareza).
Além disso, para o registro: source é completamente não relacionado neste caso. Você pode definir apenas inner() no arquivo outer-scope.sh , com os mesmos resultados.