This can look like a bug if you leave out the steps in between, but if you look at what you did in detail, you see that it's kind of what you should expect.
You started with:
if (true)
shout();
Then opened a line, leaving "shout();" hanging.
if (true)
shout();
Then added a brace block, now "shout();" is orphaned.
if (true)
{
}
shout();
Then used dynamic surround to pull the statement back in, "shout();" is double-indented, as expected.
if (true)
{
shout();
}
Dynamic surround doesn't try to be excessively smart. When it pulls code into a block, it indents it, when it pulls it out, it outdents it. If the code was already hanging there at an incorrect indentation level, all dynamic surround will do is pull it into the block at a different incorrect indentation level, as you have observed.
There are times when code is intentionally indented outside of convention. Dynamic surround handles that by assuming that the coder liked the way it was indented before, which is the case 99% of the time, and just wants to pull it inside a block, so it makes minimal modificaitons to the code's indentation level. If dynamic surround had additional logic built into it to re-indent lines intelligently, it might work better for your case where you give dynamic surround incorrectly indented code, and want it fixed, but it was be extremely annoying for the other case where you have code that is indented in a very specific manner and you don't want dynamic surround to drastically reformat it.
Now for a suggustion. What you wanted to do could have been done with only a few keystrokes if you used smart-brace.
Start with:
if (true)
shout();
Put curser where you want the open brace:
if (true)
<cursor> shout();
Type the open brace and let smart-brace fix the statement.
if (true)
{
shout();
}
That will work great as long as you haven't disabled smart-brace / unbrace.