Nick, I just did the following and it worked the way I would have expected...
1) Created a stored proc that I knew would generate an error
2) Created a small SSIS package with an Execute SQL Task that runs the stored proc
3) Dragged a dummy task to the right of the SSIS package, and connected the 2 with a precedence constraint so that the dummy task would fire if the execute sql task errored out
When I run the package, the execute sql task fails, but then control goes to the dummy task (as I would have expected)
There's only one thing I can think of that would keep the dummy task from running - if I did an override of the FailPackageOnFaillure properties such that it caused SSIS not to execute the dummy package on the failure of the execute sql task.
Let me know if that helps.