# Knowledge Base Nickel Schemas

This directory contains Nickel schema definitions for the knowledge base configuration system.

## Overview

The KOGRAL uses a **config-driven architecture** with Nickel providing type-safe configuration:

```text
.ncl files → nickel export --format json → JSON → serde → Rust structs
```

**Benefits:**
- Type safety at config definition time (Nickel type checker)
- Composition and reuse (Nickel imports)
- Runtime type-safe Rust structs (serde)
- Clear contracts and documentation

## Schema Files

| File | Purpose |
| --- | --- |
| `types.ncl` | Shared type definitions (enums, primitives) |
| `kogral-config.ncl` | Main configuration schema (KbConfig) |
| `frontmatter.ncl` | Document frontmatter schema (YAML in .md files) |

## Usage

### Export Schema to JSON

```bash
# Export a configuration file
nickel export --format json config/defaults.ncl > .kogral/config.json

# Export minimal config
nickel export --format json config/minimal.ncl > .kogral/config.json

# Export production config
nickel export --format json config/production.ncl > .kogral/config.json
```

### Create Custom Configuration

```nickel
# my-kogral-config.ncl
let Schema = import "schemas/kogral-config.ncl" in

{
  graph = {
    name = "my-project",
    version = "1.0.0",
  },

  embeddings = {
    provider = 'ollama,
    model = "llama2",
  },

  # Other fields use defaults
} | Schema.KbConfig
```

### Type Checking

Nickel will validate your configuration against the schema:

```bash
# Check configuration without exporting
nickel typecheck my-kogral-config.ncl

# Export (also type-checks)
nickel export --format json my-kogral-config.ncl
```

## Schema Structure

### Main Config (`kogral-config.ncl`)

```nickel
KbConfig = {
  graph: GraphConfig,           # Graph metadata
  inheritance: InheritanceConfig,  # Guideline inheritance
  storage: StorageConfig,        # Storage backends
  embeddings: EmbeddingConfig,   # Embedding providers
  templates: TemplateConfig,     # Tera templates
  query: QueryConfig,            # Search behavior
  mcp: McpConfig,                # MCP server settings
  sync: SyncConfig,              # Filesystem ↔ DB sync
}
```

### Frontmatter (`frontmatter.ncl`)

```nickel
Frontmatter = {
  id: String,                    # UUID
  type: NodeType,                # note, decision, etc.
  title: String,                 # Human-readable title
  created: Timestamp,            # ISO 8601
  modified: Timestamp,           # ISO 8601
  tags: Array String,            # Categorization
  status: NodeStatus,            # draft, active, etc.
  relates_to: Array String,      # Relationships
  # ... type-specific fields
}
```

## Examples

### Default Configuration

See `config/defaults.ncl` for a fully documented example with sensible defaults.

### Minimal Configuration

```nickel
{
  graph = { name = "my-kogral" },
} | Schema.KbConfig
```

All other fields will use schema defaults.

### Production Configuration

See `config/production.ncl` for a production setup with:
- SurrealDB backend enabled
- API-based embeddings (OpenAI)
- Optimized sync settings

## Field Defaults

All config fields have sensible defaults. Required fields:

- `graph.name` - Graph identifier

Optional fields (with defaults):
- `graph.version` → `"1.0.0"`
- `storage.primary` → `'filesystem`
- `embeddings.provider` → `'fastembed`
- `query.similarity_threshold` → `0.4`
- `mcp.server.transport` → `'stdio`
- ... (see schema files for complete list)

## Type Definitions

### Enums

Defined in `types.ncl`:

```nickel
NodeType = [| 'note, 'decision, 'guideline, 'pattern, 'journal, 'execution |]
NodeStatus = [| 'draft, 'active, 'superseded, 'archived |]
StorageType = [| 'filesystem, 'memory |]
EmbeddingProvider = [| 'openai, 'claude, 'ollama, 'fastembed |]
```

### Primitives

- `String` - Text values
- `Number` - Numeric values
- `Bool` - Boolean values
- `Array T` - Lists of type T
- `{ _ | T }` - Map/dictionary with values of type T

## Validation

Nickel enforces:
- **Required fields**: Must be present
- **Type constraints**: Values must match declared types
- **Enum values**: Must be one of the allowed variants
- **Default values**: Applied automatically if field omitted

Example error:

```bash
$ nickel export invalid-config.ncl
error: type error
  ┌─ invalid-config.ncl:5:15
  │
5 │   provider = 'gpt4,
  │              ^^^^^ this expression has type [| 'gpt4 |]
  │
  = Expected an expression of type [| 'openai, 'claude, 'ollama, 'fastembed |]
```

## Integration with Rust

The Rust code loads JSON via serde:

```rust
use kb_core::config::loader::load_config;

// Load from .kogral/config.{ncl,toml,json}
let config = load_config(None, None)?;

// Access type-safe fields
println!("Graph: {}", config.graph.name);
println!("Provider: {:?}", config.embeddings.provider);
```

## References

- [Nickel Language](https://nickel-lang.org/)
- [Nickel Documentation](https://nickel-lang.org/user-manual/)
- Rust schema types: `crates/kogral-core/src/config/schema.rs`
