Destructive Daemon Lifecycle Guard in no-mistakes: Preventing Daemon Stop During Active Runs

The Destructive Daemon Lifecycle Guard located in internal/lifecycle/guard.go blocks daemon stop, restart, and update commands whenever pipeline runs are active, requiring an explicit --force flag to proceed.

The no-mistakes repository implements a protective mechanism to prevent accidental daemon termination during critical operations. This lifecycle guard that prevents daemon stop during active runs ensures data integrity by verifying no pending or running pipelines exist before allowing destructive lifecycle changes. The implementation resides in the internal lifecycle package and integrates with the CLI to enforce strict safety checks.

How the Lifecycle Guard Works

The guard operates as a gatekeeper for all destructive daemon operations. Before executing stop, restart, or update commands, the system queries the current execution state to determine if intervention is safe.

When invoked, the guard checks lifecycle.ActiveRuns and lifecycle.RunList to enumerate any pipelines in pending or running states. If active runs exist, the CLI aborts the operation and displays a formatted list of blocking runs including their IDs, states, and associated branches. Only the presence of the --force flag overrides this protection, allowing users to acknowledge the risk of terminating the daemon while work is in progress.

Source Code Architecture and Key Files

The implementation spans several internal packages that coordinate to maintain daemon integrity:

Active Run Detection and Enforcement

The detection mechanism leverages shared helpers to inspect the run registry. The guard specifically looks for runs in non-terminal states before granting permission to proceed.

Querying Active Runs

The guard utilizes the following pattern to detect blocking executions:

runs, err := lifecycle.ActiveRuns(ctx)
if err != nil {
    // handle error
}
for _, r := range runs {
    fmt.Printf("run %d (%s) – branch %s\n", r.ID, r.State, r.Branch)
}

Blocking Behavior Without Force

If the guard detects active runs, it prevents daemon termination and outputs diagnostic information:

$ no-mistakes daemon stop
Daemon stop blocked – active runs detected:
  • run 42 (pending) – branch feature/foo
  • run 57 (running) – branch fix/bar
Use --force to override.

Force Override Mechanism

Users can bypass the protection by appending --force, acknowledging the risk of potential data loss or undefined worktree states:

$ no-mistakes daemon stop --force
Daemon stopped successfully (force‑override).

The same protection applies to restart and update operations:

$ no-mistakes update
Update aborted – the daemon has active runs.
Use --force to proceed anyway.

Audit Logging and Forensic Tracking

Every lifecycle guard invocation—whether blocked or permitted—is recorded in <NM_HOME>/logs/cli.log. Each entry includes caller attribution such as PID, PPID, and the full command line, creating an essential audit trail for forensic analysis of daemon lifecycle decisions.

This logging ensures administrators can trace who attempted to stop the daemon, whether the operation succeeded, and if force override was employed. The conservative design deliberately avoids silent daemon kills that could leave pipeline worktrees in corrupted states.

Summary

  • The Destructive Daemon Lifecycle Guard in internal/lifecycle/guard.go prevents accidental daemon termination during active pipeline execution.
  • It blocks daemon stop, daemon restart, and update commands when runs are in pending or running states.
  • Override requires the explicit --force flag, ensuring users consciously accept the risk of interrupting active work.
  • The guard utilizes lifecycle.ActiveRuns and lifecycle.RunList from internal/lifecycle/runlist.go to detect active executions.
  • All lifecycle decisions are logged to <NM_HOME>/logs/cli.log with full caller attribution for audit purposes.

Frequently Asked Questions

What triggers the lifecycle guard to block a daemon stop command?

The guard triggers whenever the no-mistakes daemon stop command detects active pipeline runs through the lifecycle.ActiveRuns helper. If any runs report states of pending or running, the guard aborts the operation and lists the blocking runs, requiring --force to proceed.

How does the lifecycle guard prevent data loss during daemon updates?

By requiring explicit confirmation via --force, the guard ensures users acknowledge that stopping or restarting the daemon while pipelines are active could leave worktrees in undefined states. This prevents silent termination that might interrupt file operations or corrupt pipeline state.

Where is the lifecycle guard logic implemented in the no-mistakes codebase?

The core logic resides in internal/lifecycle/guard.go, with supporting run detection implemented in internal/lifecycle/runlist.go. The guard integrates with the daemon lock management in internal/daemon/lock.go to verify daemon status before enforcing lifecycle restrictions.

Can the lifecycle guard be disabled or configured to ignore active runs?

No, the guard cannot be disabled through configuration. It is a hard-coded safety mechanism that always evaluates active runs before permitting destructive operations. The only mechanism to proceed with active runs is the --force flag, which acts as an explicit user override rather than a configuration change.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →