No, goroutines can't be killed. They don't even have a handle (as I pointed out in the package docs), so there's no way to address them once started, unless the routines cooperate.

I honestly think the explanation is simpler. You can always "get a panic in your code"; that's just part of Go. I mean... of course you can always come up with a more complex description but, in the end, the rules are quite "natural":

1. Tasks are subject to be cancelled through a pm-specific panic.
2. You can prevent that panic from passing `Done()` using an option.
3. All other panics work just as expected.

I think (correct me if I'm wrong) that I made the behavior clear in the package documentation. There's nothing surprising to item 1, precisely because routines can't be killed in Go.

Regarding cleanup... I don't see how you'd need to duplicate code. Your deferred function will run just like `Done()` does. The only "problem" I see is if your function relies on panics to cleanup *and* you deferred your function prior to `Done()` (so that the later will run first) *and* you set `StopCancelPanic`. But:

1. You shouldn't be cleaning up *only* if you see a panic. A deferred cleanup function should cleanup no matter the exit conditions, i.e., a `recover()` shouldn't be involved. Otherwise you may not be properly disposing resources on normal/successful exit, unless you also write the cleanup code in every `return` (thus defeating the purpose of `defer`).
2. If you're faced with such a scenario, you're already recovering panics. Then why using pm's feature to recover from cancellations? It's wiser to reset `StopCancelPanic` and do the handling yourself. In that case there are no special conditions for panics inside pm. All panics will reach your application code, even after `Done()` is done.
3. Let's say you really want to depend on panics for your application cleanup (item 1 above) *and* you want pm to prevent cancellation-related panics from reaching your code (item 2). Then you can always defer calls in the reverse order. That is, you should `Start()` as soon as the task starts and defer a call to `Done()` prior to any other defer. Then, `Done()` will be the last function to run and therefore you have a chance to catch panics in your other deferred functions, no matter the setting for `StopCancelPanic`. This is the most recommended approach in my opinion.

As for panics in worker routines: you're not supposed to call `Status()` from other routines spawned from your main task. I thought about that and, honestly, the more I did the more I convinced myself it was a bad idea, precisely because of what you say. The problem is that there's no nice solution. In the code you wrote (current master) panics would be called only if you invoked the result from `Status()`. That gives you some degree of control; you can make the call only in your task's main routine. But in my opinion, that's error-prone to say the least. The extra parenthesis are too easy to overlook, making debug harder. With that, there's the possibility to miss a cancellation point or, yet worse, call the panic-launch function from a worker routine that was not intended to.

If we really wish to update the status from multiple routines (and panics are the only reason not to do it), I'd use separate status functions: one specified as a cancellation point and the other one not. That's in many aspects equivalent to the parentheses, but it's easier to see and the panic (for the cancellation-point version) is still thrown in a well-defined location. However, I still don't like it. Asynchronous worker routines should communicate in a way or another with the main routine, so the later should have an idea of current activities and could thus post the `Status()` itself.

I do agree with adding an additional feature to prevent some routines to be cancelled. That should be an option to `Start()`.