471 lines
11 KiB
Markdown
471 lines
11 KiB
Markdown
# Design Philosophy
|
|
|
|
The principles and values guiding KOGRAL design and implementation.
|
|
|
|
## Core Tenets
|
|
|
|
### 1. Config-Driven, Not Hardcoded
|
|
|
|
**Principle**: All behavior should be configurable via schemas, not baked into code.
|
|
|
|
**Why**: Flexibility without code changes. Users adapt KOGRAL to their workflows, not vice versa.
|
|
|
|
**Example**:
|
|
|
|
```rust
|
|
// ❌ Bad: Hardcoded
|
|
impl EmbeddingProvider {
|
|
fn new() -> Self {
|
|
FastEmbedProvider::new("BAAI/bge-small-en-v1.5") // Can't change
|
|
}
|
|
}
|
|
|
|
// ✅ Good: Config-driven
|
|
impl EmbeddingProvider {
|
|
fn from_config(config: &EmbeddingConfig) -> Result<Box<dyn EmbeddingProvider>> {
|
|
match config.provider {
|
|
'fastembed => Ok(Box::new(FastEmbedProvider::new(&config.model)?)),
|
|
'openai => Ok(Box::new(OpenAIProvider::new(&config.model)?)),
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Benefits**:
|
|
- Switch embedding providers without recompilation
|
|
- Different configs for dev/prod
|
|
- User choice, not developer mandate
|
|
|
|
### 2. Type-Safe Configuration
|
|
|
|
**Principle**: Validate configuration before runtime, not during.
|
|
|
|
**Why**: Catch errors early, reduce runtime failures.
|
|
|
|
**Implementation**: Nickel contracts + serde validation = double validation
|
|
|
|
```nickel
|
|
# Schema defines valid values
|
|
EmbeddingProvider = [| 'openai, 'claude, 'fastembed |]
|
|
|
|
# Typo caught at export time, not runtime
|
|
{ provider = 'opena1 } # Error: Invalid variant
|
|
```
|
|
|
|
**Benefits**:
|
|
- Errors found during `nickel export`, not during execution
|
|
- Self-documenting: schema is the spec
|
|
- Refactoring safe: change schema, find all usages
|
|
|
|
### 3. Local-First, Cloud-Optional
|
|
|
|
**Principle**: Core functionality works offline, cloud is enhancement.
|
|
|
|
**Why**: Privacy, cost control, offline development.
|
|
|
|
**Examples**:
|
|
|
|
| Feature | Local | Cloud |
|
|
| --------- | ------- | ------- |
|
|
| Storage | Filesystem | SurrealDB |
|
|
| Embeddings | fastembed | OpenAI/Claude |
|
|
| Search | Text-based | Semantic |
|
|
|
|
**Benefits**:
|
|
- Works on planes, trains, areas with poor internet
|
|
- No API costs for small projects
|
|
- Privacy-sensitive projects keep data local
|
|
- Production can use cloud for scale
|
|
|
|
### 4. Git-Friendly by Default
|
|
|
|
**Principle**: Knowledge should version alongside code.
|
|
|
|
**Why**: Knowledge describes code, should evolve with it.
|
|
|
|
**Implementation**:
|
|
- Markdown + YAML frontmatter (text-based, diffable)
|
|
- One file per node (granular commits)
|
|
- Wikilinks preserved (works in Logseq, Obsidian)
|
|
|
|
**Benefits**:
|
|
|
|
```bash
|
|
# Review knowledge changes in PRs
|
|
git diff .kogral/decisions/
|
|
|
|
# Knowledge follows branches
|
|
git checkout feature-x
|
|
# .kogral/ reflects feature-x decisions
|
|
|
|
# Knowledge merges
|
|
git merge feature-x
|
|
# Merge conflicts = knowledge conflicts (resolve intentionally)
|
|
```
|
|
|
|
### 5. AI-Native, Human-Readable
|
|
|
|
**Principle**: Optimized for AI consumption, readable by humans.
|
|
|
|
**Why**: Best of both worlds - AI-assisted discovery, human verification.
|
|
|
|
**Implementation**:
|
|
- **Structured**: YAML frontmatter for AI parsing
|
|
- **Semantic**: Embeddings for AI queries
|
|
- **Readable**: Markdown for human consumption
|
|
- **Linked**: Typed relationships for AI traversal
|
|
|
|
**Example**:
|
|
|
|
```markdown
|
|
---
|
|
id: note-auth
|
|
type: note
|
|
title: Authentication Implementation
|
|
tags: [security, auth]
|
|
relates_to: [guideline-security, pattern-jwt]
|
|
---
|
|
|
|
# Authentication Implementation
|
|
|
|
Humans read this markdown normally.
|
|
|
|
AI can:
|
|
- Parse frontmatter for metadata
|
|
- Extract tags for filtering
|
|
- Follow relates_to links
|
|
- Generate embeddings for semantic search
|
|
```
|
|
|
|
### 6. Composition Over Inheritance
|
|
|
|
**Principle**: Build systems by composing small, focused components.
|
|
|
|
**Why**: Flexibility, testability, maintainability.
|
|
|
|
**Implementation**:
|
|
|
|
```rust
|
|
// Small, focused traits
|
|
trait Storage { ... }
|
|
trait EmbeddingProvider { ... }
|
|
trait TemplateEngine { ... }
|
|
|
|
// Compose into systems
|
|
struct KnowledgeBase {
|
|
storage: Box<dyn Storage>,
|
|
embeddings: Option<Box<dyn EmbeddingProvider>>,
|
|
templates: TemplateEngine,
|
|
}
|
|
```
|
|
|
|
**Benefits**:
|
|
- Swap storage without affecting embeddings
|
|
- Disable embeddings without breaking storage
|
|
- Test components in isolation
|
|
- Add new providers by implementing trait
|
|
|
|
### 7. Fail Fast, Fail Clearly
|
|
|
|
**Principle**: Detect errors early, provide clear messages.
|
|
|
|
**Why**: Developer experience - fast feedback, actionable errors.
|
|
|
|
**Implementation**:
|
|
|
|
```rust
|
|
// ❌ Bad: Silent failure
|
|
fn load_config(path: &Path) -> Option<Config> {
|
|
std::fs::read_to_string(path)
|
|
.ok()
|
|
.and_then(|s| serde_json::from_str(&s).ok())
|
|
}
|
|
|
|
// ✅ Good: Explicit errors
|
|
fn load_config(path: &Path) -> Result<Config, ConfigError> {
|
|
let content = std::fs::read_to_string(path)
|
|
.map_err(|e| ConfigError::ReadFailed(path.to_path_buf(), e))?;
|
|
|
|
serde_json::from_str(&content)
|
|
.map_err(|e| ConfigError::ParseFailed(path.to_path_buf(), e))
|
|
}
|
|
```
|
|
|
|
**Error messages**:
|
|
|
|
```text
|
|
❌ "Failed to load config"
|
|
✅ "Failed to read config file '/path/to/config.ncl': Permission denied"
|
|
```
|
|
|
|
### 8. Convention Over Configuration (With Escape Hatches)
|
|
|
|
**Principle**: Sane defaults, but everything customizable.
|
|
|
|
**Why**: Easy to start, flexible as you grow.
|
|
|
|
**Examples**:
|
|
|
|
```nickel
|
|
# Minimal config (uses conventions)
|
|
{ graph = { name = "my-project" } }
|
|
# Defaults: filesystem storage, no embeddings, standard templates
|
|
|
|
# Full config (explicit everything)
|
|
{
|
|
graph = { name = "my-project" },
|
|
storage = { primary = 'surrealdb, /* ... */ },
|
|
embeddings = { provider = 'openai, /* ... */ },
|
|
templates = { templates_dir = "custom" },
|
|
}
|
|
```
|
|
|
|
**Conventions**:
|
|
- `.kogral/` directory in project root
|
|
- Filesystem storage by default
|
|
- YAML frontmatter + markdown body
|
|
- Standard template names (note.md.tera, decision.md.tera)
|
|
|
|
**Escape hatches**:
|
|
- `--kogral-dir` to use different location
|
|
- Configure alternative storage backends
|
|
- Custom frontmatter schemas
|
|
- Override any template
|
|
|
|
### 9. Documentation as Code
|
|
|
|
**Principle**: Documentation lives with code, versioned together.
|
|
|
|
**Why**: Outdated docs are worse than no docs.
|
|
|
|
**Implementation**:
|
|
- ADRs in `.kogral/decisions/` (alongside code)
|
|
- Guidelines in `.kogral/guidelines/` (versioned with code)
|
|
- Patterns in `.kogral/patterns/` (evolve with implementations)
|
|
|
|
**Benefits**:
|
|
|
|
```bash
|
|
# Code and docs branch together
|
|
git checkout old-version
|
|
# .kogral/ reflects that version's decisions
|
|
|
|
# Code and docs merge together
|
|
git merge feature
|
|
# Merge includes new patterns, updated guidelines
|
|
|
|
# Code and docs reviewed together
|
|
# PR shows code + decision + guideline updates
|
|
```
|
|
|
|
### 10. Optimize for Discoverability
|
|
|
|
**Principle**: Knowledge is useless if you can't find it.
|
|
|
|
**Why**: The point is to **use** knowledge, not just store it.
|
|
|
|
**Features**:
|
|
- **Text search**: Find exact keywords
|
|
- **Semantic search**: Find related concepts
|
|
- **Graph traversal**: Follow relationships
|
|
- **Tag filtering**: Narrow by category
|
|
- **MCP integration**: AI-assisted discovery
|
|
|
|
**Example**:
|
|
|
|
User doesn't remember exact term, but knows the concept:
|
|
|
|
```text
|
|
"Find anything about handling errors gracefully"
|
|
```
|
|
|
|
KOGRAL finds (semantically):
|
|
- "Error Handling with thiserror" (pattern)
|
|
- "Result Type Best Practices" (guideline)
|
|
- "Panic Recovery" (note)
|
|
- "Graceful Degradation" (pattern)
|
|
|
|
No exact keyword match needed, concept match sufficient.
|
|
|
|
### 11. Build for Humans, Enable AI
|
|
|
|
**Principle**: Humans are the primary users, AI is the assistant.
|
|
|
|
**Why**: AI should enhance human workflows, not replace them.
|
|
|
|
**Implementation**:
|
|
- **Human-readable formats**: Markdown, YAML
|
|
- **Human-editable**: Any text editor works
|
|
- **Human-discoverable**: `ls .kogral/notes/` shows files
|
|
- **AI-enhanced**: MCP for AI-assisted queries
|
|
|
|
**Example**:
|
|
|
|
```bash
|
|
# Human workflow
|
|
vim .kogral/notes/my-note.md # Edit directly
|
|
git add .kogral/notes/my-note.md
|
|
git commit -m "Add note about X"
|
|
|
|
# AI-enhanced workflow
|
|
# (in Claude Code)
|
|
"Add a note about X with tags Y, Z"
|
|
# AI creates file, human reviews
|
|
```
|
|
|
|
### 12. Embrace the Graph
|
|
|
|
**Principle**: Knowledge is interconnected, embrace the relationships.
|
|
|
|
**Why**: Context comes from connections, not isolation.
|
|
|
|
**Implementation**:
|
|
- Typed relationships (not just "related")
|
|
- Bidirectional traversal
|
|
- Relationship strength (0.0-1.0)
|
|
- Multi-hop queries
|
|
|
|
**Example**:
|
|
|
|
```text
|
|
Find all patterns that:
|
|
- Are implemented by current project
|
|
- Depend on shared guidelines
|
|
- Were added in the last 6 months
|
|
|
|
# Graph query, not sequential file search
|
|
```
|
|
|
|
## Anti-Patterns to Avoid
|
|
|
|
### 1. ❌ Hardcoding Behavior
|
|
|
|
```rust
|
|
// Don't
|
|
const EMBEDDING_MODEL: &str = "BAAI/bge-small-en-v1.5";
|
|
|
|
// Do
|
|
let model = config.embeddings.model.as_str();
|
|
```
|
|
|
|
### 2. ❌ Runtime Schema Validation
|
|
|
|
```nickel
|
|
// Don't validate at runtime
|
|
let provider = config.provider; // Might be invalid
|
|
|
|
// Do validate at export time (Nickel contracts)
|
|
provider | [| 'openai, 'claude, 'fastembed |]
|
|
```
|
|
|
|
### 3. ❌ Opaque Errors
|
|
|
|
```rust
|
|
// Don't
|
|
Err("Failed".into())
|
|
|
|
// Do
|
|
Err(KbError::NodeNotFound(id.to_string()))
|
|
```
|
|
|
|
### 4. ❌ Coupling Components
|
|
|
|
```rust
|
|
// Don't
|
|
impl KnowledgeBase {
|
|
fn search(&self) -> Vec<Node> {
|
|
let embeddings = FastEmbedProvider::new(); // Hardcoded!
|
|
// ...
|
|
}
|
|
}
|
|
|
|
// Do
|
|
impl KnowledgeBase {
|
|
fn search(&self) -> Vec<Node> {
|
|
if let Some(provider) = &self.embeddings {
|
|
// Use configured provider
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5. ❌ Proprietary Formats
|
|
|
|
```text
|
|
// Don't
|
|
Binary blob: [0x4B, 0x42, 0x01, ...]
|
|
|
|
// Do
|
|
Markdown + YAML:
|
|
---
|
|
id: note-1
|
|
---
|
|
# Content
|
|
```
|
|
|
|
## Influences
|
|
|
|
KOGRAL draws inspiration from:
|
|
|
|
- **Logseq**: Outliner, graph view, wikilinks
|
|
- **Obsidian**: Markdown-first, local storage, plugins
|
|
- **Zettelkasten**: Atomic notes, links, emergence
|
|
- **ADR**: Decision records, context preservation
|
|
- **Git**: Version control, branching, merging
|
|
- **Nickel**: Type-safe configuration, contracts
|
|
- **MCP**: AI integration protocol
|
|
- **SurrealDB**: Graph database, relationships
|
|
|
|
## Implementation Principles
|
|
|
|
### Rust
|
|
|
|
- Zero unsafe code (`#![forbid(unsafe_code)]`)
|
|
- No `unwrap()` in production code
|
|
- Always use `Result<T>` for fallibility
|
|
- Comprehensive error types with `thiserror`
|
|
- Full test coverage (100+ tests)
|
|
|
|
### Nickel
|
|
|
|
- Contracts for validation
|
|
- Defaults in schemas
|
|
- Documentation in contracts
|
|
- Composition via imports
|
|
|
|
### NuShell
|
|
|
|
- Structured data pipelines
|
|
- Error handling in scripts
|
|
- Colored output for UX
|
|
- Dry-run modes
|
|
|
|
## Evolution Strategy
|
|
|
|
KOGRAL follows these guidelines for evolution:
|
|
|
|
1. **Backward Compatibility**: Don't break existing configs
|
|
2. **Deprecation Period**: Warn before removal (1 major version)
|
|
3. **Migration Tools**: Provide automated migrations
|
|
4. **Semantic Versioning**: MAJOR.MINOR.PATCH strictly
|
|
|
|
## Conclusion
|
|
|
|
These principles guide every decision:
|
|
|
|
✅ **Config-driven**: Behavior in schemas, not code
|
|
✅ **Type-safe**: Validate before runtime
|
|
✅ **Local-first**: Works offline, cloud optional
|
|
✅ **Git-friendly**: Knowledge versions with code
|
|
✅ **AI-native**: Optimized for AI, readable by humans
|
|
✅ **Composable**: Small pieces, loosely coupled
|
|
✅ **Fast feedback**: Fail early, clear errors
|
|
✅ **Discoverable**: Easy to find what you need
|
|
|
|
The goal: **Knowledge management that developers actually use.**
|
|
|
|
## Next Steps
|
|
|
|
- **See it in action**: [Use Cases](../guides/use-cases.md)
|
|
- **Understand architecture**: [System Overview](../architecture/overview.md)
|
|
- **Start using**: [Quick Start](../guides/quickstart.md)
|