Para empezar, cambia tu query:
Dim cmd As New SqlCommand("INSERT INTO [Etapas] ([proyecto], [descripcion], [finalizado]) VALUES (@proyecto, @descripcion, @finalizado);
SELECT @@IDENTITY", cnn)
No es necesario que pases el valor @@IDENTITY a una variable... y menos si la variable no fue declarada
Despues, cuando lo ejecutes no usese ExecuteNonQuery()...
Este método, ejecuta la sentencia, sin regresar valor.. (o creo que regresa el numero de registros afectados o algo asi)..
En su lugar, usa ExecuteScalar()
Con este método ejecutas tu query, y regresa la primer columna del primer registro del SELECT que estes ejecutando. En tu caso "Select @@IDENTITY".. te regresara el valor del ID insertado.