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:
- Mark the window as
quittingso the close handler does not re-hide to the tray. - Call
server.closeAllConnections()to drop active NDJSON streams. - Cap
Observability.shutdown()at two seconds usingPromise.race. - Attach a
.catch()on the shutdown promise so any rejection still exits. - 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.