feat: Add SOLID principles and TDD reference documentation
- Created solid.md to document the SOLID principles for clean code practices. - Created tdd.md to outline Test Driven Development principles and practices. - Added kana-rust-backend-best-practice.md as a reference guide for building a Rust backend using Axum and SeaORM. - Established push-flow-convention.md to enforce pre-commit and pre-push hooks with versioning rules. - Introduced AGENTS.md to provide guidance on best practices and available commands for Kilo. - Configured kilo.json to include new skills and agents for enhanced functionality. - Added lefthook.yml for managing git hooks to ensure code quality and adherence to conventions.
This commit is contained in:
@@ -77,12 +77,14 @@ pub struct DirCache {
|
||||
}
|
||||
|
||||
impl DirCache {
|
||||
/// Create an empty directory cache.
|
||||
pub fn new() -> Self {
|
||||
DirCache {
|
||||
entries: Arc::new(tokio::sync::RwLock::new(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace the cached directory entries.
|
||||
pub async fn set(&self, paths: Vec<PathBuf>) {
|
||||
let mut w = self.entries.write().await;
|
||||
*w = paths;
|
||||
@@ -103,24 +105,28 @@ pub struct MentionIndex {
|
||||
}
|
||||
|
||||
impl MentionIndex {
|
||||
/// Create an empty mention index.
|
||||
pub fn new() -> Self {
|
||||
MentionIndex {
|
||||
entries: Arc::new(std::sync::RwLock::new(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace the entire index with a new set of file paths.
|
||||
pub fn set(&self, paths: Vec<String>) {
|
||||
if let Ok(mut w) = self.entries.write() {
|
||||
*w = paths;
|
||||
}
|
||||
}
|
||||
|
||||
/// Append a single file path to the index.
|
||||
pub fn push(&self, path: String) {
|
||||
if let Ok(mut w) = self.entries.write() {
|
||||
w.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a copy of all indexed paths.
|
||||
pub fn snapshot(&self) -> Vec<String> {
|
||||
self.entries.read().map(|r| r.clone()).unwrap_or_default()
|
||||
}
|
||||
|
||||
@@ -3,21 +3,24 @@
|
||||
use tower_http::cors::{AllowHeaders, AllowOrigin, CorsLayer};
|
||||
|
||||
/// Return a permissive CorsLayer for local daemon IPC.
|
||||
///
|
||||
/// All method and header names are static strings guaranteed to be valid
|
||||
/// HTTP tokens — `.parse()` is infallible here.
|
||||
pub fn default_cors_layer() -> CorsLayer {
|
||||
CorsLayer::new()
|
||||
.allow_origin(AllowOrigin::any())
|
||||
.allow_methods([
|
||||
"GET".parse().unwrap(),
|
||||
"POST".parse().unwrap(),
|
||||
"PUT".parse().unwrap(),
|
||||
"DELETE".parse().unwrap(),
|
||||
"PATCH".parse().unwrap(),
|
||||
"OPTIONS".parse().unwrap(),
|
||||
"GET".parse().expect("static HTTP method"),
|
||||
"POST".parse().expect("static HTTP method"),
|
||||
"PUT".parse().expect("static HTTP method"),
|
||||
"DELETE".parse().expect("static HTTP method"),
|
||||
"PATCH".parse().expect("static HTTP method"),
|
||||
"OPTIONS".parse().expect("static HTTP method"),
|
||||
])
|
||||
.allow_headers(AllowHeaders::any())
|
||||
.expose_headers([
|
||||
"Content-Type".parse().unwrap(),
|
||||
"X-Session-Id".parse().unwrap(),
|
||||
"X-Request-Id".parse().unwrap(),
|
||||
"Content-Type".parse().expect("static HTTP header"),
|
||||
"X-Session-Id".parse().expect("static HTTP header"),
|
||||
"X-Request-Id".parse().expect("static HTTP header"),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ impl MemoryRepository for MarkdownMemoryRepository {
|
||||
|
||||
fn save(&self, memory_dir: &Path, memory: &Memory) -> Result<(), RepositoryError> {
|
||||
let path = Memory::path(memory_dir, &memory.name);
|
||||
let parent = path.parent().unwrap();
|
||||
let parent = path.parent().expect("memory path always has a parent directory");
|
||||
std::fs::create_dir_all(parent)?;
|
||||
|
||||
let frontmatter = Self::build_frontmatter(memory);
|
||||
|
||||
@@ -85,16 +85,17 @@ fn compiled_regexes() -> (
|
||||
Regex,
|
||||
Regex,
|
||||
) {
|
||||
// All regex patterns are static — compilation is infallible.
|
||||
(
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?(?:(?:unsafe\s+)?async\s+)?fn\s+(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?struct\s+(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?enum\s+(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?(?:(?:unsafe\s+)?)?trait\s+(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?mod\s+(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?(?:unsafe\s+)?impl(?:\s*<[^>]*>)?\s+(?:for\s+)?(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?type\s+(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?const\s+(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?macro_rules!\s*\(\s*(\w+)").unwrap(),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?(?:(?:unsafe\s+)?async\s+)?fn\s+(\w+)").expect("fn regex"),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?struct\s+(\w+)").expect("struct regex"),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?enum\s+(\w+)").expect("enum regex"),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?(?:(?:unsafe\s+)?)?trait\s+(\w+)").expect("trait regex"),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?mod\s+(\w+)").expect("mod regex"),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?(?:unsafe\s+)?impl(?:\s*<[^>]*>)?\s+(?:for\s+)?(\w+)").expect("impl regex"),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?type\s+(\w+)").expect("type regex"),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?const\s+(\w+)").expect("const regex"),
|
||||
Regex::new(r"(?m)^\s*(?:pub\s+)?macro_rules!\s*\(\s*(\w+)").expect("macro regex"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -272,7 +273,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Check for function declarations
|
||||
if let Some(caps) = fn_re.captures(trimmed) {
|
||||
let name = caps.get(1).unwrap().as_str().to_string();
|
||||
let name = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
let doc = doc_comments.get(&line_num).cloned();
|
||||
symbols.push(CodeSymbol {
|
||||
name,
|
||||
@@ -287,7 +288,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Check for struct declarations
|
||||
if let Some(caps) = struct_re.captures(trimmed) {
|
||||
let name = caps.get(1).unwrap().as_str().to_string();
|
||||
let name = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
let doc = doc_comments.get(&line_num).cloned();
|
||||
symbols.push(CodeSymbol {
|
||||
name,
|
||||
@@ -302,7 +303,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Check for enum declarations
|
||||
if let Some(caps) = enum_re.captures(trimmed) {
|
||||
let name = caps.get(1).unwrap().as_str().to_string();
|
||||
let name = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
let doc = doc_comments.get(&line_num).cloned();
|
||||
symbols.push(CodeSymbol {
|
||||
name,
|
||||
@@ -317,7 +318,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Check for trait declarations
|
||||
if let Some(caps) = trait_re.captures(trimmed) {
|
||||
let name = caps.get(1).unwrap().as_str().to_string();
|
||||
let name = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
let doc = doc_comments.get(&line_num).cloned();
|
||||
symbols.push(CodeSymbol {
|
||||
name,
|
||||
@@ -332,7 +333,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Check for module declarations
|
||||
if let Some(caps) = mod_re.captures(trimmed) {
|
||||
let name = caps.get(1).unwrap().as_str().to_string();
|
||||
let name = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
symbols.push(CodeSymbol {
|
||||
name,
|
||||
kind: SymbolKind::Module,
|
||||
@@ -346,7 +347,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Check for type alias declarations
|
||||
if let Some(caps) = type_re.captures(trimmed) {
|
||||
let name = caps.get(1).unwrap().as_str().to_string();
|
||||
let name = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
let doc = doc_comments.get(&line_num).cloned();
|
||||
symbols.push(CodeSymbol {
|
||||
name,
|
||||
@@ -361,7 +362,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Check for const declarations
|
||||
if let Some(caps) = const_re.captures(trimmed) {
|
||||
let name = caps.get(1).unwrap().as_str().to_string();
|
||||
let name = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
let doc = doc_comments.get(&line_num).cloned();
|
||||
symbols.push(CodeSymbol {
|
||||
name,
|
||||
@@ -376,7 +377,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Check for macro declarations
|
||||
if let Some(caps) = macro_re.captures(trimmed) {
|
||||
let name = caps.get(1).unwrap().as_str().to_string();
|
||||
let name = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
symbols.push(CodeSymbol {
|
||||
name,
|
||||
kind: SymbolKind::Macro,
|
||||
@@ -390,7 +391,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
|
||||
// Parse impl blocks for method-level indexing
|
||||
if let Some(caps) = impl_re.captures(trimmed) {
|
||||
let impl_for = caps.get(1).unwrap().as_str().to_string();
|
||||
let impl_for = caps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
// Look for methods inside this impl block
|
||||
let mut brace_depth: i32 = 0;
|
||||
let mut started = false;
|
||||
@@ -413,7 +414,7 @@ fn extract_symbols(content: &str, rel_path: &str) -> Vec<CodeSymbol> {
|
||||
if j > 0 {
|
||||
let inner_line = l.trim();
|
||||
if let Some(mcaps) = fn_re.captures(inner_line) {
|
||||
let method_name = mcaps.get(1).unwrap().as_str().to_string();
|
||||
let method_name = mcaps.get(1).expect("capture group 1 exists by regex").as_str().to_string();
|
||||
let abs_line = i + j + 1;
|
||||
let doc = doc_comments.get(&abs_line).cloned();
|
||||
symbols.push(CodeSymbol {
|
||||
|
||||
Reference in New Issue
Block a user