destructive_command_guard

The Destructive Command Guard (dcg) is for blocking dangerous git and shell commands from being executed by agents.

RAW Doc

File: docs/architecture/pack-design.md

Pack Architecture Decisions

This document captures the architectural decisions required before expanding
pack coverage. It is the canonical reference for pack authors and reviewers.

1) REST API Pattern Detection (curl/httpie)

Decision: Hybrid detection (keyword gate + lightweight argument parsing).

  • Gate on curl, http, or httpie keywords to avoid touching every command.
  • Parse method flags (-X, --request, --method) and extract the URL.
  • Pack-specific host filters: each pack owns its hostnames or URL prefixes.
  • Decision rule: only treat DELETE (and other explicitly destructive methods)
    as destructive when the host/path match a pack.

Rationale: A pure keyword scan is too noisy; full AST parsing is too slow.
The hybrid approach is fast, deterministic, and maintainable.

2) Pack Overlap Resolution

Decision: Keep packs separate but clarify boundaries.

From git_safety_guard-qdhh: cicd.github_actions is for CI operations
(secrets, variables, workflows, runs). platform.github is for broader platform
operations (repos, releases, deploy keys, webhooks, collaborators). Do not
duplicate patterns across packs; document scope in pack descriptions.

Rationale: Separation reduces regex scope and allows users to enable only
what they need. Clear boundaries avoid duplication and false positives.

3) Command Alias Handling

Decision: Explicit aliases for high-impact, common tools plus opt-in config.

  • Include well-known aliases in keywords (e.g., k for kubectl).
  • Avoid regex alias heuristics that cause false positives.
  • Allow user config to add custom aliases via pack enablement/keywords.

Rationale: Minimizes noise while still covering common shortcuts.

4) Performance Budget Per Pack

Decision: Enforce a per-pack budget and pattern cap.

  • Budget: < 500 microseconds per pack evaluation.
  • Pattern cap: < 50 total patterns per pack.
  • Keywords: minimal and specific; avoid broad single-letter keywords.

Rationale: Keeps pack expansion from degrading hook latency.

5) Safe vs Destructive Threshold

Decision: Flag-aware matching with explicit safe overrides.

  • Destructive by default: commands known to delete or destroy data (e.g.,
    rclone sync, aws s3 rm --recursive) should be blocked even without flags.
  • Flag-sensitive: allow dry-run/preview flags and safe variants.
  • Ambiguous commands: only block when flags or subcommands are clearly
    destructive; otherwise allow with high-signal patterns.

Rationale: Reduces false positives while still blocking dangerous actions.

Acceptance Criteria Mapping

  • Decisions documented with rationale (this doc).
  • Performance budget defined and referenced by pack checklist.
  • Pack overlap resolution aligned with git_safety_guard-qdhh.

Open Questions

  • Which alias list should be system defaults vs per-user config?
  • How to represent host allowlists for REST APIs in pack metadata?

File: docs/design/rule-metrics-struct-mapping.md

Rule-Level Metrics: Struct Mapping & Reuse Strategy

Design document for git_safety_guard-1dri.1

This document inventories existing history analytics structs and maps rule-level
metrics needs to them, ensuring no duplicate or competing analytics pipelines.


Executive Summary

Finding: The existing history analytics structs in src/history/schema.rs are
well-designed and sufficient for rule-level metrics. No new analytics structs are
needed. The PatternEffectiveness struct already captures per-rule metrics, and
the rule_id field in CommandEntry provides stable rule identifiers.

Recommendation: Reuse existing structs. Extend query/aggregation logic only.


Struct Inventory

Core Data Types

Struct Location Purpose Rule-Metrics Relevance
CommandEntry L133 Single command record Primary data source - contains rule_id, pack_id, pattern_name, outcome
Outcome L81 Enum: Allow/Deny/Warn/Bypass Categorizes command outcomes for metrics

Statistics Types

Struct Location Purpose Rule-Metrics Relevance
OutcomeStats L230 Aggregate counts (allowed/denied/warned/bypassed) Can aggregate by rule
PerformanceStats L239 Latency percentiles (p50/p95/p99/max) Could extend for per-rule latency
PatternStat L248 Pattern name + count + pack_id Direct reuse for top patterns
HistoryStats L325 Complete stats for time window Contains top_patterns: Vec
StatsTrends L271 Period-over-period comparison Extendable for rule trends

Analytics Types (Key for Rule-Metrics)

Struct Location Purpose Rule-Metrics Relevance
PatternEffectiveness L2177 Per-pattern metrics with bypass analysis PERFECT FIT - use directly
PotentialGap L2195 Dangerous commands that were allowed Coverage gap analysis
RecommendationType L2208 Enum: RelaxPattern/EnablePack/etc. Tuning recommendations
PackRecommendation L2225 Actionable recommendation with config Extend for rule-specific recs
PackEffectivenessAnalysis L2246 Complete analysis result Already groups by pattern

