To me, starting a service expresses the intent: This service should be running. What the underlying process is is of no concern; a service is an abstraction of an OS process, not the process itself. The service's "target state" drives what to do with the process. I want to the service to be running, irrespective of what the underlying process is, which means that a process dying just implies it must be started again.
This functionality belongs in the init system first because it's closest to the source, secondly because it's such a common requirement that it belongs there. Sure, one can argue the technical design; respawning can be a separate subsystem forked from the init, for example. But it should be an integral feature of the init system, not something I have to get from a third party. To paraphrase Jobs, it's a feature, not a product.
This conflation of "target state" and "actual state" is something that so many apps get wrong. For example, consider an FTP client or an IM client: If I connect to a remote server and the connection fails, the app should not require me to manually connect again. I, as a user, has expressed the intent that I wanted to be connected. That's my target state. Whether that state is reachable is the concern of the underlying connection manager. The underlying connection is just an implementation detail. Imagine if the lights and all your electrical appliances didn't automatically come back on after the power went out.
In other words, high-level abstractions should always attempt to be seamless.