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.
This commit is contained in:
1 parent
884b19ccb5
commit
7b0b53671f
127 files changed
+1271
-1156
No files matched your search
@@ -59,17 +59,25 @@ pub struct AuditReport {
|
||||
impl AuditReport {
|
||||
/// True if any ERROR-level violations exist.
|
||||
pub fn has_errors(&self) -> bool {
|
||||
self.violations.iter().any(|v| v.severity == Severity::Error)
|
||||
self.violations
|
||||
.iter()
|
||||
.any(|v| v.severity == Severity::Error)
|
||||
}
|
||||
|
||||
/// Number of errors.
|
||||
pub fn error_count(&self) -> usize {
|
||||
self.violations.iter().filter(|v| v.severity == Severity::Error).count()
|
||||
self.violations
|
||||
.iter()
|
||||
.filter(|v| v.severity == Severity::Error)
|
||||
.count()
|
||||
}
|
||||
|
||||
/// Number of warnings.
|
||||
pub fn warning_count(&self) -> usize {
|
||||
self.violations.iter().filter(|v| v.severity == Severity::Warning).count()
|
||||
self.violations
|
||||
.iter()
|
||||
.filter(|v| v.severity == Severity::Warning)
|
||||
.count()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,11 +160,7 @@ fn forbidden_imports(layer: &str) -> &'static [&'static str] {
|
||||
}
|
||||
|
||||
/// Scan a single Rust source file for forbidden imports.
|
||||
fn scan_file(
|
||||
file_path: &Path,
|
||||
layer: &'static str,
|
||||
root: &Path,
|
||||
) -> Vec<Violation> {
|
||||
fn scan_file(file_path: &Path, layer: &'static str, root: &Path) -> Vec<Violation> {
|
||||
let mut violations = Vec::new();
|
||||
let content = match std::fs::read_to_string(file_path) {
|
||||
Ok(c) => c,
|
||||
@@ -185,10 +189,12 @@ fn scan_file(
|
||||
// `use crate::` in domain could reference domain-only items — skip.
|
||||
continue;
|
||||
}
|
||||
if trimmed.starts_with(&pattern) || trimmed.starts_with(&format!("use {forbidden}::")) {
|
||||
if trimmed.starts_with(&pattern)
|
||||
|| trimmed.starts_with(&format!("use {forbidden}::"))
|
||||
{
|
||||
// Skip test code — test modules commonly import outer layers.
|
||||
let is_test = content[..content.len().saturating_sub(1)]
|
||||
.contains("#[cfg(test)]");
|
||||
let is_test =
|
||||
content[..content.len().saturating_sub(1)].contains("#[cfg(test)]");
|
||||
if is_test {
|
||||
continue;
|
||||
}
|
||||
@@ -243,10 +249,7 @@ pub fn audit_layering(root: &Path) -> Result<AuditReport> {
|
||||
}
|
||||
|
||||
// Determine which crate this file belongs to by walking up.
|
||||
let layer = path
|
||||
.ancestors()
|
||||
.skip(1)
|
||||
.find_map(|p| classify_layer(p));
|
||||
let layer = path.ancestors().skip(1).find_map(|p| classify_layer(p));
|
||||
|
||||
if let Some(layer) = layer {
|
||||
files_scanned += 1;
|
||||
@@ -371,7 +374,10 @@ mod tests {
|
||||
fn function_metrics_short_function_ok() {
|
||||
let content = "fn ok() {\n let x = 1;\n}\n";
|
||||
let violations = check_function_metrics(content);
|
||||
let long: Vec<_> = violations.iter().filter(|v| v.message.contains("Function too long")).collect();
|
||||
let long: Vec<_> = violations
|
||||
.iter()
|
||||
.filter(|v| v.message.contains("Function too long"))
|
||||
.collect();
|
||||
assert!(long.is_empty(), "short function should not trigger");
|
||||
}
|
||||
|
||||
@@ -383,7 +389,10 @@ mod tests {
|
||||
}
|
||||
lines.push_str("}\n");
|
||||
let violations = check_function_metrics(&lines);
|
||||
let long: Vec<_> = violations.iter().filter(|v| v.message.contains("Function too long")).collect();
|
||||
let long: Vec<_> = violations
|
||||
.iter()
|
||||
.filter(|v| v.message.contains("Function too long"))
|
||||
.collect();
|
||||
assert!(!long.is_empty(), "long function should trigger warning");
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,9 @@ pub struct CodeQualityReport {
|
||||
|
||||
impl CodeQualityReport {
|
||||
pub fn has_errors(&self) -> bool {
|
||||
self.findings.iter().any(|f| f.severity == super::arch_audit::Severity::Error)
|
||||
self.findings
|
||||
.iter()
|
||||
.any(|f| f.severity == super::arch_audit::Severity::Error)
|
||||
}
|
||||
pub fn count_by_rule(&self) -> Vec<(&'static str, usize)> {
|
||||
let mut counts: std::collections::HashMap<&str, usize> = std::collections::HashMap::new();
|
||||
@@ -147,7 +149,8 @@ pub fn scan_quality_file(file_path: &Path, root: &Path) -> Vec<Finding> {
|
||||
|
||||
// ── Rule: Missing doc comments on pub items ────────────────────
|
||||
if (trimmed.starts_with("pub ") || trimmed.starts_with("pub("))
|
||||
&& !prev_line_doc && !prev_line_empty
|
||||
&& !prev_line_doc
|
||||
&& !prev_line_empty
|
||||
{
|
||||
// Check it's a struct/enum/fn/trait/type/const/mod
|
||||
let is_item = trimmed.starts_with("pub fn ")
|
||||
@@ -246,7 +249,10 @@ mod tests {
|
||||
std::fs::write(&file, "fn x() { let y = foo.unwrap(); }\n").unwrap();
|
||||
|
||||
let findings = scan_quality_file(&file, &dir);
|
||||
let unwrap_findings: Vec<_> = findings.iter().filter(|f| f.rule == "unwrap-in-production").collect();
|
||||
let unwrap_findings: Vec<_> = findings
|
||||
.iter()
|
||||
.filter(|f| f.rule == "unwrap-in-production")
|
||||
.collect();
|
||||
assert!(!unwrap_findings.is_empty(), "should detect unwrap");
|
||||
}
|
||||
|
||||
@@ -262,8 +268,14 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
let findings = scan_quality_file(&file, &dir);
|
||||
let unwrap_findings: Vec<_> = findings.iter().filter(|f| f.rule == "unwrap-in-production").collect();
|
||||
assert!(unwrap_findings.is_empty(), "should skip unwrap in test blocks");
|
||||
let unwrap_findings: Vec<_> = findings
|
||||
.iter()
|
||||
.filter(|f| f.rule == "unwrap-in-production")
|
||||
.collect();
|
||||
assert!(
|
||||
unwrap_findings.is_empty(),
|
||||
"should skip unwrap in test blocks"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -274,7 +286,13 @@ mod tests {
|
||||
std::fs::write(&file, "#[allow(clippy::too_many_arguments)]\nfn x() {}\n").unwrap();
|
||||
|
||||
let findings = scan_quality_file(&file, &dir);
|
||||
let bypass_findings: Vec<_> = findings.iter().filter(|f| f.rule == "compiler-bypass").collect();
|
||||
assert!(!bypass_findings.is_empty(), "should detect allow attributes");
|
||||
let bypass_findings: Vec<_> = findings
|
||||
.iter()
|
||||
.filter(|f| f.rule == "compiler-bypass")
|
||||
.collect();
|
||||
assert!(
|
||||
!bypass_findings.is_empty(),
|
||||
"should detect allow attributes"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -50,10 +50,9 @@ pub fn validate_commit_message(msg: &str) -> Result<(), Vec<String>> {
|
||||
}
|
||||
|
||||
// Parse: `type(scope): description` or `type!: description` or `type: description`
|
||||
let re = Regex::new(
|
||||
r"^(?P<type>[a-z]+)(?:\((?P<scope>[^)]+)\))?(?P<breaking>!)?:\s+(?P<desc>.+)$",
|
||||
)
|
||||
.expect("valid regex for commit parsing");
|
||||
let re =
|
||||
Regex::new(r"^(?P<type>[a-z]+)(?:\((?P<scope>[^)]+)\))?(?P<breaking>!)?:\s+(?P<desc>.+)$")
|
||||
.expect("valid regex for commit parsing");
|
||||
|
||||
match re.captures(subject) {
|
||||
None => {
|
||||
@@ -94,21 +93,19 @@ pub fn validate_commit_message(msg: &str) -> Result<(), Vec<String>> {
|
||||
} else {
|
||||
let first_char = desc.chars().next().unwrap_or(' ');
|
||||
if first_char.is_uppercase() {
|
||||
errors.push(format!(
|
||||
"Description must start with lowercase: '{desc}'"
|
||||
));
|
||||
errors.push(format!("Description must start with lowercase: '{desc}'"));
|
||||
}
|
||||
if desc.ends_with('.') {
|
||||
errors.push(format!(
|
||||
"Description must not end with a period: '{desc}'"
|
||||
));
|
||||
errors.push(format!("Description must not end with a period: '{desc}'"));
|
||||
}
|
||||
}
|
||||
|
||||
// Type-specific rules.
|
||||
match type_ {
|
||||
"chore" | "docs" | "refactor" | "test" | "style" | "perf" | "ci" | "build"
|
||||
| "revert" if scope.is_some() => {
|
||||
| "revert"
|
||||
if scope.is_some() =>
|
||||
{
|
||||
errors.push(format!(
|
||||
"'{type_}' commits should not use a scope. \
|
||||
Only 'feat' and 'fix' require scopes."
|
||||
@@ -140,10 +137,9 @@ pub fn parse_commit_message(msg: &str) -> Option<CommitInfo> {
|
||||
let msg = msg.trim();
|
||||
let subject = msg.lines().next()?;
|
||||
|
||||
let re = Regex::new(
|
||||
r"^(?P<type>[a-z]+)(?:\((?P<scope>[^)]+)\))?(?P<breaking>!)?:\s+(?P<desc>.+)$",
|
||||
)
|
||||
.expect("valid regex");
|
||||
let re =
|
||||
Regex::new(r"^(?P<type>[a-z]+)(?:\((?P<scope>[^)]+)\))?(?P<breaking>!)?:\s+(?P<desc>.+)$")
|
||||
.expect("valid regex");
|
||||
|
||||
let caps = re.captures(subject)?;
|
||||
|
||||
@@ -155,10 +151,18 @@ pub fn parse_commit_message(msg: &str) -> Option<CommitInfo> {
|
||||
};
|
||||
|
||||
Some(CommitInfo {
|
||||
type_: caps.name("type").map(|m| m.as_str()).unwrap_or("").to_string(),
|
||||
type_: caps
|
||||
.name("type")
|
||||
.map(|m| m.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string(),
|
||||
scope: caps.name("scope").map(|m| m.as_str().to_string()),
|
||||
breaking: caps.name("breaking").is_some(),
|
||||
description: caps.name("desc").map(|m| m.as_str()).unwrap_or("").to_string(),
|
||||
description: caps
|
||||
.name("desc")
|
||||
.map(|m| m.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string(),
|
||||
body,
|
||||
})
|
||||
}
|
||||
@@ -232,7 +236,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parses_valid_commit() {
|
||||
let parsed = parse_commit_message("feat(agent): add parallel execution\n\nWith cycle orchestration.").unwrap();
|
||||
let parsed = parse_commit_message(
|
||||
"feat(agent): add parallel execution\n\nWith cycle orchestration.",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(parsed.type_, "feat");
|
||||
assert_eq!(parsed.scope, Some("agent".to_string()));
|
||||
assert!(!parsed.breaking);
|
||||
|
||||
@@ -51,7 +51,6 @@ const EXPLORE_DIRECTIVES: [&str; 3] = [
|
||||
4. Identify main entry points (main.rs, main.py, index.ts, etc.).\n\
|
||||
5. Count files by extension type.\n\
|
||||
Use the ls_dir, read, grep, and glob tools. Be concise.",
|
||||
|
||||
// Agent 1: Symbol Index
|
||||
"You are a symbol index explorer.\n\
|
||||
1. Call the 'rebuild_index' tool to rebuild the symbol index.\n\
|
||||
@@ -59,7 +58,6 @@ const EXPLORE_DIRECTIVES: [&str; 3] = [
|
||||
3. Identify public APIs, entry points, and key types.\n\
|
||||
4. Group symbols by language and kind.\n\
|
||||
Be concise. Report what symbols exist and where they live.",
|
||||
|
||||
// Agent 2: Semantic Context
|
||||
"You are a semantic context explorer.\n\
|
||||
1. Call the 'rebuild_index' tool to ensure the index is fresh.\n\
|
||||
@@ -231,8 +229,8 @@ async fn run_explore_phase(
|
||||
let tc = tool_ctx.clone();
|
||||
|
||||
let handle = thread::spawn(move || {
|
||||
let rt = tokio::runtime::Runtime::new()
|
||||
.context("create explore subagent tokio runtime")?;
|
||||
let rt =
|
||||
tokio::runtime::Runtime::new().context("create explore subagent tokio runtime")?;
|
||||
rt.block_on(run_agent(ctx, &directive, AccessTier::Read, tc))
|
||||
});
|
||||
|
||||
@@ -252,12 +250,22 @@ async fn run_explore_phase(
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
warn!(agent = i, error = %e, "explore subagent failed");
|
||||
emit_failed(&turn_events_clone, EXPLORE_IDS[i], EXPLORE_LABELS[i], &e.to_string());
|
||||
emit_failed(
|
||||
&turn_events_clone,
|
||||
EXPLORE_IDS[i],
|
||||
EXPLORE_LABELS[i],
|
||||
&e.to_string(),
|
||||
);
|
||||
(i, format!("Error: {e}"), false)
|
||||
}
|
||||
Err(e) => {
|
||||
warn!(agent = i, error = ?e, "explore subagent panicked");
|
||||
emit_failed(&turn_events_clone, EXPLORE_IDS[i], EXPLORE_LABELS[i], "thread panicked");
|
||||
emit_failed(
|
||||
&turn_events_clone,
|
||||
EXPLORE_IDS[i],
|
||||
EXPLORE_LABELS[i],
|
||||
"thread panicked",
|
||||
);
|
||||
(i, format!("Thread panic: {e:?}"), false)
|
||||
}
|
||||
};
|
||||
@@ -281,9 +289,7 @@ fn build_explore_context(results: &[(usize, String, bool)]) -> String {
|
||||
let success_count = results.iter().filter(|r| r.2).count();
|
||||
let total = results.len();
|
||||
|
||||
let mut msg = format!(
|
||||
"[Explore Phase — {success_count}/{total} agents succeeded]\n\n"
|
||||
);
|
||||
let mut msg = format!("[Explore Phase — {success_count}/{total} agents succeeded]\n\n");
|
||||
|
||||
for (i, output, success) in results {
|
||||
let label = EXPLORE_LABELS.get(*i).unwrap_or(&"❓ Unknown");
|
||||
|
||||
@@ -107,10 +107,7 @@ impl BestPracticeEngine {
|
||||
let layering = self.audit_layering(workspace_root)?;
|
||||
let quality = self.scan_quality(workspace_root)?;
|
||||
|
||||
Ok(CombinedAuditReport {
|
||||
layering,
|
||||
quality,
|
||||
})
|
||||
Ok(CombinedAuditReport { layering, quality })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user