Closedloop.ai
Mechanisms

Recovery and Resilience

How Closedloop survives crashes, restarts, and ghost loops without losing progress.

Loops are long-running, and long-running work eventually collides with an app restart, a CMD+Q, a hung process, or a transient network blip. Closedloop's recovery layer is designed so the state you see in the web app always matches what happened on disk.

Graceful quit

Quitting the desktop app triggers a deterministic shutdown:

  1. Mark the window as quitting so the close handler does not re-hide to the tray.
  2. Call server.closeAllConnections() to drop active NDJSON streams.
  3. Cap Observability.shutdown() at two seconds using Promise.race.
  4. Attach a .catch() on the shutdown promise so any rejection still exits.
  5. If the orderly shutdown does not complete in eight seconds, a hard-exit failsafe terminates the process.

This is the fix that guarantees CMD+Q reliably quits the app.

On this page