原です。

>なかだです。

>'_'で始まる変数はブロックローカルにするとか。

'!' で終わる変数をブロックローカルにするのは?

既に似た案があるのは承知ですが、見た目が違うのでもう一度。
こういうのはいかが?

(0)今までのローカル変数に対しては互換とする。

(1)ブロックローカル変数の名前には ! を使う。

def foo
   yield 1
end

x!, y! = 0, 0
foo { |x!|
   p [x!, y!] #=> [1, 0]
   y! = 1
}
p [x!, y!] #=> [0, 0]


(2)外側のブロックローカル変数への代入は := を使う。

x! = 0
foo {
   x! := 1
}
p x! #=> 1


(3):= がアクセスする定義済みブロックローカル変数は、外で最も近いもの。

x! = 0
foo {
   x! = 1
   x! := 10
   p x! #=> 1
   foo {
     foo {
       x! := 3
     }
     p x! #=> 3
   }
   p x! #=> 3
}
p x! #=> 10
# x! := -1 #=> NG


(4)未定義ブロックローカル変数と未定義ローカル変数に対する
ブロック内部における := は、トップレベルでの定義と解釈する。

foo {
   t! = 1
   t = 1
   foo {
     t!, u!, t, u := 2, 2, 2, 2
     p [t!, u!, t, u] #=> [2, 2, 2, 2]
   }
   p [t!, u!, t, u] #=> [2, 2, 2, 2]
}
#t! #=> undefined
#t  #=> undefined
p [u!, u] #=> [2, 2]


(5)定義済みローカル変数に対する := は = と同値。


最後に

(6)隙を見て x と x! の記法の役割を交換する。:-)