Problem
When a managed session's provider process dies, the supervisor detects it precisely and then does nothing. There is no manifest replay and no restart. Detection is implemented; recovery is not.
Evidence
Linux host, convoy 0.2.0-ts.0, isolated network, one declared agent with both limbs running under a hosted convoy up.
Killing the provider process produced an immediate and correct diagnosis:
worker crash <host>.w1 (vanished (hard death — no exit record)) — dinged 0 orchestrator(s)
The supervisor then ran many 30-second reconcile cycles without restarting anything. The provider stayed dead. .convoy/pty.toml was present and valid the whole time.
Worth stating explicitly, because it is the good news: the detection is genuinely precise — it distinguished a hard death with no exit record, and it did so promptly. The gap is purely what happens next.
Why this matters
The manifest is described as a launch spec that a session can be replayed from — that is what makes a managed session survivable rather than something an operator has to babysit. Without replay:
- an unattended role does not come back from a crash, a provider OOM, or a host reboot
- the manifest's value is limited to initial launch
- an operator has to notice and intervene manually, which is exactly what hosting was meant to remove
This compounds badly with the sidecar liveness defect (compoundingtech/smalltalk#101): the provider stays dead and the bus keeps reporting it healthy. Together they mean a crashed always-on session fails silently and stays failed. Either one alone is recoverable by an attentive operator; both together are not.
Proposed direction
The reconcile loop already knows the session is dead and already has the manifest. The minimal change is for the crash path to replay .convoy/pty.toml rather than only reporting.
Things worth deciding rather than assuming:
- Restart policy. Unconditional restart risks a crash loop against a genuinely broken config. Some backoff and a give-up threshold probably belong here — there is already a flapping cap in
convoy up, so possibly this reuses it.
- Which limbs. If only the provider died, does the existing Ding get reused or torn down and relaunched with it? Relaunching both is simpler to reason about; reusing risks a sidecar bound to a stale target.
- Cold boot on replay. Replay should presumably cold-boot from external context rather than pinning a provider transcript, consistent with the manifest being a launch spec rather than a conversation pin. Worth confirming that is the intent.
What I would like consensus on
- Is recovery-on-death in scope for the supervisor, or is it deliberately delegated to an external process manager? If delegated, that should probably be documented, since the crash log reads as though convoy intends to handle it.
- If in scope: restart policy — unconditional, backoff, or capped attempts before it stays down and escalates?
- On a provider-only death, relaunch both limbs or reattach the survivor?
I can put up a PR for the minimal version (replay the manifest, reuse the existing flapping cap, relaunch both limbs) if that shape sounds right — but the answers to 2 and 3 change the implementation enough that I would rather agree first.
Notes from the same session
Smaller things observed while testing this, filed here as context rather than as asks — happy to split any of them out:
convoy up --once does not pre-trust the agent directory, so the provider sits at the harness trust prompt forever. Hosted convoy up does pre-trust. As-is, --once is not usable headlessly.
convoy init exits 0 after failing to create the CoS, leaving an empty catalog behind.
- Every supervisor log line is printed twice.
Problem
When a managed session's provider process dies, the supervisor detects it precisely and then does nothing. There is no manifest replay and no restart. Detection is implemented; recovery is not.
Evidence
Linux host, convoy
0.2.0-ts.0, isolated network, one declared agent with both limbs running under a hostedconvoy up.Killing the provider process produced an immediate and correct diagnosis:
The supervisor then ran many 30-second reconcile cycles without restarting anything. The provider stayed dead.
.convoy/pty.tomlwas present and valid the whole time.Worth stating explicitly, because it is the good news: the detection is genuinely precise — it distinguished a hard death with no exit record, and it did so promptly. The gap is purely what happens next.
Why this matters
The manifest is described as a launch spec that a session can be replayed from — that is what makes a managed session survivable rather than something an operator has to babysit. Without replay:
This compounds badly with the sidecar liveness defect (compoundingtech/smalltalk#101): the provider stays dead and the bus keeps reporting it healthy. Together they mean a crashed always-on session fails silently and stays failed. Either one alone is recoverable by an attentive operator; both together are not.
Proposed direction
The reconcile loop already knows the session is dead and already has the manifest. The minimal change is for the crash path to replay
.convoy/pty.tomlrather than only reporting.Things worth deciding rather than assuming:
convoy up, so possibly this reuses it.What I would like consensus on
I can put up a PR for the minimal version (replay the manifest, reuse the existing flapping cap, relaunch both limbs) if that shape sounds right — but the answers to 2 and 3 change the implementation enough that I would rather agree first.
Notes from the same session
Smaller things observed while testing this, filed here as context rather than as asks — happy to split any of them out:
convoy up --oncedoes not pre-trust the agent directory, so the provider sits at the harness trust prompt forever. Hostedconvoy updoes pre-trust. As-is,--onceis not usable headlessly.convoy initexits 0 after failing to create the CoS, leaving an empty catalog behind.