No-Mistakes Lifecycle Guard: Preventing Daemon Stops During Active Runs
The lifecycle guard in no-mistakes prevents destructive daemon stops, restarts, or updates while pipeline runs are active, requiring an explicit --force flag to override.
The no-mistakes repository provides a machine-wide daemon that coordinates concurrent pipeline runs. The lifecycle guard is a safety mechanism that blocks shutdown commands when jobs are still pending or running, preventing data corruption and inconsistent worktree states.
Why the Lifecycle Guard Exists
The daemon serves as a single process coordinating multiple concurrent runs. Stopping it while runs are pending or running would abruptly terminate those jobs, potentially leaving worktrees, locks, or temporary data in an inconsistent state and risking data loss. To avoid these race conditions, the guard forces users to explicitly acknowledge the danger and provide a --force flag before the daemon can be stopped, restarted, or updated.
How the Lifecycle Guard Works
The guard implements a check-before-act pattern across all lifecycle commands. When a user issues daemon stop, daemon restart, or update, the system validates active run states before proceeding.
Querying the ActiveRuns Registry
The guard first queries the daemon’s internal ActiveRuns registry defined in internal/lifecycle/active_runs.go. If the registry contains any runs that are not yet finished, the command prints a concise list of those runs and aborts with a non-zero exit status. This check ensures the daemon cannot be destroyed while work is in progress.
The Force Override Mechanism
The command only proceeds if the user supplies --force, which overrides the guard after the active runs list has been displayed. This explicit opt-out ensures the user is aware of the impact before terminating active jobs.
Logging and Audit Trails
Every lifecycle request, whether allowed or blocked, is logged to <NM_HOME>/logs/cli.log with the caller’s PID, PPID, and the full command line. This audit trail is essential for post-mortem analysis of accidental daemon shutdowns, allowing administrators to trace who attempted to stop the daemon and when.
Integration and Implementation Details
The guard logic lives in internal/lifecycle/guard.go and is invoked from the CLI command handlers in internal/cli/daemon_lifecycle_test.go, which also contains the corresponding tests. The daemon’s startup and shutdown entry points in internal/daemon/daemon.go consult this guard before executing destructive operations.
The guard is deliberately disabled by default for the auto_fix.review feature, because review-related stops are handled separately through a different code path.
Practical Examples
Attempting to stop the daemon while runs are active results in a blocked operation:
$ no-mistakes daemon stop
Active runs:
• run 42 – pending (branch: feature/foo)
• run 43 – running (branch: bugfix/bar)
Refusing to stop daemon while runs are active. Use --force to override.
To force the daemon to stop despite active runs:
$ no-mistakes daemon stop --force
Daemon stopped successfully.
The same protection applies to restart and update commands:
$ no-mistakes daemon restart
Active runs detected; aborting. Add --force to restart anyway.
$ no-mistakes update
Active runs present – refusing to replace the running daemon.
Run `no-mistakes update -y --force` to proceed anyway.
Summary
- The lifecycle guard prevents accidental daemon stops that would terminate active pipeline runs and corrupt data.
- It queries the ActiveRuns registry in
internal/lifecycle/active_runs.goto check for pending or running jobs before executingstop,restart, orupdatecommands. - Users must provide the
--forceflag to override the guard, ensuring explicit acknowledgment of the risk. - All lifecycle attempts are logged to
<NM_HOME>/logs/cli.logwith caller PID and PPID for forensic analysis. - The core implementation resides in
internal/lifecycle/guard.gowith integration points ininternal/daemon/daemon.goandinternal/cli/daemon_lifecycle_test.go. - The guard is disabled by default only for the
auto_fix.reviewfeature.
Frequently Asked Questions
What happens if I try to stop the daemon without --force while runs are active?
The command queries the ActiveRuns registry and, if any runs are pending or running, prints a list of those runs and aborts with a non-zero exit code. The daemon remains running to protect active jobs from abrupt termination.
Where is the lifecycle guard logic implemented in the no-mistakes codebase?
The core implementation resides in internal/lifecycle/guard.go. It is invoked from CLI handlers in internal/cli/daemon_lifecycle_test.go and consulted by the daemon startup and shutdown entry points in internal/daemon/daemon.go.
How does the guard track active runs?
The guard consults the ActiveRuns registry maintained in internal/lifecycle/active_runs.go, which maintains an in-memory list of all pipeline runs that have not yet finished, including their status and branch information.
Is the lifecycle guard ever disabled?
The guard is disabled by default only for the auto_fix.review feature, as review-related stops are handled separately. For standard lifecycle operations, you cannot permanently disable the guard; you must use the --force flag to override it on a per-command basis.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →