Maximum Processing Timeout and 200ms Deadline in dcg: How Destructive Command Guard Enforces Hard Limits

The Destructive Command Guard (dcg) enforces a hard 200ms processing deadline for every command evaluation, automatically failing open (allowing the command) when the limit is exceeded to prevent workflow blocking.

The Destructive Command Guard (dcg) is a Rust-based safety hook that intercepts shell commands before execution in AI-coding environments. To guarantee it never blocks a user's workflow, the project implements a strict maximum processing timeout of 200ms that triggers a fail-open mechanism when exceeded, as defined in the core performance module and enforced throughout the evaluation pipeline.

Where the 200ms Deadline is Defined in dcg

The absolute maximum processing time is hardcoded as a constant in the performance module.

In src/perf.rs, the primary constant is defined at line 277:

pub const ABSOLUTE_MAX: Duration = Duration::from_millis(200);

This value is also exposed as a configuration constant at lines 79-84:

pub const HOOK_EVALUATION_BUDGET_MS: u64 = 200;

The should_fail_open helper function (lines 90-93) provides a convenient check:

pub fn should_fail_open(duration: Duration) -> bool {
    duration > ABSOLUTE_MAX
}

Documentation across the repository reinforces this limit. The README.md (lines 58-61) explicitly states the "Absolute Timeout" of 200ms, while AGENTS.md (line 701) lists the "Hook fail-open deadline: 200 ms" for agent integration.

How the 200ms Deadline Works at Runtime

When dcg processes a command, it creates a Deadline instance in src/main.rs (lines 1001-1008) using the configured timeout:

let deadline = Deadline::new(
    config
        .general
        .hook_timeout_ms
        .map_or(HOOK_EVALUATION_BUDGET, |ms| {
            Duration::from_millis(ms.max(destructive_command_guard::perf::MIN_HOOK_TIMEOUT_MS))
        }),
);

The evaluation process follows this pattern:

  1. Initialization – After reading and size-checking the command, dcg builds a Deadline with the 200ms budget (or user-configured value clamped to minimums).
  2. Periodic checks – Every expensive stage—including heredoc extraction, AST matching, and pattern-matching tiers—calls deadline.is_exceeded() in src/evaluator.rs.
  3. Fail-open behavior – When the deadline passes, dcg skips remaining heavy analysis tiers, emits a warning to stderr, and returns no JSON denial. This safety-first design treats blocking a legitimate command for >200ms as worse than allowing it unchecked.

If the deadline is exceeded, only a lightweight critical-pattern check (FALLBACK_PATTERNS) runs before allowing the command.

Configuring the Maximum Processing Timeout

While 200ms is the default, you can adjust the timeout via the TOML configuration file. The hook_timeout_ms parameter in the [general] section allows customization:


# dcg.toml

[general]
hook_timeout_ms = 300   # Increase budget for complex scripts

The code enforces a minimum timeout of MIN_HOOK_TIMEOUT_MS (10ms) to prevent an instant "allow-all" bypass. If you specify a value below 10ms, the code clamps it to the minimum in src/main.rs:

Duration::from_millis(ms.max(destructive_command_guard::perf::MIN_HOOK_TIMEOUT_MS))

Practical Code Examples

Checking the Deadline Programmatically

You can use the Deadline helper directly in Rust code:

use destructive_command_guard::perf::{Deadline, ABSOLUTE_MAX};
use std::time::Duration;

// Initialize with the 200ms hard limit
let deadline = Deadline::new(Duration::from_millis(200));

// During analysis...
if deadline.is_exceeded() {
    eprintln!("[dcg] Warning: evaluation exceeded 200ms, allowing command");
    return;
}

Using the Fail-Open Convenience Function

For manual duration checks, use the should_fail_open function:

use destructive_command_guard::perf::should_fail_open;
use std::time::Instant;

let start = Instant::now();
// ... perform expensive operation ...
let elapsed = start.elapsed();

if should_fail_open(elapsed) {
    eprintln!("[dcg] Warning: operation took >200ms, fail-open");
    // Allow command to proceed
}

Handling Timeout in Custom Evaluators

When implementing custom evaluation logic, respect the fallback pattern behavior:

if deadline.is_exceeded() {
    // Only check critical patterns
    if fallback_patterns.matches(&command) {
        // Deny if critical pattern matches
    } else {
        // Allow command - deadline exceeded but no critical match
    }
}

Summary

  • ABSOLUTE_MAX in src/perf.rs defines the hard 200ms limit as a Duration constant.
  • The should_fail_open function determines if elapsed time exceeds the 200ms threshold.
  • Deadline::new constructs the timeout tracker in src/main.rs using either the default 200ms or a user-configured hook_timeout_ms.
  • Fail-open behavior ensures commands are allowed rather than blocked when analysis exceeds the deadline.
  • Minimum timeout of 10ms (MIN_HOOK_TIMEOUT_MS) prevents configuration bypasses.
  • The 200ms limit is documented in README.md and AGENTS.md for both users and agent developers.

Frequently Asked Questions

What happens when dcg exceeds the 200ms deadline during evaluation?

When the deadline is exceeded, dcg immediately stops expensive analysis tiers (like AST matching and pattern evaluation) and enters a lightweight fallback mode. It checks only critical patterns (FALLBACK_PATTERNS), and if none match, the command is allowed to execute. A warning is emitted to stderr indicating the timeout occurred.

Can I increase the 200ms timeout in dcg?

Yes, you can configure a longer timeout by setting hook_timeout_ms in your dcg.toml configuration file under the [general] section. However, the code clamps this value to a minimum of 10ms (MIN_HOOK_TIMEOUT_MS) to prevent accidentally disabling the guard with a near-zero timeout.

Where is the deadline checked during command evaluation?

The deadline is checked periodically in src/evaluator.rs before entering expensive stages like heredoc extraction, AST parsing, and pattern-matching tiers. The deadline.is_exceeded() method is called to determine whether to skip remaining analysis and proceed to the fail-open fallback.

What is the minimum timeout value allowed in dcg?

The minimum allowed timeout is 10ms, defined as MIN_HOOK_TIMEOUT_MS in src/perf.rs. If you configure hook_timeout_ms to a value lower than 10ms, the code automatically clamps it to 10ms using ms.max(MIN_HOOK_TIMEOUT_MS) in the deadline construction logic in src/main.rs.

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 →