1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#![cfg_attr(coverage_nightly, coverage(off))]
use super::types::*;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::fs;
use std::path::Path;
// =============================================================================
// CB-081: Dependency Count Detection (Enhanced v2.9)
// Per rust-project-score spec: Too many dependencies degrades build times,
// increases supply chain risk, and bloats binaries.
//
// Enhancements:
// - CB-081-A: Base dependency count scoring
// - CB-081-B: Duplicate crate detection
// - CB-081-C: Feature flag hygiene analysis
// - CB-081-D: Sovereign stack bonus
// - CB-081-E: Trend tracking
// =============================================================================
/// Sovereign stack crates (batuta ecosystem)
const SOVEREIGN_CRATES: &[&str] = &[
"aprender",
"trueno",
"trueno-graph",
"trueno-db",
"trueno-rag",
"trueno-viz",
"trueno-zram-core",
"pmcp",
"presentar-core",
"renacer",
"certeza",
"bashrs",
"probar",
"ruchy",
];
/// Dependency count analysis result (enhanced)
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DependencyCountReport {
pub direct_count: usize,
/// Total packages in Cargo.lock (includes dev-dep transitive)
pub transitive_count: usize,
/// Production-only transitive count (excludes dev-dep transitive), used for scoring
pub prod_transitive_count: Option<usize>,
pub score: u8, // 0-5 points based on rust-project-score thresholds
/// Crates with multiple versions in Cargo.lock
pub duplicate_crates: Vec<DuplicateCrate>,
/// Dependencies using default-features = false
pub feature_gated_count: usize,
pub feature_gated_pct: f64,
/// Sovereign stack crates used
pub sovereign_crates: Vec<String>,
pub sovereign_bonus: u8, // 0-3 bonus points
/// Delta from previous check (if available)
pub trend: Option<DependencyTrend>,
pub violations: Vec<CbPatternViolation>,
}
/// Duplicate crate info
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DuplicateCrate {
pub name: String,
pub versions: Vec<String>,
}
/// Trend tracking data
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DependencyTrend {
pub direct_delta: i32,
pub transitive_delta: i32,
pub previous_timestamp: String,
}
/// CB-081 Cache for O(1) dependency analysis (issue #148 fix)
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub(super) struct DependencyCache {
/// Cargo.lock file mtime (unix timestamp)
cargo_lock_mtime: u64,
/// Cached transitive count (all packages from Cargo.lock)
transitive_count: usize,
/// Cached production-only transitive count (via cargo tree --no-dev)
#[serde(default)]
prod_transitive_count: Option<usize>,
/// Cached duplicate crates
duplicate_crates: Vec<DuplicateCrate>,
}
// =============================================================================
// CB-130: Agent Context Adoption (PMAT-470)
// =============================================================================
/// CB-130 Agent Context Adoption report
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentContextReport {
/// Whether the RAG index exists
pub index_exists: bool,
/// Index age in hours (None if no index)
pub index_age_hours: Option<f64>,
/// Whether index is considered stale (>24h)
pub index_stale: bool,
/// Number of functions indexed
pub function_count: usize,
/// Whether CLAUDE.md mentions pmat_query_code
pub claude_md_configured: bool,
/// Required patterns missing from CLAUDE.md
pub missing_required_patterns: Vec<String>,
/// Forbidden patterns found in CLAUDE.md
pub forbidden_patterns_found: Vec<ForbiddenPatternMatch>,
}
/// A forbidden pattern match with location info
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ForbiddenPatternMatch {
/// The pattern that was found
pub pattern: String,
/// Line number where it was found
pub line: usize,
/// The actual line content (truncated)
pub context: String,
}
// --- Include implementation files ---
include!("dependency_checks_cache.rs");
include!("dependency_checks_analysis.rs");
include!("dependency_checks_agent_context.rs");