Floot restart does not reprovision a terminated per-session CLI client #31

Open
opened 2026-09-01 18:09:26 +09:00 by floot · 0 comments
Owner

Summary

Floot session metadata and conversation history survive daemon or machine restart, but a per-session Codex or Claude client that was explicitly terminated does not recover. The terminated client capability remains stored under its per-session petname, and the restarted Floot factory treats petname existence as proof that the client is usable.

This leaves the session permanently visible but unable to start a new turn. The UI can look wedged even after a full host restart.

Observed

Session mti93nj6-8dakam used codex-client-mti93nj6-8dakam. After CodexClient.terminate():

  • client status reported terminated: true;
  • the Floot session remained in the durable registry;
  • a later NixOS deployment restarted the daemon and host services successfully;
  • the same per-session client capability still reported terminated: true;
  • the session did not reprovision a fresh sandbox and remained stuck in the UI.

Cause

makeCliClientResolver.get() currently returns the existing per-session petname immediately when powers.has(perSession) is true.

It does not inspect client liveness or ask the provisioner to repair a terminated client. Startup startAllInboxes() calls getAgent(), which therefore binds the revived agent to the dead capability.

Expected behavior

A durable Floot session should reopen after daemon or machine restart even when its prior CLI sandbox was terminated or disappeared. Conversation and workspace state should survive according to backend policy; a fresh live client should be provisioned lazily.

Suggested fix

  • Add a liveness check when resolving an existing per-session CLI client.
  • If status is terminated, missing, or otherwise unusable, ask the session provisioner to replace or recreate it instead of returning it.
  • Make replacement preserve the session workspace and backend conversation identity where available.
  • Surface an explicit recoverable error if reprovisioning fails rather than leaving a permanently pending turn.
  • Apply the same contract to Claude and Codex resolvers.

Acceptance criteria

  • Terminate a per-session Codex client, restart the daemon, and start another turn in the same Floot session successfully.
  • Repeat for Claude.
  • Session history remains present.
  • No stale terminated client is returned solely because its petname exists.
  • Add a restart/reprovision regression test.

Related to #30, but distinct: #30 covers in-flight turn, MCP bridge, and secret-request recovery across restart; this issue covers recovery of the underlying per-session CLI client after explicit termination or loss.

## Summary Floot session metadata and conversation history survive daemon or machine restart, but a per-session Codex or Claude client that was explicitly terminated does not recover. The terminated client capability remains stored under its per-session petname, and the restarted Floot factory treats petname existence as proof that the client is usable. This leaves the session permanently visible but unable to start a new turn. The UI can look wedged even after a full host restart. ## Observed Session mti93nj6-8dakam used codex-client-mti93nj6-8dakam. After CodexClient.terminate(): - client status reported terminated: true; - the Floot session remained in the durable registry; - a later NixOS deployment restarted the daemon and host services successfully; - the same per-session client capability still reported terminated: true; - the session did not reprovision a fresh sandbox and remained stuck in the UI. ## Cause makeCliClientResolver.get() currently returns the existing per-session petname immediately when powers.has(perSession) is true. It does not inspect client liveness or ask the provisioner to repair a terminated client. Startup startAllInboxes() calls getAgent(), which therefore binds the revived agent to the dead capability. ## Expected behavior A durable Floot session should reopen after daemon or machine restart even when its prior CLI sandbox was terminated or disappeared. Conversation and workspace state should survive according to backend policy; a fresh live client should be provisioned lazily. ## Suggested fix - Add a liveness check when resolving an existing per-session CLI client. - If status is terminated, missing, or otherwise unusable, ask the session provisioner to replace or recreate it instead of returning it. - Make replacement preserve the session workspace and backend conversation identity where available. - Surface an explicit recoverable error if reprovisioning fails rather than leaving a permanently pending turn. - Apply the same contract to Claude and Codex resolvers. ## Acceptance criteria - Terminate a per-session Codex client, restart the daemon, and start another turn in the same Floot session successfully. - Repeat for Claude. - Session history remains present. - No stale terminated client is returned solely because its petname exists. - Add a restart/reprovision regression test. Related to #30, but distinct: #30 covers in-flight turn, MCP bridge, and secret-request recovery across restart; this issue covers recovery of the underlying per-session CLI client after explicit termination or loss.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
floot/endo#31
No description provided.