I'll repeat bcobb's recommendation for Working Effectively with Legacy Code. It's the bible.
In my Let's Code JavaScript screencast, I've recently started a three-part special on legacy JavaScript code. It follows my efforts to "do it live" with actual legacy code someone else wrote. You might find it useful. (Full disclosure: subscription required, and parts II and III don't come out until April 4th and May 2nd.) http://www.letscodejavascript.com/v3/episodes/lab/6
Edit: I just realized that you already said you're using Feathers' book, and that the challenge isn't technical, it's planning and communication. Let me try again:
Part of that is just "the way it is." At the risk of sounding snarky, I imagine you could plan fairly effectively ("we have huge error bars because our velocity is unpredictable, so given backlog X, we're confident we'll be done sometime within 3-12 months"). See the "Risk Management" and "Slack" sections of AoAD for that.
I also imagine you could communicate that fairly easily ("given our three month estimate, we think we have a 50/50 shot of being done in six months and we're almost certain of being done in less than 12").
For many teams I work with, the problem isn't planning or communication, the problem is that reality isn't conforming to stakeholders' wishes. And there's no way to make it conform. (Short of kicking the problem down the road by accumulating more debt while you search for a new job.)
So how do you break the news?
One way is to, um, not. At this point, stakeholders are used to delays and bugs. The status quo ("we'll pretend to follow your schedule, and you'll pretend to believe us") can be comforting. It might be useful to stick with that.
Another way is to ramp up the frequency of delivery so much that the error bars are less noticeable. An estimate to deliver in 3-12 business days is less painful than an estimate of 3-12 months.
A third option is to negotiate for scope rather than schedule. "We'll absolutely deliver in three months. It might be tiny. That's because of technical debt." (I'm less fond of this approach than I used to be. Negotiating scope makes stakeholders profoundly uncomfortable in a way that slipping dates doesn't, for some reason. Perhaps because they see it as an attempt to weasel out of producing anything.)
Another approach is to stop estimating entirely. "We're working on Feature X and we'll tell you when it's done."
There's also simply explaining the situation: the cynical approach ("we have a ton of technical debt because of the decisions your predecessor made, isn't it great you're here now") or the enlightened approach ("we've got a technical debt problem, it has effects W, T, and F; we're addressing it with P, D, and Q; you can expect consequences O, M, G; we're preventing it from happening again with techniques S, L, A, C, and K.").
I'll typically use some combination of the above depending on the audience.
(I'm in a weird mood. Sorry if this came across as uncaring. The ideas are serious even if the tone is not.)
Thanks for the detailed reply! I understood your intent, don't worry about the tone.
We're a small enough team that we all understand the business drivers. The main goal of our agile transition is to improve predictability and clarity. Month-wide error bars on a three-month release don't help those goals much.
Right now we're working to shorten our release cycle and learn how to communicate clearly even when it hurts, on the assumption that shining light on the difficulties will help us find and solve the problems as quickly as possible. But it's definitely a painful transition.
One more point: I agree that negotiating scope with a fixed schedule is difficult. We have done that occasionally. But sales and business people are definitely more willing to accept schedule slippage than scope reduction.
In my Let's Code JavaScript screencast, I've recently started a three-part special on legacy JavaScript code. It follows my efforts to "do it live" with actual legacy code someone else wrote. You might find it useful. (Full disclosure: subscription required, and parts II and III don't come out until April 4th and May 2nd.) http://www.letscodejavascript.com/v3/episodes/lab/6
Edit: I just realized that you already said you're using Feathers' book, and that the challenge isn't technical, it's planning and communication. Let me try again:
Part of that is just "the way it is." At the risk of sounding snarky, I imagine you could plan fairly effectively ("we have huge error bars because our velocity is unpredictable, so given backlog X, we're confident we'll be done sometime within 3-12 months"). See the "Risk Management" and "Slack" sections of AoAD for that.
I also imagine you could communicate that fairly easily ("given our three month estimate, we think we have a 50/50 shot of being done in six months and we're almost certain of being done in less than 12").
For many teams I work with, the problem isn't planning or communication, the problem is that reality isn't conforming to stakeholders' wishes. And there's no way to make it conform. (Short of kicking the problem down the road by accumulating more debt while you search for a new job.)
So how do you break the news?
One way is to, um, not. At this point, stakeholders are used to delays and bugs. The status quo ("we'll pretend to follow your schedule, and you'll pretend to believe us") can be comforting. It might be useful to stick with that.
Another way is to ramp up the frequency of delivery so much that the error bars are less noticeable. An estimate to deliver in 3-12 business days is less painful than an estimate of 3-12 months.
A third option is to negotiate for scope rather than schedule. "We'll absolutely deliver in three months. It might be tiny. That's because of technical debt." (I'm less fond of this approach than I used to be. Negotiating scope makes stakeholders profoundly uncomfortable in a way that slipping dates doesn't, for some reason. Perhaps because they see it as an attempt to weasel out of producing anything.)
Another approach is to stop estimating entirely. "We're working on Feature X and we'll tell you when it's done."
There's also simply explaining the situation: the cynical approach ("we have a ton of technical debt because of the decisions your predecessor made, isn't it great you're here now") or the enlightened approach ("we've got a technical debt problem, it has effects W, T, and F; we're addressing it with P, D, and Q; you can expect consequences O, M, G; we're preventing it from happening again with techniques S, L, A, C, and K.").
I'll typically use some combination of the above depending on the audience.
(I'm in a weird mood. Sorry if this came across as uncaring. The ideas are serious even if the tone is not.)