Files
zesdex/apps/infrastructure/src/best_practice/mod.rs
T
asepharyana 7b0b53671f style: format seluruh workspace dengan cargo fmt
Menyeragamkan format kode sesuai rustfmt (126 file). Sebelumnya
lefthook pre-commit 'cargo fmt --check' akan gagal pada commit apa pun.
2026-08-27 22:10:28 +07:00

187 lines
6.6 KiB
Rust

//! # Built-in Kana Engineering Best Practices Engine
//!
//! This module provides compile-time embedded skills, architecture audit,
//! code-quality scanning, and commit-message validation as **built-in**
//! features of the zesdex binary — not external configuration files.
//!
//! ## Modules
//!
//! | Module | Purpose |
//! |--------|---------|
//! | [`skills`] | Compile-time embedded skill markdown files via `include_dir!` |
//! | [`arch_audit`] | Clean-architecture layering violation scanner |
//! | [`code_quality`] | Clean-code rule checker (unwrap, missing docs, etc.) |
//! | [`commit`] | Conventional Commits message validator |
//!
//! ## Usage
//!
//! The [`BestPracticeEngine`] struct provides a unified API that tools call.
//! New tool implementations in `crate::tools::best_practice` delegate to this
//! engine.
pub mod arch_audit;
pub mod code_quality;
pub mod commit;
pub mod explore;
pub mod skills;
use anyhow::Result;
use std::path::Path;
/// Unified engine for all best-practice operations.
///
/// Wraps the individual audit, quality, and commit modules behind a single
/// struct that tools and subagents can call without knowing the module layout.
#[derive(Default)]
pub struct BestPracticeEngine {
/// Compile-time embedded skills, lazy-loaded.
embedded_skills: std::sync::OnceLock<skills::EmbeddedSkills>,
}
impl BestPracticeEngine {
/// Create a new engine (skills index is built lazily on first access).
pub fn new() -> Self {
BestPracticeEngine {
embedded_skills: std::sync::OnceLock::new(),
}
}
// ── Skills ─────────────────────────────────────────────────────────
/// Access the embedded skills index.
pub fn skills(&self) -> &skills::EmbeddedSkills {
self.embedded_skills
.get_or_init(skills::EmbeddedSkills::load)
}
/// List all available embedded-skills names.
pub fn list_skills(&self) -> Vec<&'static str> {
self.skills().list()
}
/// Get the full content of a skill by name.
pub fn get_skill(&self, name: &str) -> Option<&'static str> {
self.skills().get(name)
}
/// Get skill summaries (name + description).
pub fn skill_summaries(&self) -> Vec<(&'static str, &'static str)> {
self.skills().summaries()
}
// ── Architecture Audit ─────────────────────────────────────────────
/// Run a full architecture layering audit on a workspace directory.
pub fn audit_layering(&self, workspace_root: &Path) -> Result<arch_audit::AuditReport> {
arch_audit::audit_layering(workspace_root)
}
// ── Code Quality ───────────────────────────────────────────────────
/// Run a full code-quality scan on a workspace directory.
pub fn scan_quality(&self, workspace_root: &Path) -> Result<code_quality::CodeQualityReport> {
code_quality::scan_quality(workspace_root)
}
// ── Commit Convention ──────────────────────────────────────────────
/// Validate a commit message against Conventional Commits.
pub fn validate_commit(&self, message: &str) -> Result<(), Vec<String>> {
commit::validate_commit_message(message)
}
/// Parse a commit message into its structured fields.
pub fn parse_commit(&self, message: &str) -> Option<commit::CommitInfo> {
commit::parse_commit_message(message)
}
/// Get a commit template suggestion.
pub fn suggest_commit_template(&self, type_: &str, scope: Option<&str>) -> String {
commit::suggest_template(type_, scope)
}
// ── Combined Audit ─────────────────────────────────────────────────
/// Run all audits (layering + code quality) and return combined results.
pub fn audit_all(&self, workspace_root: &Path) -> Result<CombinedAuditReport> {
let layering = self.audit_layering(workspace_root)?;
let quality = self.scan_quality(workspace_root)?;
Ok(CombinedAuditReport { layering, quality })
}
}
/// Combined report from all audits.
#[derive(Debug, Clone)]
pub struct CombinedAuditReport {
pub layering: arch_audit::AuditReport,
pub quality: code_quality::CodeQualityReport,
}
impl CombinedAuditReport {
/// Format the full report as a human-readable string.
pub fn format(&self) -> String {
let mut out = String::new();
// ── Layering ──
out.push_str(&format!(
"=== Architecture Layering Audit ===\n\
Files scanned: {}\n",
self.layering.files_scanned
));
if self.layering.violations.is_empty() {
out.push_str(" ✅ No layering violations found.\n");
} else {
for v in &self.layering.violations {
out.push_str(&format!(
" [{}] {}:{} — {}\n",
v.severity, v.file, v.line, v.message
));
}
}
// ── Code Quality ──
out.push_str(&format!(
"\n=== Code Quality Scan ===\n\
Files scanned: {}\n",
self.quality.files_scanned
));
if self.quality.findings.is_empty() {
out.push_str(" ✅ No code-quality issues found.\n");
} else {
let by_rule = self.quality.count_by_rule();
out.push_str(" By rule:\n");
for (rule, count) in &by_rule {
out.push_str(&format!(" {rule}: {count}\n"));
}
out.push_str(" Top findings:\n");
for f in self.quality.findings.iter().take(20) {
out.push_str(&format!(
" [{}] {}:{} — {}: {}\n",
f.severity, f.file, f.line, f.rule, f.message
));
}
if self.quality.findings.len() > 20 {
out.push_str(&format!(
" ... and {} more findings.\n",
self.quality.findings.len() - 20
));
}
}
out
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn engine_lists_skills() {
let engine = BestPracticeEngine::new();
let names = engine.list_skills();
assert!(names.contains(&"clean-code"));
}
}