Rule Identifier Design

The rule_id is already defined in CommandEntry:

rust
/// Stable rule identifier: `pack_id:pattern_name`
/// Present only for denied commands that matched a pattern.
/// Format: "core.git:reset-hard", "core.filesystem:rm-rf-root"
pub rule_id: Option<String>,

Key methods in CommandEntry:

  • compute_rule_id() → Constructs pack_id:pattern_name
  • get_rule_id() → Returns stored or computed value
  • ensure_rule_id() → Sets rule_id if computable

This provides stable, human-readable identifiers for:

  • Allowlisting specific rules
  • Aggregating metrics per rule
  • Tracking rule effectiveness over time

PatternEffectiveness: The Core Struct

This struct is the foundation for rule-level metrics:

rust
pub struct PatternEffectiveness {
    /// Pattern name (e.g., "reset-hard")
    pub pattern: String,
    /// Pack ID the pattern belongs to (e.g., "core.git")
    pub pack_id: Option<String>,
    /// Total times this pattern triggered (deny + bypass)
    pub total_triggers: u64,
    /// Times the pattern blocked a command (deny)
    pub denied_count: u64,
    /// Times the pattern was bypassed (allow-once)
    pub bypassed_count: u64,
    /// Bypass rate as a percentage (0.0-100.0)
    pub bypass_rate: f64,
}

Mapping to rule_id: rule_id = {pack_id}:{pattern}

Already computed in PackEffectivenessAnalysis:

  • high_value_patterns: Vec - High volume, low bypass
  • potentially_aggressive: Vec - High bypass rate

Reuse vs Extend Analysis

Direct Reuse (No Changes)

Struct Usage
CommandEntry Query by rule_id for per-rule history
PatternEffectiveness Per-rule metrics with bypass analysis
PatternStat Simple name+count for top rules
OutcomeStats Aggregate outcomes per rule

Extend (Add Fields/Methods)

Struct Extension Reason
PatternEffectiveness Add first_seen_ts, last_seen_ts Track rule activity timeline
PatternEffectiveness Add projects: Vec<String> See which projects trigger rule
PackEffectivenessAnalysis Add per_rule_metrics: HashMap<String, PatternEffectiveness> Direct rule_id lookup

Do NOT Create

To avoid competing pipelines, these should NOT be created:

  • RuleMetrics → Use PatternEffectiveness
  • RuleEffectiveness → Use PatternEffectiveness
  • RuleStats → Use PatternStat with pack_id
  • RuleAnalysis → Use PackEffectivenessAnalysis

Query Patterns for Rule-Level Metrics

Per-Rule Trigger Count

sql
SELECT rule_id, COUNT(*) as triggers
FROM commands
WHERE rule_id IS NOT NULL
GROUP BY rule_id
ORDER BY triggers DESC;

Per-Rule Bypass Rate

sql
SELECT rule_id,
       COUNT(*) as total,
       SUM(CASE WHEN outcome = 'deny' THEN 1 ELSE 0 END) as denied,
       SUM(CASE WHEN outcome = 'bypass' THEN 1 ELSE 0 END) as bypassed,
       (bypassed * 100.0 / total) as bypass_rate
FROM commands
WHERE rule_id IS NOT NULL
GROUP BY rule_id;

Rule Activity Over Time

sql
SELECT rule_id,
       date(timestamp) as day,
       COUNT(*) as triggers
FROM commands
WHERE rule_id IS NOT NULL
GROUP BY rule_id, day
ORDER BY rule_id, day;

Implementation Guidance

For `dcg history stats --rule `

  1. Query commands table filtered by rule_id
  2. Compute OutcomeStats from results
  3. Return PatternEffectiveness struct populated from query
  4. No new structs needed

For `dcg history analyze`

The existing PackEffectivenessAnalysis already computes PatternEffectiveness
for each pattern. To add rule-level access:

  1. Add rule_id to PatternEffectiveness (computed from pack_id + pattern)
  2. Add by_rule_id: HashMap<String, PatternEffectiveness> to analysis result
  3. No new analysis pipeline needed

For Rule-Specific Recommendations

Extend PackRecommendation with:

rust
/// Rule ID this recommendation targets (if rule-specific)
#[serde(skip_serializing_if = "Option::is_none")]
pub rule_id: Option<String>,

Acceptance Criteria Verification

Criterion Status Evidence
Rule-metrics design references existing structs Uses PatternEffectiveness, PatternStat, CommandEntry
No duplicate analytics pipelines No new Rule* structs proposed
Clear mapping documented This document

Version History

Version Date Changes
1.0 2026-01-16 Initial design document

  • Parent: git_safety_guard-1dri (Rule-Level Metrics: Track per-rule stats)
  • Blocked by: None
  • Blocks: git_safety_guard-1dri.2 (dcg history stats --rule)