dcg
Handle blocked destructive commands and configure agent safety guardrails. Triggers: "dcg", "handle a DCG block", "configure agent safety guardrails".
Install
npx skills add https://github.com/boshu2/agentops/tree/main/skills/dcg
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install boshu2-agentops@llmmart
git clone https://github.com/boshu2/agentops.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole boshu2/agentops collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
DCG: When You Get Blocked
Core Insight: Blocks are checkpoints, not errors. A safe alternative almost always exists. Find it before mentioning override.
Constraints
- Never request, generate, or run an allow-once bypass because only the human may authorize and execute the exact blocked command.
- Preserve the user's intended outcome with the narrowest reversible alternative because the guard protects state, not merely command spelling.
- Explain the matched rule and surviving risk before asking for judgment; never retry, obfuscate, or route around a DCG block.
Quick Navigation
| I need to... | Go to |
|---|---|
| Handle a block right now | THE EXACT WORKFLOW |
| Find a safe alternative | Safe Alternatives |
| See all CLI commands | COMMANDS.md |
| Enable more rule packs | PACKS.md |
| Configure per-project | CONFIG.md |
| Debug hook issues | TROUBLESHOOTING.md |
THE EXACT WORKFLOW
When blocked, follow this sequence every time:
1. Run `dcg explain "cmd"` → Understand why (see trace)
2. Check Safe Alternatives table → Use if exists (DON'T mention override)
3. No alternative? → Explain risk clearly, let human decide
4. Human approves? → THEY run: dcg allow-once CODE
Never: Ask for override first. Never retry silently. Never circumvent.
Risk-tiered approval counts
When no safe alternative exists and the human must decide, the number of distinct human approvals scales with what the command can destroy:
| Tier | Blast radius | Approvals required |
|---|---|---|
| Recoverable | undoable via reflog/stash/trash/backup | 1 allow-once for this exact command |
| Destructive-local | permanently deletes local, uncommitted, or unbacked state | 1 allow-once, granted only after you name the exact state lost and confirm no backup exists |
| Destructive-shared | shared history, remote branches, databases, namespaces others use | 1 approval per individual command occurrence — never batched, never pattern-widened |
Stop conditions: never present a tier-2 or tier-3 command as tier-1; never convert several pending blocks into one blanket approval. A single "yes" that gets spent across multiple destructive commands is the approval laundering failure mode — each allow-once code is bound to one command in one directory, and the workflow must keep it that way.
Example block output:
BLOCKED: git reset --hard HEAD
Rule: core.git:reset-hard
Reason: Discards uncommitted changes permanently
Allow-once code: ab12
Safer alternative: git stash
Good response:
"I wanted to discard changes but
git reset --hardwas blocked. Let me usegit stashinstead—recoverable if needed." [proceeds with stash]
Safe Alternatives
| Blocked | Use Instead | Why |
|---|---|---|
git reset --hard |
git stash |
Recoverable |
git checkout -- file |
git stash push file |
Preserves changes |
git push --force |
git push --force-with-lease |
Checks remote unchanged |
git clean -fd |
git clean -fdn (preview) |
Shows what would delete |
git stash drop |
git stash list first |
Verify which stash |
rm -rf /path |
rm -ri /path or verify path |
Interactive/confirm |
kubectl delete namespace |
kubectl delete -l app=X |
Selective deletion |
DROP DATABASE |
Backup first | Human approves |
docker system prune -a |
docker system df first |
See what's used |
Quick Reference
dcg doctor # Health check — hook registered?
dcg explain "cmd" # WHY is it blocked? (with trace)
dcg test "cmd" # Would this be blocked? (dry-run)
dcg allow-once CODE # Human approves (THEY run this)
dcg packs # List available rule packs
dcg scan --staged # Pre-commit: scan for issues
What Gets Blocked
| Category | Patterns | Safe Variants |
|---|---|---|
| Git destructive | reset --hard, checkout -- |
stash, restore --staged |
| Git history | push --force, branch -D |
--force-with-lease, -d |
| Git stash | stash drop, stash clear |
stash list first |
| Filesystem | rm -rf (dangerous paths) |
/tmp/* allowed |
| Database | DROP, TRUNCATE, DELETE w/o WHERE |
Add WHERE clause |
| K8s | delete namespace, delete --all |
-l label selector |
Context-aware (measured on dcg 0.5.6): the temp carve-out allows rm -rf
under /tmp, /private/tmp, /var/tmp, and the literal $TMPDIR form.
Everything else — rm -rf ./build and other relative paths
(core.filesystem:rm-rf-general), absolute paths like /home/... and /
(core.filesystem:rm-rf-root-home), and even /private/var/tmp — is blocked.
Unresolved variables other than $TMPDIR are not treated as temp.
dcg explain example (7-step pipeline):
$ dcg explain "git reset --hard HEAD"
BLOCKED by core.git:reset-hard
Evaluation trace:
1. Config allow overrides: no match
2. Config block overrides: no match
3. Heredoc detection: not applicable
4. Quick reject: triggered (contains "reset")
5. Context sanitization: no changes
6. Normalization: git reset --hard HEAD
7. Pack evaluation:
- Safe patterns: no match
- Destructive: MATCH "reset --hard"
Suggestion: Use `git stash` to preserve changes
Anti-Patterns
❌ "Command blocked. Run dcg allow-once ab12" → Find alternative first!
❌ *Retrying silently or circumventing* → Always acknowledge blocks
❌ Treating blocks as errors → They're checkpoints
❌ Asking user to allow-once without explaining → They need context
Configuration
# .dcg.toml — enable rule packs per-project
[packs]
enabled = ["database.postgresql", "kubernetes.kubectl", "cloud.aws"]
[overrides]
allow_patterns = ["rm -rf ./node_modules"] # Project-specific safe
Environment variables:
DCG_PACKS="containers.docker,kubernetes"— Enable packsDCG_DISABLE="kubernetes.helm"— Disable specific packsDCG_BYPASS=1— Escape hatch (human-only)
Key Facts
- 49+ rule packs available (database, containers, k8s, cloud, etc.)
- Sub-millisecond latency — won't slow your workflow
- Fail-open on timeout — if DCG hangs, command runs (with warning)
- Heredoc scanning — inline scripts (
bash -c,python -c) are analyzed - Inline-fragment false positives — because scanning matches a destructive token anywhere in the command string, a pattern that appears only as data (a commit message body, a here-doc payload, a probe argument) can trip a block even though nothing destructive would run. Safe pattern: keep the payload off the command line — pass it via a file or stdin (e.g.
git commit -F <file>), or run the intended tool directly instead of inlining the text. Never reconstruct a blocked command by splitting or escaping its tokens to slip past the guard — that defeats the safety layer. - Allow-once codes — 4 hex chars, 24h expiry, bound to exact command+directory
The Incident That Started It All
On December 17, 2025, an AI agent ran
git checkout --on files containing hours of uncommitted work. The files were recovered viagit fsck --lost-found, but it proved: instructions don't prevent execution—mechanical enforcement does.
Validation
# Quick health check
dcg doctor | head -20
# Test if a command would be blocked
dcg test "git reset --hard HEAD"
# Should show: WOULD BE BLOCKED
Output Specification
- Path: the response and command output on stdout/stderr; write
.dcg.tomlor.dcg/allowlist.tomlonly when configuration was explicitly requested. - Filename: preserve DCG's project filenames exactly; ordinary block handling creates no persistent file.
- Format: state the blocked command, matched rule, risk, reversible alternative, and the alternative's validation result; quote commands exactly.
- Exit code: run
bash skills/dcg/scripts/validate-dcg.shand require zero for installation/configuration work; a blockeddcg testresult is expected evidence, not permission to bypass. - Downstream handoff: proceed with the validated safe alternative, or hand the exact risk and allow-once choice to the human when no equivalent exists.
Quality Checklist
- The response identifies the exact block and rule without exposing or suggesting an unauthorized bypass path.
- The chosen alternative is narrower, reversible where possible, and demonstrably preserves the user's requested outcome.
- Validation distinguishes an expected destructive-command block from a broken DCG installation or configuration.
Scripts
| Script | Usage |
|---|---|
./scripts/validate-dcg.sh |
Full installation validation |
References
- COMMANDS.md — Full CLI reference with
dcg explain,dcg scan - PACKS.md — 49+ rule pack system (database, k8s, cloud, etc.)
- CONFIG.md — Configuration, agent profiles, heredoc settings
- SCENARIOS.md — Detailed examples with good/bad responses
- PHILOSOPHY.md — Why DCG works this way
- TROUBLESHOOTING.md — Common issues and fixes
Files (agentops)
-
references
-
COMMANDS.md 8.8 KB
# DCG Commands Reference ## Command Overview | Command | Purpose | When to Use | |---------|---------|-------------| | `dcg doctor` | Verify installation | Hook not working | | `dcg explain "cmd"` | Understand why blocked | After any block | | `dcg test "cmd"` | Dry-run evaluation | Before risky commands | | `dcg allow-once CODE` | Temporary exception | Human approves | | `dcg allowlist add` | Permanent exception | Recurring safe ops | | `dcg allowlist list` | Show exceptions | Audit allowlist | | `dcg packs` | List available packs | See what's enabled | | `dcg scan` | Scan repository | Pre-commit checks | | `dcg update` | Self-update | Get latest rules | --- ## dcg doctor Verify DCG installation and hook registration. ```bash $ dcg doctor DCG Doctor ══════════════════════════════════════════════════ Binary: ✓ dcg version 0.5.6 ✓ Located at /usr/local/bin/dcg Hook Registration: ✓ Claude Code hook registered in ~/.claude/settings.json ✓ Hook path: /usr/local/bin/dcg hook Configuration: ✓ User config: ~/.config/dcg/config.toml ✓ Project config: .dcg.toml (not found - using defaults) Packs: ✓ Core packs loaded: core.git, core.filesystem ✓ Optional packs: 0 enabled Status: All checks passed ``` **Use when:** Hook doesn't seem to be working, commands aren't being blocked. --- ## dcg explain "command" Show exactly why a command is blocked/allowed with full evaluation trace. ```bash $ dcg explain "git reset --hard HEAD" BLOCKED by core.git:reset-hard Evaluation trace (7-step pipeline): Step 1. Config allow overrides ... no match Step 2. Config block overrides ... no match Step 3. Heredoc detection ....... not applicable Step 4. Quick reject ............ triggered (pattern: "reset") Step 5. Context sanitization .... no changes Step 6. Normalization ........... "git reset --hard HEAD" Step 7. Pack evaluation: - Safe patterns ........ no match - Destructive patterns . MATCH "reset --hard" Rule details: Pack: core.git Rule ID: reset-hard Severity: high Reason: Discards all uncommitted changes permanently Suggestion: Use `git stash` to preserve changes before resetting ``` ```bash $ dcg explain "git checkout -b feature" ALLOWED Evaluation trace (7-step pipeline): Step 4. Quick reject ............ no trigger Step 7. Pack evaluation: - Safe patterns ........ MATCH "checkout -b" (creating branch) No block - command is safe. ``` **Use when:** You want to understand WHY something was blocked before deciding next steps. --- ## dcg test "command" Dry-run evaluation without executing. ```bash $ dcg test "rm -rf /home/user/project" WOULD BE BLOCKED Rule: core.filesystem:rm-rf-root-home Reason: Recursive deletion of an absolute non-temporary path $ dcg test "rm -rf ./build" WOULD BE BLOCKED Rule: core.filesystem:rm-rf-general Reason: Recursive deletion of a relative non-temporary path $ dcg test "rm -rf /tmp/build" WOULD BE ALLOWED Context: paths under /tmp, /private/tmp, and $TMPDIR are in the temp carve-out ``` **Use when:** Checking before running something you're unsure about. --- ## dcg allow-once CODE Create temporary exception for a blocked command. ```bash $ dcg allow-once ab12 Exception created: Command: git reset --hard HEAD Directory: /home/user/project Expires: 2025-01-16T10:30:00Z (24 hours) Run the command again within 24 hours to execute. ``` **Characteristics:** - Code is 4 hex characters (cryptographically bound to command + directory) - Expires after 24 hours - Single use per command instance - Stored in `~/.config/dcg/pending_exceptions.jsonl` - Logged to `~/.config/dcg/audit.log` **Critical:** The HUMAN runs this command, not the agent. Agent should never execute `dcg allow-once`. --- ## dcg allowlist Manage permanent exceptions. ```bash # Add allowlist entry $ dcg allowlist add core.git:reset-hard -r "CI cleanup requires this" # Add with scope $ dcg allowlist add core.filesystem:rm-rf-root-home \ --path "/home/user/project/build" \ -r "Build directory cleanup" # List entries $ dcg allowlist list ┌──────────────────────────────────┬────────────────────────────┬─────────────────────────┐ │ Rule ID │ Scope │ Reason │ ├──────────────────────────────────┼────────────────────────────┼─────────────────────────┤ │ core.git:reset-hard │ global │ CI cleanup requires │ │ core.filesystem:rm-rf-root-home │ /home/user/project/build │ Build directory cleanup │ └──────────────────────────────────┴────────────────────────────┴─────────────────────────┘ # Remove entry $ dcg allowlist remove core.git:reset-hard ``` **Layered allowlists (highest to lowest priority):** 1. `.dcg/allowlist.toml` — Project-level 2. `~/.config/dcg/allowlist.toml` — User-level 3. `/etc/dcg/allowlist.toml` — System-level --- ## dcg packs List available and enabled rule packs. ```bash $ dcg packs Core (always enabled): ✓ core.git - Destructive git commands ✓ core.filesystem - Dangerous file operations Optional (49 available): Database: postgresql, mysql, mongodb, redis, sqlite Containers: docker, compose, podman Kubernetes: kubectl, helm, kustomize Cloud: aws, azure, gcp Storage: s3, gcs, azure_blob, minio ... Currently enabled: core.git, core.filesystem $ dcg packs --verbose # Shows all patterns in each pack ``` --- ## dcg scan Scan repository for destructive commands in scripts and config files. ```bash # Scan entire repo $ dcg scan Scanning 142 files... FINDINGS: ┌─────────────────────────────────┬──────────┬─────────────────────────────────┐ │ File │ Line │ Issue │ ├─────────────────────────────────┼──────────┼─────────────────────────────────┤ │ scripts/deploy.sh │ 45 │ git reset --hard (core.git) │ │ .github/workflows/ci.yml │ 23 │ rm -rf / (core.filesystem) │ │ Makefile │ 67 │ DROP DATABASE (database.*) │ └─────────────────────────────────┴──────────┴─────────────────────────────────┘ Found 3 issues in 3 files. # Scan only staged files $ dcg scan --staged # Scan specific path $ dcg scan --path scripts/ # Scan with SARIF output (for CI) $ dcg scan --format sarif > results.sarif ``` **Supported file types:** | Type | Contexts Scanned | |------|-----------------| | Shell scripts (`.sh`) | All executable lines | | Dockerfile | `RUN` instructions | | GitHub Actions | `run:` fields | | GitLab CI | `script:`, `before_script:`, `after_script:` | | Makefile | Recipe lines | | Docker Compose | `command:`, `entrypoint:` | ### Install Pre-commit Hook ```bash $ dcg scan install-pre-commit Installed pre-commit hook at .git/hooks/pre-commit Staged files will be scanned before each commit. ``` --- ## dcg update Self-update to latest version. ```bash $ dcg update Current version: <installed> Latest version: <latest> Downloading... Verifying signature... Installing... Updated to <latest> ``` --- ## Output Formats All commands support `--format`: ```bash dcg explain "cmd" --format json # Machine-readable dcg explain "cmd" --format text # Human-readable (default) dcg scan --format sarif # SARIF for CI integration ``` --- ## Environment Variables | Variable | Purpose | Example | |----------|---------|---------| | `DCG_PACKS` | Enable packs | `"database.postgresql,kubernetes"` | | `DCG_DISABLE` | Disable packs | `"kubernetes.helm"` | | `DCG_BYPASS` | Skip all checks | `1` (human-only escape hatch) | | `DCG_VERBOSE` | Verbosity (0-3) | `2` | | `DCG_FORMAT` | Default output | `json` | | `DCG_CONFIG` | Config file path | `/path/to/config.toml` | -
CONFIG.md 4.8 KB
# DCG Configuration Reference ## Configuration Hierarchy Settings are loaded in this order (highest to lowest priority): 1. **Environment Variables** (`DCG_*` prefix) 2. **Explicit Config File** (`DCG_CONFIG` env var) 3. **Project Config** (`.dcg.toml` in repo root) 4. **User Config** (`~/.config/dcg/config.toml`) 5. **System Config** (`/etc/dcg/config.toml`) 6. **Compiled Defaults** --- ## Environment Variables | Variable | Purpose | Example | |----------|---------|---------| | `DCG_PACKS` | Enable optional packs | `"database.postgresql,kubernetes"` | | `DCG_DISABLE` | Disable specific packs | `"kubernetes.helm"` | | `DCG_BYPASS` | Skip all checks (escape hatch) | `1` | | `DCG_VERBOSE` | Verbosity level | `0-3` | | `DCG_FORMAT` | Default output format | `text`, `json`, `sarif` | | `DCG_CONFIG` | Explicit config path | `/path/to/config.toml` | --- ## Project Config (.dcg.toml) ```toml # Pack configuration [packs] enabled = [ "database.postgresql", "kubernetes.kubectl", "cloud.aws" ] # Override patterns (evaluated before packs) [overrides] allow_patterns = [ "rm -rf ./node_modules", "rm -rf ./build", "git clean -fd ./generated" ] block_patterns = [ "rm -rf /custom/dangerous/path" ] # Heredoc scanning configuration [heredoc] enabled = true max_size_bytes = 1048576 # 1MB max_lines = 10000 tier2_budget_ms = 200 tier3_budget_ms = 5000 # Supported languages for AST analysis languages = ["bash", "python", "ruby", "javascript", "typescript", "go", "php"] ``` --- ## Agent-Specific Profiles Configure different trust levels and rules per agent: ```toml # Claude Code - high trust, additional allowlist [agents.claude-code] trust_level = "high" additional_allowlist = [ "npm run build", "cargo build --release" ] # Gemini CLI - medium trust [agents.gemini-cli] trust_level = "medium" # Unknown agents - paranoid mode [agents.unknown] trust_level = "low" extra_packs = ["paranoid"] ``` ### Trust Levels | Level | Behavior | |-------|----------| | `high` | Core packs only, faster evaluation | | `medium` | Standard evaluation (default) | | `low` | Extra scrutiny, more packs enabled | --- ## Allowlist Configuration ### Project-Level Allowlist (.dcg/allowlist.toml) ```toml [[rules]] id = "core.git:reset-hard" reason = "CI cleanup requires hard reset" expires = "2025-12-31" # Optional expiration [[rules]] id = "core.filesystem:rm-rf-general" path = "./build" # Scope to specific path reason = "Build directory cleanup" ``` ### User-Level Allowlist (~/.config/dcg/allowlist.toml) ```toml [[rules]] id = "containers.docker:system-prune" reason = "Regular Docker cleanup on dev machine" ``` --- ## Heredoc Three-Tier Architecture DCG scans inline scripts (`bash -c`, `python -c`, heredocs) with progressive depth: ### Tier 1: Trigger Detection (<5μs) - Ultra-fast RegexSet screening - Detects heredoc operators (`<<EOF`, `<<'EOF'`) - Detects inline script flags (`python -c`, `bash -c`, `ruby -e`) ### Tier 2: Content Extraction (<200μs) - Parse heredoc body between delimiters - Bounded by `max_size_bytes` and `max_lines` - Budget controlled by `tier2_budget_ms` ### Tier 3: AST Pattern Matching (<5ms) - Parse with language-specific grammars (tree-sitter/ast-grep) - Match structural patterns for destructive operations - Budget controlled by `tier3_budget_ms` **Fail-open behavior:** If any tier exceeds its budget, remaining tiers are skipped and command is ALLOWED with a warning logged. ### Tune Heredoc Settings ```toml [heredoc] # Increase for large scripts max_size_bytes = 2097152 # 2MB # Increase budgets if seeing "budget exceeded" warnings tier2_budget_ms = 500 tier3_budget_ms = 10000 # Disable for performance (not recommended) enabled = false ``` --- ## CI Integration ### GitHub Actions ```yaml - name: DCG Pre-commit Scan run: dcg scan --git-diff origin/main..HEAD --fail-on error ``` ### Pre-commit Hook ```bash # Install hook dcg scan install-pre-commit # Hook checks staged files before each commit # Blocks commit if destructive patterns found ``` ### GitLab CI ```yaml dcg-scan: script: - dcg scan --format sarif > dcg-results.sarif artifacts: reports: sast: dcg-results.sarif ``` --- ## Hook Protocol DCG integrates with Claude Code via the PreToolUse hook: ### Registration (~/.claude/settings.json) ```json { "hooks": { "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "dcg hook" }] }] } } ``` ### Input (JSON on stdin) ```json { "tool_name": "Bash", "tool_input": {"command": "git reset --hard"} } ``` ### Deny Response (JSON on stdout) ```json { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "BLOCKED by dcg: ...", "allowOnceCode": "ab12", "ruleId": "core.git:reset-hard" } } ``` ### Allow Response Exit code 0 with no output. -
PACKS.md 8.6 KB
# DCG Rule Packs DCG uses a modular pack system with 49+ rule packs organized by domain. ## Core Packs (Always Enabled) These cannot be disabled—they catch the most common destructive patterns. ### core.git | Pattern | Blocked | Safe Alternative | |---------|---------|-----------------| | `git reset --hard` | Yes | `git stash` | | `git checkout -- <file>` | Yes | `git stash push <file>` | | `git clean -f` | Yes | `git clean -n` (dry-run) | | `git push --force` | Yes | `git push --force-with-lease` | | `git branch -D` | Yes | `git branch -d` (checks merge) | | `git stash drop` | Yes | `git stash list` first | | `git stash clear` | Yes | Review stashes first | **Safe patterns (allowed):** - `git checkout -b` — Creating branches - `git restore --staged` — Unstaging files - `git clean -n` / `--dry-run` — Preview mode - `git push --force-with-lease` — Safe force push ### core.filesystem | Pattern | Blocked | Condition | |---------|---------|-----------| | `rm -rf /` | Yes | Always | | `rm -rf /*` | Yes | Always | | `rm -rf ~` | Yes | Always | | `rm -rf /home` | Yes | System paths | | `rm -rf /path` | Depends | Non-temp paths blocked | **Safe patterns (allowed) — measured on dcg 0.5.6.** The temp carve-out allows `rm -rf` under exactly these roots: - `rm -rf /tmp/*` — Temp directory - `rm -rf /private/tmp/*` — Temp directory (macOS) - `rm -rf /var/tmp/*` — Temp directory - `rm -rf $TMPDIR/*` — User temp (literal `$TMPDIR` only) `rm -rf ./build` and other relative or absolute non-temp paths — and even `/private/var/tmp` — are **blocked** (`core.filesystem:rm-rf-general` / `rm-rf-root-home`); allowlist them explicitly if a project needs them (see [CONFIG.md](CONFIG.md)). --- ## Optional Packs by Category Enable with `DCG_PACKS` or in `.dcg.toml`: ```toml [packs] enabled = ["database.postgresql", "kubernetes.kubectl", "cloud.aws"] ``` ### Database Packs | Pack | Blocks | Examples | |------|--------|----------| | `database.postgresql` | Data destruction | `DROP DATABASE`, `TRUNCATE`, `DELETE` w/o WHERE | | `database.mysql` | Data destruction | `DROP`, `TRUNCATE`, unsafe deletes | | `database.mongodb` | Collection drops | `db.dropDatabase()`, `db.collection.drop()` | | `database.redis` | Data wipes | `FLUSHALL`, `FLUSHDB`, `DEBUG SEGFAULT` | | `database.sqlite` | File deletion | `.backup` overwrites, `DROP TABLE` | ### Container Packs | Pack | Blocks | Examples | |------|--------|----------| | `containers.docker` | System prune | `docker system prune -a`, `docker rm -f $(...)` | | `containers.compose` | Stack destruction | `docker-compose down -v --rmi all` | | `containers.podman` | Same as docker | Pod and container mass deletion | ### Kubernetes Packs | Pack | Blocks | Examples | |------|--------|----------| | `kubernetes.kubectl` | Namespace/cluster | `delete namespace`, `delete --all`, `drain --force` | | `kubernetes.helm` | Release destruction | `helm uninstall`, `helm delete --purge` | | `kubernetes.kustomize` | Dangerous applies | `delete -k` without confirmation | ### Cloud Provider Packs | Pack | Blocks | Examples | |------|--------|----------| | `cloud.aws` | Resource destruction | `aws ec2 terminate-instances`, `aws s3 rb --force` | | `cloud.azure` | Resource groups | `az group delete`, `az vm delete` | | `cloud.gcp` | Project/instance | `gcloud projects delete`, instance termination | ### Storage Packs | Pack | Blocks | Examples | |------|--------|----------| | `storage.s3` | Bucket destruction | `aws s3 rb`, `aws s3 rm --recursive` | | `storage.gcs` | Bucket destruction | `gsutil rm -r`, `gsutil rb` | | `storage.azure_blob` | Container deletion | `az storage container delete` | | `storage.minio` | S3-compatible ops | `mc rb --force` | ### Infrastructure Packs | Pack | Blocks | Examples | |------|--------|----------| | `infrastructure.terraform` | State destruction | `terraform destroy`, `terraform state rm` | | `infrastructure.ansible` | Dangerous playbooks | File deletion tasks, service stops | | `infrastructure.pulumi` | Stack destruction | `pulumi destroy`, `pulumi stack rm` | ### CI/CD Packs | Pack | Blocks | Examples | |------|--------|----------| | `cicd.github_actions` | Workflow deletion | Dangerous `run:` commands in workflows | | `cicd.gitlab_ci` | Pipeline destruction | Risky `script:` blocks | | `cicd.circleci` | Config issues | Destructive commands in jobs | | `cicd.jenkins` | Pipeline risks | Shell steps with dangerous commands | ### Secrets Management Packs | Pack | Blocks | Examples | |------|--------|----------| | `secrets.vault` | Secret deletion | `vault kv delete`, `vault secrets disable` | | `secrets.aws_secrets` | Secret destruction | `aws secretsmanager delete-secret` | | `secrets.doppler` | Config deletion | `doppler configs delete` | | `secrets.onepassword` | Vault destruction | `op vault delete` | ### Messaging Packs | Pack | Blocks | Examples | |------|--------|----------| | `messaging.kafka` | Topic deletion | `kafka-topics.sh --delete` | | `messaging.rabbitmq` | Queue/exchange | `rabbitmqctl delete_queue` | | `messaging.nats` | Stream deletion | `nats stream delete` | | `messaging.sqs_sns` | Queue destruction | `aws sqs delete-queue` | ### Search & Analytics Packs | Pack | Blocks | Examples | |------|--------|----------| | `search.elasticsearch` | Index deletion | `DELETE /index`, `_delete_by_query` | | `search.algolia` | Index clear | `clearObjects`, `deleteIndex` | | `search.meilisearch` | Index destruction | Index deletion APIs | | `search.opensearch` | Same as ES | Index and alias deletion | ### Monitoring Packs | Pack | Blocks | Examples | |------|--------|----------| | `monitoring.datadog` | Monitor deletion | API calls to delete monitors | | `monitoring.prometheus` | Rule deletion | Recording rule destruction | | `monitoring.splunk` | Index deletion | Index and data destruction | | `monitoring.newrelic` | Alert deletion | Policy and condition removal | | `monitoring.pagerduty` | Service deletion | Escalation policy destruction | ### Backup Packs | Pack | Blocks | Examples | |------|--------|----------| | `backup.restic` | Snapshot deletion | `restic forget --prune` | | `backup.borg` | Archive deletion | `borg delete`, `borg prune` | | `backup.rclone` | Remote deletion | `rclone delete`, `rclone purge` | | `backup.velero` | Backup destruction | `velero backup delete` | ### Platform Packs | Pack | Blocks | Examples | |------|--------|----------| | `platform.github` | Repo destruction | `gh repo delete` | | `platform.gitlab` | Project deletion | `glab project delete` | ### DNS Packs | Pack | Blocks | Examples | |------|--------|----------| | `dns.cloudflare` | Zone destruction | `cloudflare dns delete` | | `dns.route53` | Record deletion | `aws route53 change-resource-record-sets DELETE` | ### Payment Packs | Pack | Blocks | Examples | |------|--------|----------| | `payment.stripe` | Customer/sub deletion | API calls to delete customers | | `payment.braintree` | Transaction voids | Refund and void operations | | `payment.square` | Payment cancellation | Payment and customer deletion | ### Load Balancer Packs | Pack | Blocks | Examples | |------|--------|----------| | `lb.elb` | LB destruction | `aws elb delete-load-balancer` | | `lb.haproxy` | Config destruction | Runtime API deletions | | `lb.nginx` | Config issues | Dangerous reload patterns | | `lb.traefik` | Dynamic config | Router and service deletion | ### CDN Packs | Pack | Blocks | Examples | |------|--------|----------| | `cdn.cloudflare_workers` | Worker deletion | `wrangler delete` | | `cdn.cloudfront` | Distribution deletion | `aws cloudfront delete-distribution` | | `cdn.fastly` | Service destruction | Service and VCL deletion | ### API Gateway Packs | Pack | Blocks | Examples | |------|--------|----------| | `api.apigee` | Proxy deletion | API proxy and product deletion | | `api.aws` | Gateway destruction | `aws apigateway delete-rest-api` | | `api.kong` | Route deletion | Service and route destruction | --- ## Enabling Packs ### Via Environment Variable ```bash export DCG_PACKS="database.postgresql,kubernetes.kubectl,cloud.aws" ``` ### Via Project Config (.dcg.toml) ```toml [packs] enabled = [ "database.postgresql", "database.mysql", "kubernetes.kubectl", "kubernetes.helm", "cloud.aws", "storage.s3" ] ``` ### Via User Config (~/.config/dcg/config.toml) ```toml [packs] enabled = ["containers.docker", "platform.github"] ``` ### Disabling Specific Packs ```bash # Disable helm even if kubernetes is enabled export DCG_DISABLE="kubernetes.helm" ``` --- ## Pack Inspection ```bash # List all packs dcg packs # Show patterns in a pack dcg packs --verbose database.postgresql # Check which packs would match a command dcg explain "kubectl delete namespace prod" ``` -
PHILOSOPHY.md 2.9 KB
# DCG Philosophy ## The Core Asymmetry ``` Execute "rm -rf /": 0.001 seconds Recover from it: impossible ``` DCG exists because the cost of a false negative (destructive command runs) far exceeds the cost of a false positive (safe command blocked for 30 seconds). ## Mechanical Enforcement vs Instructions ``` AGENTS.md says "don't run destructive commands" → Agent might ignore DCG blocks destructive commands before execution → Physically impossible to run ``` Instructions in AGENTS.md are suggestions. DCG is enforcement. This is the key differentiator. ## Why Pre-Execution Blocking ``` Your Decision → DCG Hook → Shell → Kernel ↑ Intercept HERE ``` - No partial execution - No cleanup needed - Clear audit trail Alternatives (backups, permissions, monitoring) all act too late. ## Human Context You Lack When blocked, you're being told "get human confirmation" because they know: - Production vs test environment - Whether uncommitted changes matter - Who else is working on this branch - Actual blast radius ## Why Patterns, Not AI | Property | Pattern Matching | |----------|------------------| | Speed | <2ms | | Determinism | Same input → same result | | Auditability | Exact pattern visible | | Predictability | No model variance | ## Allow-Once Codes ``` ALLOW-24H CODE: [12345] ``` - Cryptographically bound to exact command + directory - Time-limited, single-use, logged - Human explicitly accepts responsibility ## Why Never Circumvent 1. Your context may be incomplete 2. Human loses visibility 3. Erodes trust in all your actions Correct response: explain why you think it's safe, let human decide. ## Design Principles | Principle | Meaning | |-----------|---------| | Fail-closed on match | Pattern hits → block | | Fail-open on error | DCG breaks → allow | | Fail-open on timeout | >200ms → allow + warning | | Fast safe path | Most commands <1ms | | Human override | Never permanent, just confirmed | ## Performance Contract **Latency Tiers:** | Tier | Stage | Target | Panic Threshold | |------|-------|--------|-----------------| | 0 | Quick Reject | <1μs | >50μs | | 1 | Normalization | <5μs | >100μs | | 2 | Safe Pattern Check | <50μs | >500μs | | 3 | Destructive Pattern Check | <50μs | >500μs | | 4 | Heredoc Extraction | <1ms | >20ms | | 5 | Heredoc Evaluation | <2ms | >30ms | | 6 | Full Pipeline | <5ms | >50ms | **Absolute Max:** 200ms (fail-open threshold) **SIMD Optimizations:** - `memchr` crate for fast substring search - `Aho-Corasick` for multi-pattern keyword matching - `LazyLock` for one-time pattern compilation - `SmallVec` for stack-allocated collections DCG will never significantly slow your workflow. If something goes wrong, commands run (with warnings logged). You can always run `dcg explain "command"` to see exactly why something was blocked. DCG makes you more useful: humans trust you more when safety rails exist. -
SCENARIOS.md 2.6 KB
# DCG Scenarios Quick reference for handling common blocks. --- ## 1. Git Reset — Use Alternative **Blocked:** `git reset --hard HEAD` ❌ "Command blocked. Run `dcg allow-once 12345`." ✓ "Blocked because it destroys uncommitted work. Using `git stash` instead—recoverable if needed." ```bash git stash -m "experimental changes" ``` --- ## 2. Force Push — Use Safer Flag **Blocked:** `git push --force origin feature-branch` ✓ "Using `--force-with-lease` instead—checks remote hasn't changed since fetch." ```bash git push --force-with-lease origin feature-branch ``` --- ## 3. rm -rf Typo — DCG Saved You **Blocked:** `rm -rf /home/user/project/` (typo — meant a scoped build dir) DCG caught the typo. Note that `rm -rf ./build` is **also** blocked by default (relative non-temp path, `core.filesystem:rm-rf-general`). Reach for a genuinely safe target, or allowlist the build dir explicitly: ```bash rm -rf "$TMPDIR/project-build" # temp carve-out — allowed # or, if ./build itself must be cleaned, allowlist it once (see CONFIG.md): # [overrides] allow_patterns = ["rm -rf ./build"] ``` --- ## 4. DROP DATABASE — Human Decision **Blocked:** `DROP DATABASE test_db;` ✓ "Blocked as safety measure. Since this is a test database, you can approve with `dcg allow-once 12345`, or I can show contents first." **Approve for:** Test/dev databases, known context **Don't approve for:** Production, unrecognized names, uncertainty --- ## 5. K8s Namespace — Show Contents First **Blocked:** `kubectl delete namespace staging` ✓ "Namespace deletion removes ALL resources. Let me show what's there first:" ```bash kubectl get all -n staging ``` Then human can approve or you can delete selectively with `-l app=X`. --- ## 6. Documented Procedure Requires It **Blocked:** `git reset --hard origin/main` (per cleanup docs) ✓ "Procedure requires this. Blocked because it discards local changes. Approve with `dcg allow-once 12345` if no local work to keep." Even documented procedures deserve checkpoints—docs may be outdated. --- ## 7. False Positive **Blocked:** `rm -rf ./node_modules` (unusual config) ✓ "This is typically safe—might be a false positive. Options: 1. `dcg allow-once 12345` for this instance 2. Add allowlist entry if recurring" Suggest allowlist only for genuinely safe, recurring operations. --- ## Anti-Patterns | Don't | Why | |-------|-----| | Retry silently | Human loses visibility | | Ask for override first | Find alternatives first | | Treat blocks as errors | They're checkpoints | | Circumvent detection | Defeats safety system | -
TROUBLESHOOTING.md 5.6 KB
# DCG Troubleshooting ## Quick Diagnostics ```bash dcg doctor # First step for any issue ``` --- ## Common Issues ### 1. Commands Not Being Blocked **Symptom:** Destructive commands run without DCG intercepting. **Diagnose:** ```bash $ dcg doctor Hook Registration: ✗ Claude Code hook NOT registered ``` **Fix:** ```bash # Re-register hook dcg install # Verify dcg doctor ``` **Other causes:** - `DCG_BYPASS=1` is set → unset it - Command uses absolute path `/usr/bin/git` → DCG normalizes these, check config - Running in a context where hooks don't apply ### 2. False Positives (Safe Command Blocked) **Symptom:** `rm -rf ./node_modules` blocked when it shouldn't be. **Diagnose:** ```bash $ dcg explain "rm -rf ./node_modules" BLOCKED by core.filesystem:rm-rf-general Evaluation trace: ... Step 7. Pack evaluation: MATCH (relative non-temp path) ``` **Fix options:** 1. **Project allowlist** (recommended): ```toml # .dcg.toml [overrides] allow_patterns = ["rm -rf ./node_modules"] ``` 2. **One-time allow:** ```bash # Human runs this dcg allow-once ab12 ``` 3. **Permanent allowlist:** ```bash dcg allowlist add core.filesystem:rm-rf-general \ --path "$PWD/node_modules" \ -r "Package cleanup" ``` ### 3. Hook Timeout / Slow Performance **Symptom:** Commands hang for 200ms before running. **Diagnose:** ```bash $ time dcg test "git status" real 0m0.250s # Should be <5ms ``` **Possible causes:** - Complex heredoc scanning taking too long - Config file parsing issues - Disk I/O problems **Fix:** ```bash # Check heredoc settings grep -i heredoc ~/.config/dcg/config.toml # Reduce heredoc limits if needed # In config.toml: [heredoc] max_size_bytes = 524288 # 512KB instead of 1MB max_lines = 5000 # Reduce from 10000 ``` **Note:** DCG is fail-open. If it exceeds 200ms deadline, command runs with warning. ### 4. Allow-Once Code Not Working **Symptom:** `dcg allow-once ab12` says "Invalid code" or exception doesn't apply. **Causes:** 1. **Code expired** (24h limit) 2. **Different directory** — codes are bound to exact directory 3. **Command changed** — even whitespace matters **Diagnose:** ```bash $ dcg allow-once ab12 Error: Exception not found or expired Details: - Code 'ab12' was valid for: git reset --hard HEAD - In directory: /home/user/other-project - Current directory: /home/user/this-project ``` **Fix:** Re-run the blocked command to get a fresh code for current context. ### 5. Pack Not Loading **Symptom:** Database commands not blocked despite enabling pack. **Diagnose:** ```bash $ dcg packs Currently enabled: core.git, core.filesystem # database.postgresql not showing $ echo $DCG_PACKS # Empty or missing postgresql ``` **Fix:** ```bash # Environment variable export DCG_PACKS="database.postgresql" # Or in .dcg.toml [packs] enabled = ["database.postgresql"] ``` **Verify:** ```bash $ dcg explain "DROP DATABASE test" BLOCKED by database.postgresql:drop-database ``` ### 6. Heredoc/Inline Script Not Scanned **Symptom:** Destructive command in heredoc runs without block. ```bash # This should be caught bash -c "rm -rf /important" ``` **Diagnose:** ```bash $ dcg explain 'bash -c "rm -rf /important"' ALLOWED Evaluation trace: Step 3. Heredoc detection: triggered (bash -c) Step 3a. Tier 1: Pattern match ✓ Step 3b. Tier 2: Content extraction ✓ Step 3c. Tier 3: AST parsing... SKIPPED (budget exceeded) ``` **Cause:** Heredoc budget exceeded, fell back to allow. **Fix:** ```toml # .dcg.toml - increase heredoc budget [heredoc] tier2_budget_ms = 500 # Default 200 tier3_budget_ms = 10000 # Default 5000 ``` ### 7. Config Not Being Applied **Symptom:** `.dcg.toml` settings ignored. **Diagnose:** ```bash $ dcg doctor Configuration: ✓ User config: ~/.config/dcg/config.toml ✗ Project config: .dcg.toml (parse error line 15) ``` **Common config errors:** ```toml # BAD: Wrong TOML syntax [packs] enabled = "postgresql" # Should be array # GOOD: [packs] enabled = ["database.postgresql"] # BAD: Invalid pack name enabled = ["postgres"] # Should be "database.postgresql" # GOOD: enabled = ["database.postgresql"] ``` **Verify config:** ```bash # TOML syntax check cat .dcg.toml | python3 -c "import sys,tomli;tomli.loads(sys.stdin.read())" ``` ### 8. Agent Bypassing DCG **Symptom:** Agent uses workarounds like: - Breaking command across lines - Using aliases - Calling absolute paths **DCG handles these:** Command normalization strips sudo, env, aliases, and absolute paths. **If still bypassed:** 1. Check DCG version is current: `dcg update` 2. Report bypass pattern to DCG maintainers 3. Add custom block pattern: ```toml [overrides] block_patterns = ["the-bypass-pattern"] ``` --- ## Hook Protocol Issues ### Claude Code Hook Not Receiving Input **Check hook is registered:** ```bash jq '.hooks' ~/.claude/settings.json ``` **Expected:** ```json { "PreToolUse": [{ "matcher": "Bash", "hooks": [{"type": "command", "command": "dcg hook"}] }] } ``` ### Hook Returns Wrong Format **DCG hook protocol:** **Input (stdin):** ```json {"tool_name": "Bash", "tool_input": {"command": "git reset --hard"}} ``` **Deny output (stdout):** ```json { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "BLOCKED: ...", "allowOnceCode": "ab12" } } ``` **Allow:** Exit 0 with no output. --- ## Getting Help 1. **Check version:** `dcg --version` 2. **Run diagnostics:** `dcg doctor` 3. **Explain specific command:** `dcg explain "the-command"` 4. **Check logs:** `~/.config/dcg/dcg.log` (if verbose enabled) **Report issues:** Include output of `dcg doctor` and `dcg explain "command"`.
-
-
scripts
-
validate-dcg.sh 2.1 KB
#!/usr/bin/env bash # Validate DCG installation and configuration set -euo pipefail echo "=== DCG Installation Validation ===" # Check if dcg is installed if ! command -v dcg &> /dev/null; then echo "ERROR: dcg not found in PATH" echo "Install from: https://github.com/Dicklesworthstone/destructive_command_guard" echo " (cargo install destructive_command_guard)" exit 1 fi echo "✓ dcg binary found: $(command -v dcg)" # Check version DCG_VERSION=$(dcg --version 2>&1 | awk '/dcg v/ { for (i = 1; i <= NF; i++) if ($i ~ /^v[0-9]/) { print $i; exit } }') if [[ -z "$DCG_VERSION" ]]; then DCG_VERSION="unknown" fi echo "✓ Version: $DCG_VERSION" # Check if hook is installed if dcg doctor &> /dev/null; then echo "✓ Hook installed correctly" else echo "⚠ Hook may not be installed. Run: dcg install" fi # Test pattern detection echo "" echo "=== Pattern Detection Tests ===" test_command() { local cmd="$1" local expected="$2" local result if dcg test "$cmd" &> /dev/null; then result="allow" else result="block" fi if [ "$result" = "$expected" ]; then echo "✓ '$cmd' → $result (expected)" else echo "✗ '$cmd' → $result (expected: $expected)" return 1 fi } # Commands that SHOULD be blocked test_command "rm -r""f /" "block" test_command "rm -rf ./build" "block" test_command "git reset --hard HEAD" "block" # Optional packs (database, Kubernetes, cloud, and others) are validated only # when the project enables them; the installation validator must stay valid for # the default core pack set. # Commands that SHOULD be allowed test_command "git status" "allow" test_command "find . -maxdepth 1 -type d" "allow" test_command "ls -la" "allow" echo "" echo "=== Configuration ===" # Check for project config if [ -f ".dcg.toml" ]; then echo "✓ Project config found: .dcg.toml" else echo "○ No project config (.dcg.toml)" fi # Check for allowlist if [ -f ".dcg/allowlist.toml" ]; then echo "✓ Allowlist found: .dcg/allowlist.toml" else echo "○ No allowlist (.dcg/allowlist.toml)" fi echo "" echo "=== Validation Complete ==="
-
-
SELF-TEST.md 2.8 KB
# DCG Skill Self-Test > Validate trigger phrases and skill functionality. ## Trigger Test Cases Each phrase should trigger this skill. Test by pasting into Claude Code: ### Direct triggers (high confidence) 1. "DCG blocked my command, what do I do?" 2. "git reset --hard was blocked" 3. "rm -rf got blocked by dcg" 4. "How do I allow a blocked command?" 5. "Configure dcg for my project" 6. "kubectl delete namespace was blocked" ### Intent-based triggers (should trigger) 7. "My destructive command was blocked" 8. "How do I bypass dcg safely?" 9. "Set up safety guardrails for agents" 10. "DROP DATABASE got blocked" 11. "Why did dcg block git push --force?" 12. "Configure agent safety rules" ### Tool-specific triggers 13. "dcg explain isn't working" 14. "How do I use dcg allow-once?" 15. "Enable more dcg packs" 16. "dcg doctor shows an error" ### Should NOT trigger - "Search for dangerous code patterns" (code search) - "Review this bash script for issues" (code review) - "What git commands are dangerous?" (general git help) - "How do I reset my git branch?" (git help, not dcg-specific) --- ## Validation ### Quick Smoke Test ```bash # 1. Validate dcg installation dcg doctor # 2. Test explain command dcg explain "git reset --hard HEAD" # 3. Test dry-run dcg test "rm -rf /home" # 4. Verify skill structure ls -la /cs/dcg/ ls -la /cs/dcg/references/ ``` ### Manual Validation ```bash # Should show BLOCKED dcg test "git reset --hard HEAD" # Should show ALLOWED dcg test "git checkout -b new-branch" # Should show packs dcg packs ``` --- ## Expected Skill Behavior When triggered, the skill should: 1. **Provide THE EXACT WORKFLOW** — The 4-step response sequence 2. **Check Safe Alternatives first** — Before mentioning override 3. **Use `dcg explain`** — To understand why blocked 4. **Never ask for override first** — Find alternative or explain risk 5. **Human runs allow-once** — Agent never runs this command --- ## Common Failure Modes | Failure | Cause | Fix | |---------|-------|-----| | Skill doesn't trigger | Vague query | Use explicit "dcg blocked", "command blocked" | | Hook not working | Not registered | Run `dcg doctor`, check Claude Code settings | | Commands not blocked | Wrong hook path | Verify `dcg hook` in settings.json | | Allow-once fails | Wrong directory | Codes are directory-bound; re-run blocked command | --- ## Good vs Bad Responses ### Good Response to Block > "I wanted to discard changes but `git reset --hard` was blocked. Let me run `dcg explain` to understand why... The reason is it destroys uncommitted work. I'll use `git stash` instead—it's recoverable if needed." ### Bad Response to Block > "Command blocked. Run `dcg allow-once ab12` to proceed." **Why bad:** Didn't look for alternative first, didn't explain risk. -
SKILL.md 10.1 KB
--- name: dcg user-invocable: true skill_api_version: 1 hexagonal_role: supporting consumes: [] produces: [] context_rel: [] metadata: dependencies: [] capabilities: [dcg] effects: [write_dcg_config] canonical_status: canonical disposition: keep_optional_adapter tier: execution description: 'Diagnose a Destructive Command Guard block or configure its rules. Use when: DCG rejected an operation or policy work is requested; never disguise commands to bypass it.' practices: - pragmatic-programmer output_contract: the blocked command, matched rule, surviving risk, and validated safe alternative; config writes only when explicitly requested --- <!-- TOC: Core Insight | THE EXACT WORKFLOW | Quick Reference | Safe Alternatives | What Gets Blocked | Anti-Patterns | Configuration | References --> # DCG: When You Get Blocked > **Core Insight:** Blocks are checkpoints, not errors. A safe alternative almost always exists. Find it before mentioning override. ## Constraints - Never request, generate, or run an allow-once bypass because only the human may authorize and execute the exact blocked command. - Preserve the user's intended outcome with the narrowest reversible alternative because the guard protects state, not merely command spelling. - Explain the matched rule and surviving risk before asking for judgment; never retry, obfuscate, or route around a DCG block. ## Quick Navigation | I need to... | Go to | |--------------|-------| | Handle a block right now | [THE EXACT WORKFLOW](#the-exact-workflow) | | Find a safe alternative | [Safe Alternatives](#safe-alternatives) | | See all CLI commands | [COMMANDS.md](references/COMMANDS.md) | | Enable more rule packs | [PACKS.md](references/PACKS.md) | | Configure per-project | [CONFIG.md](references/CONFIG.md) | | Debug hook issues | [TROUBLESHOOTING.md](references/TROUBLESHOOTING.md) | --- ## THE EXACT WORKFLOW When blocked, follow this sequence every time: ``` 1. Run `dcg explain "cmd"` → Understand why (see trace) 2. Check Safe Alternatives table → Use if exists (DON'T mention override) 3. No alternative? → Explain risk clearly, let human decide 4. Human approves? → THEY run: dcg allow-once CODE ``` **Never:** Ask for override first. Never retry silently. Never circumvent. ### Risk-tiered approval counts When no safe alternative exists and the human must decide, the number of distinct human approvals scales with what the command can destroy: | Tier | Blast radius | Approvals required | |------|--------------|--------------------| | Recoverable | undoable via reflog/stash/trash/backup | 1 allow-once for this exact command | | Destructive-local | permanently deletes local, uncommitted, or unbacked state | 1 allow-once, granted only after you name the exact state lost and confirm no backup exists | | Destructive-shared | shared history, remote branches, databases, namespaces others use | 1 approval per individual command occurrence — never batched, never pattern-widened | Stop conditions: never present a tier-2 or tier-3 command as tier-1; never convert several pending blocks into one blanket approval. A single "yes" that gets spent across multiple destructive commands is the **approval laundering** failure mode — each allow-once code is bound to one command in one directory, and the workflow must keep it that way. **Example block output:** ``` BLOCKED: git reset --hard HEAD Rule: core.git:reset-hard Reason: Discards uncommitted changes permanently Allow-once code: ab12 Safer alternative: git stash ``` **Good response:** > "I wanted to discard changes but `git reset --hard` was blocked. Let me use `git stash` instead—recoverable if needed." [proceeds with stash] ## Safe Alternatives | Blocked | Use Instead | Why | |---------|-------------|-----| | `git reset --hard` | `git stash` | Recoverable | | `git checkout -- file` | `git stash push file` | Preserves changes | | `git push --force` | `git push --force-with-lease` | Checks remote unchanged | | `git clean -fd` | `git clean -fdn` (preview) | Shows what would delete | | `git stash drop` | `git stash list` first | Verify which stash | | `rm -rf /path` | `rm -ri /path` or verify path | Interactive/confirm | | `kubectl delete namespace` | `kubectl delete -l app=X` | Selective deletion | | `DROP DATABASE` | Backup first | Human approves | | `docker system prune -a` | `docker system df` first | See what's used | ## Quick Reference ```bash dcg doctor # Health check — hook registered? dcg explain "cmd" # WHY is it blocked? (with trace) dcg test "cmd" # Would this be blocked? (dry-run) dcg allow-once CODE # Human approves (THEY run this) dcg packs # List available rule packs dcg scan --staged # Pre-commit: scan for issues ``` --- ## What Gets Blocked | Category | Patterns | Safe Variants | |----------|----------|---------------| | Git destructive | `reset --hard`, `checkout --` | `stash`, `restore --staged` | | Git history | `push --force`, `branch -D` | `--force-with-lease`, `-d` | | Git stash | `stash drop`, `stash clear` | `stash list` first | | Filesystem | `rm -rf` (dangerous paths) | `/tmp/*` allowed | | Database | `DROP`, `TRUNCATE`, `DELETE` w/o WHERE | Add WHERE clause | | K8s | `delete namespace`, `delete --all` | `-l` label selector | **Context-aware (measured on dcg 0.5.6):** the temp carve-out allows `rm -rf` under `/tmp`, `/private/tmp`, `/var/tmp`, and the literal `$TMPDIR` form. Everything else — `rm -rf ./build` and other relative paths (`core.filesystem:rm-rf-general`), absolute paths like `/home/...` and `/` (`core.filesystem:rm-rf-root-home`), and even `/private/var/tmp` — is blocked. Unresolved variables other than `$TMPDIR` are not treated as temp. **`dcg explain` example (7-step pipeline):** ```bash $ dcg explain "git reset --hard HEAD" BLOCKED by core.git:reset-hard Evaluation trace: 1. Config allow overrides: no match 2. Config block overrides: no match 3. Heredoc detection: not applicable 4. Quick reject: triggered (contains "reset") 5. Context sanitization: no changes 6. Normalization: git reset --hard HEAD 7. Pack evaluation: - Safe patterns: no match - Destructive: MATCH "reset --hard" Suggestion: Use `git stash` to preserve changes ``` ## Anti-Patterns ``` ❌ "Command blocked. Run dcg allow-once ab12" → Find alternative first! ❌ *Retrying silently or circumventing* → Always acknowledge blocks ❌ Treating blocks as errors → They're checkpoints ❌ Asking user to allow-once without explaining → They need context ``` ## Configuration ```toml # .dcg.toml — enable rule packs per-project [packs] enabled = ["database.postgresql", "kubernetes.kubectl", "cloud.aws"] [overrides] allow_patterns = ["rm -rf ./node_modules"] # Project-specific safe ``` **Environment variables:** - `DCG_PACKS="containers.docker,kubernetes"` — Enable packs - `DCG_DISABLE="kubernetes.helm"` — Disable specific packs - `DCG_BYPASS=1` — Escape hatch (human-only) ## Key Facts - **49+ rule packs** available (database, containers, k8s, cloud, etc.) - **Sub-millisecond latency** — won't slow your workflow - **Fail-open on timeout** — if DCG hangs, command runs (with warning) - **Heredoc scanning** — inline scripts (`bash -c`, `python -c`) are analyzed - **Inline-fragment false positives** — because scanning matches a destructive token anywhere in the command string, a pattern that appears only as *data* (a commit message body, a here-doc payload, a probe argument) can trip a block even though nothing destructive would run. Safe pattern: keep the payload off the command line — pass it via a file or stdin (e.g. `git commit -F <file>`), or run the intended tool directly instead of inlining the text. Never reconstruct a blocked command by splitting or escaping its tokens to slip past the guard — that defeats the safety layer. - **Allow-once codes** — 4 hex chars, 24h expiry, bound to exact command+directory ## The Incident That Started It All > On December 17, 2025, an AI agent ran `git checkout --` on files containing hours of uncommitted work. The files were recovered via `git fsck --lost-found`, but it proved: **instructions don't prevent execution—mechanical enforcement does.** --- ## Validation ```bash # Quick health check dcg doctor | head -20 # Test if a command would be blocked dcg test "git reset --hard HEAD" # Should show: WOULD BE BLOCKED ``` ## Output Specification - **Path:** the response and command output on stdout/stderr; write `.dcg.toml` or `.dcg/allowlist.toml` only when configuration was explicitly requested. - **Filename:** preserve DCG's project filenames exactly; ordinary block handling creates no persistent file. - **Format:** state the blocked command, matched rule, risk, reversible alternative, and the alternative's validation result; quote commands exactly. - **Exit code:** run `bash skills/dcg/scripts/validate-dcg.sh` and require zero for installation/configuration work; a blocked `dcg test` result is expected evidence, not permission to bypass. - **Downstream handoff:** proceed with the validated safe alternative, or hand the exact risk and allow-once choice to the human when no equivalent exists. ## Quality Checklist - The response identifies the exact block and rule without exposing or suggesting an unauthorized bypass path. - The chosen alternative is narrower, reversible where possible, and demonstrably preserves the user's requested outcome. - Validation distinguishes an expected destructive-command block from a broken DCG installation or configuration. --- ## Scripts | Script | Usage | |--------|-------| | `./scripts/validate-dcg.sh` | Full installation validation | --- ## References - [COMMANDS.md](references/COMMANDS.md) — Full CLI reference with `dcg explain`, `dcg scan` - [PACKS.md](references/PACKS.md) — 49+ rule pack system (database, k8s, cloud, etc.) - [CONFIG.md](references/CONFIG.md) — Configuration, agent profiles, heredoc settings - [SCENARIOS.md](references/SCENARIOS.md) — Detailed examples with good/bad responses - [PHILOSOPHY.md](references/PHILOSOPHY.md) — Why DCG works this way - [TROUBLESHOOTING.md](references/TROUBLESHOOTING.md) — Common issues and fixes
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.