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:
- Initialization – After reading and size-checking the command,
dcgbuilds aDeadlinewith the 200ms budget (or user-configured value clamped to minimums). - Periodic checks – Every expensive stage—including heredoc extraction, AST matching, and pattern-matching tiers—calls
deadline.is_exceeded()insrc/evaluator.rs. - Fail-open behavior – When the deadline passes,
dcgskips remaining heavy analysis tiers, emits a warning tostderr, 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_MAXinsrc/perf.rsdefines the hard 200ms limit as aDurationconstant.- The
should_fail_openfunction determines if elapsed time exceeds the 200ms threshold. Deadline::newconstructs the timeout tracker insrc/main.rsusing either the default 200ms or a user-configuredhook_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.mdandAGENTS.mdfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →