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, orhttpiekeywords 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.,
kforkubectl). - 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.1This 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:
/// 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()→ Constructspack_id:pattern_nameget_rule_id()→ Returns stored or computed valueensure_rule_id()→ Setsrule_idif 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:
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 bypasspotentially_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:
→ UseRuleMetricsPatternEffectiveness→ UseRuleEffectivenessPatternEffectiveness→ UseRuleStatsPatternStatwith pack_id→ UseRuleAnalysisPackEffectivenessAnalysis
Query Patterns for Rule-Level Metrics
Per-Rule Trigger Count
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
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
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 `
- Query
commandstable filtered byrule_id - Compute
OutcomeStatsfrom results - Return
PatternEffectivenessstruct populated from query - No new structs needed
For `dcg history analyze`
The existing PackEffectivenessAnalysis already computes PatternEffectiveness
for each pattern. To add rule-level access:
- Add
rule_idtoPatternEffectiveness(computed from pack_id + pattern) - Add
by_rule_id: HashMap<String, PatternEffectiveness>to analysis result - No new analysis pipeline needed
For Rule-Specific Recommendations
Extend PackRecommendation with:
/// 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 |
Related Issues
- 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)