Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: dcg user-invocable: false skill_api_version: 1 hexagonal_role: supporting consumes: [] produces: [] context_rel: [] metadata: dependencies: [] capabilities: [dcg] effects: [write_dcg_config] canonical_status: canonical disposition: keep_specialist tier: execution description: 'Handle blocked destructive commands and configure agent safety guardrails. Triggers: "dcg", "handle a DCG block", "configure agent safety guardrails".' 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 | |
| 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 decide4. 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 HEADRule: core.git:reset-hardReason: Discards uncommitted changes permanentlyAllow-once code: ab12Safer alternative: git stash
Good response:
"I wanted to discard changes butgit 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 packsdcg 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-hardEvaluation trace:1. Config allow overrides: no match2. Config block overrides: no match3. Heredoc detection: not applicable4. Quick reject: triggered (contains "reset")5. Context sanitization: no changes6. Normalization: git reset --hard HEAD7. 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 rangit 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 checkdcg doctor | head -20# Test if a command would be blockeddcg 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