400 lines
8.5 KiB
Markdown
400 lines
8.5 KiB
Markdown
|
|
# Knowledge Base Templates
|
||
|
|
|
||
|
|
This directory contains Tera templates for generating and exporting knowledge base documents.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Templates are divided into two categories:
|
||
|
|
|
||
|
|
1. **Document Templates** - Generate new KOGRAL documents with proper frontmatter
|
||
|
|
2. **Export Templates** - Export KOGRAL data to various formats (Logseq, JSON, reports)
|
||
|
|
|
||
|
|
## Document Templates
|
||
|
|
|
||
|
|
Located in the root `templates/` directory. Used to create new knowledge base entries.
|
||
|
|
|
||
|
|
### Available Templates
|
||
|
|
|
||
|
|
| Template | Purpose | Node Type |
|
||
|
|
|----------|---------|-----------|
|
||
|
|
| `note.md.tera` | General notes and observations | note |
|
||
|
|
| `decision.md.tera` | Architectural Decision Records (ADR) | decision |
|
||
|
|
| `guideline.md.tera` | Code guidelines and best practices | guideline |
|
||
|
|
| `pattern.md.tera` | Design patterns and solutions | pattern |
|
||
|
|
| `journal.md.tera` | Daily notes and journal entries | journal |
|
||
|
|
| `execution.md.tera` | Agent execution records (from Vapora) | execution |
|
||
|
|
|
||
|
|
### Template Variables
|
||
|
|
|
||
|
|
All document templates receive these common variables:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
id: String, // UUID
|
||
|
|
title: String, // Node title
|
||
|
|
created: DateTime, // ISO 8601 timestamp
|
||
|
|
modified: DateTime, // ISO 8601 timestamp
|
||
|
|
tags: Vec<String>, // Tags
|
||
|
|
status: NodeStatus, // draft, active, superseded, archived
|
||
|
|
content: String, // Markdown content
|
||
|
|
relates_to: Vec<String>, // Related node IDs
|
||
|
|
depends_on: Vec<String>, // Dependency node IDs
|
||
|
|
implements: Vec<String>, // Pattern/guideline node IDs
|
||
|
|
extends: Vec<String>, // Extension node IDs
|
||
|
|
project: Option<String>, // Project identifier
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Type-Specific Variables
|
||
|
|
|
||
|
|
**Decision (ADR):**
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
context: String, // Problem context
|
||
|
|
decision: String, // Decision made
|
||
|
|
consequences: Vec<String>, // Impacts
|
||
|
|
alternatives: Vec<{ // Alternatives considered
|
||
|
|
name: String,
|
||
|
|
description: String,
|
||
|
|
pros: Vec<String>,
|
||
|
|
cons: Vec<String>,
|
||
|
|
}>,
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Guideline:**
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
language: String, // Programming language
|
||
|
|
category: String, // Category (error-handling, testing, etc.)
|
||
|
|
overview: String, // Brief overview
|
||
|
|
rules: Vec<{ // Guideline rules
|
||
|
|
title: String,
|
||
|
|
description: String,
|
||
|
|
rationale: String,
|
||
|
|
}>,
|
||
|
|
examples: Vec<{ // Code examples
|
||
|
|
title: String,
|
||
|
|
good: String, // Good practice
|
||
|
|
bad: String, // Bad practice
|
||
|
|
explanation: String,
|
||
|
|
}>,
|
||
|
|
exceptions: Vec<String>,
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Pattern:**
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
problem: String, // Problem statement
|
||
|
|
solution: String, // Solution description
|
||
|
|
forces: Vec<String>, // Constraints/forces
|
||
|
|
context: String, // When to use
|
||
|
|
structure: String, // Pattern structure
|
||
|
|
implementation: Vec<{ // Implementation steps
|
||
|
|
title: String,
|
||
|
|
description: String,
|
||
|
|
code: String,
|
||
|
|
language: String,
|
||
|
|
}>,
|
||
|
|
consequences: {
|
||
|
|
benefits: Vec<String>,
|
||
|
|
drawbacks: Vec<String>,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Journal:**
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
date: String, // Date (YYYY-MM-DD)
|
||
|
|
tasks: Vec<{ // Tasks for the day
|
||
|
|
description: String,
|
||
|
|
completed: bool,
|
||
|
|
}>,
|
||
|
|
highlights: Vec<String>, // Daily highlights
|
||
|
|
learnings: Vec<String>, // Things learned
|
||
|
|
links: Vec<String>, // Related node IDs
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Execution:**
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
task_type: String, // Type of task
|
||
|
|
agent: String, // Agent name
|
||
|
|
outcome: String, // success, failure, etc.
|
||
|
|
duration_ms: u64, // Execution time
|
||
|
|
steps: Vec<{ // Execution steps
|
||
|
|
description: String,
|
||
|
|
duration_ms: u64,
|
||
|
|
result: String,
|
||
|
|
}>,
|
||
|
|
errors: Vec<{ // Errors encountered
|
||
|
|
type: String,
|
||
|
|
message: String,
|
||
|
|
details: String,
|
||
|
|
}>,
|
||
|
|
metrics: Vec<{ // Performance metrics
|
||
|
|
name: String,
|
||
|
|
value: f64,
|
||
|
|
unit: String,
|
||
|
|
}>,
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Export Templates
|
||
|
|
|
||
|
|
Located in `templates/export/`. Used to export KOGRAL data to external formats.
|
||
|
|
|
||
|
|
### Available Export Templates
|
||
|
|
|
||
|
|
| Template | Format | Purpose |
|
||
|
|
|----------|--------|---------|
|
||
|
|
| `logseq-page.md.tera` | Logseq Markdown | Export single node to Logseq page |
|
||
|
|
| `logseq-journal.md.tera` | Logseq Markdown | Export journal to Logseq daily note |
|
||
|
|
| `summary.md.tera` | Markdown Report | Generate KOGRAL summary report |
|
||
|
|
| `graph.json.tera` | JSON | Export entire graph to JSON |
|
||
|
|
|
||
|
|
### Export Template Variables
|
||
|
|
|
||
|
|
**Logseq Export:**
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
node: Node, // Full node object
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Summary Export:**
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
graph: {
|
||
|
|
name: String,
|
||
|
|
version: String,
|
||
|
|
description: String,
|
||
|
|
},
|
||
|
|
timestamp: DateTime,
|
||
|
|
stats: {
|
||
|
|
total_nodes: usize,
|
||
|
|
total_edges: usize,
|
||
|
|
nodes_by_type: HashMap<NodeType, usize>,
|
||
|
|
nodes_by_status: HashMap<NodeStatus, usize>,
|
||
|
|
top_tags: Vec<(String, usize)>,
|
||
|
|
},
|
||
|
|
nodes: Vec<Node>,
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**JSON Export:**
|
||
|
|
```rust
|
||
|
|
{
|
||
|
|
graph: Graph,
|
||
|
|
nodes: Vec<Node>,
|
||
|
|
edges: Vec<Edge>,
|
||
|
|
stats: Statistics,
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage Examples
|
||
|
|
|
||
|
|
### Generate a New Note
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use kb_core::export::tera::TeraEngine;
|
||
|
|
use kb_core::models::{Node, NodeType};
|
||
|
|
|
||
|
|
let tera = TeraEngine::new(Path::new("templates"))?;
|
||
|
|
let mut node = Node::new(NodeType::Note, "My Note".to_string());
|
||
|
|
node.content = "This is my note content".to_string();
|
||
|
|
node.tags = vec!["rust".to_string(), "kogral".to_string()];
|
||
|
|
|
||
|
|
let markdown = tera.render_node(&node)?;
|
||
|
|
```
|
||
|
|
|
||
|
|
### Export to Logseq
|
||
|
|
|
||
|
|
```rust
|
||
|
|
let logseq_md = tera.export_logseq(&node)?;
|
||
|
|
std::fs::write(".logseq/pages/my-note.md", logseq_md)?;
|
||
|
|
```
|
||
|
|
|
||
|
|
### Generate Summary Report
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use tera::Context;
|
||
|
|
|
||
|
|
let mut context = Context::new();
|
||
|
|
context.insert("graph", &graph);
|
||
|
|
context.insert("timestamp", &Utc::now());
|
||
|
|
context.insert("stats", &statistics);
|
||
|
|
context.insert("nodes", &nodes);
|
||
|
|
|
||
|
|
let summary = tera.render_custom("export/summary.md.tera", &context)?;
|
||
|
|
```
|
||
|
|
|
||
|
|
## Customization
|
||
|
|
|
||
|
|
### Override Default Templates
|
||
|
|
|
||
|
|
Copy a template and modify it:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cp templates/note.md.tera my-templates/custom-note.md.tera
|
||
|
|
# Edit my-templates/custom-note.md.tera
|
||
|
|
```
|
||
|
|
|
||
|
|
Update configuration:
|
||
|
|
|
||
|
|
```nickel
|
||
|
|
{
|
||
|
|
templates = {
|
||
|
|
templates_dir = "my-templates",
|
||
|
|
templates = {
|
||
|
|
note = "custom-note.md.tera",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Create Custom Templates
|
||
|
|
|
||
|
|
Add to `templates/custom/`:
|
||
|
|
|
||
|
|
```jinja2
|
||
|
|
---
|
||
|
|
id: {{ id }}
|
||
|
|
title: {{ title }}
|
||
|
|
custom_field: {{ my_custom_field }}
|
||
|
|
---
|
||
|
|
|
||
|
|
# {{ title }}
|
||
|
|
|
||
|
|
Custom template content here.
|
||
|
|
```
|
||
|
|
|
||
|
|
Register in config:
|
||
|
|
|
||
|
|
```nickel
|
||
|
|
{
|
||
|
|
templates = {
|
||
|
|
custom = {
|
||
|
|
my-template = "custom/my-template.md.tera",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Template Syntax
|
||
|
|
|
||
|
|
Templates use Tera syntax (similar to Jinja2):
|
||
|
|
|
||
|
|
### Variables
|
||
|
|
```jinja2
|
||
|
|
{{ variable }}
|
||
|
|
{{ object.field }}
|
||
|
|
{{ array.0 }}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Filters
|
||
|
|
```jinja2
|
||
|
|
{{ text | upper }}
|
||
|
|
{{ date | date(format="%Y-%m-%d") }}
|
||
|
|
{{ content | truncate(length=100) }}
|
||
|
|
{{ json_data | json_encode | safe }}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Conditionals
|
||
|
|
```jinja2
|
||
|
|
{% if condition %}
|
||
|
|
...
|
||
|
|
{% elif other_condition %}
|
||
|
|
...
|
||
|
|
{% else %}
|
||
|
|
...
|
||
|
|
{% endif %}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Loops
|
||
|
|
```jinja2
|
||
|
|
{% for item in items %}
|
||
|
|
{{ item }}
|
||
|
|
{% endfor %}
|
||
|
|
|
||
|
|
{% for key, value in map %}
|
||
|
|
{{ key }}: {{ value }}
|
||
|
|
{% endfor %}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Comments
|
||
|
|
```jinja2
|
||
|
|
{# This is a comment #}
|
||
|
|
```
|
||
|
|
|
||
|
|
## YAML Frontmatter
|
||
|
|
|
||
|
|
All document templates generate YAML frontmatter compatible with:
|
||
|
|
|
||
|
|
- **Logseq** - Wikilinks, properties
|
||
|
|
- **kogral-core parser** - Full schema validation
|
||
|
|
- **Git** - Human-readable diffs
|
||
|
|
|
||
|
|
Example:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
---
|
||
|
|
id: abc-123
|
||
|
|
type: note
|
||
|
|
title: My Note
|
||
|
|
created: 2026-01-17T10:30:00Z
|
||
|
|
modified: 2026-01-17T10:30:00Z
|
||
|
|
tags: ["rust", "kogral"]
|
||
|
|
status: draft
|
||
|
|
relates_to:
|
||
|
|
- other-note-id
|
||
|
|
---
|
||
|
|
```
|
||
|
|
|
||
|
|
## Best Practices
|
||
|
|
|
||
|
|
1. **Keep Templates Simple** - Focus on structure, not complex logic
|
||
|
|
2. **Use Defaults** - Provide sensible defaults with `| default(value="...")`
|
||
|
|
3. **Indent Consistently** - Use `| indent(width=2)` for nested content
|
||
|
|
4. **Escape User Content** - Use `| escape` for user-provided text in HTML/JSON
|
||
|
|
5. **Document Custom Fields** - Add comments explaining custom template variables
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Template Not Found
|
||
|
|
|
||
|
|
Ensure `templates_dir` in config points to the correct directory:
|
||
|
|
|
||
|
|
```nickel
|
||
|
|
templates = {
|
||
|
|
templates_dir = "templates", // Relative to project root
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Variable Not Found
|
||
|
|
|
||
|
|
Check that the variable is provided in the template context. Add a default:
|
||
|
|
|
||
|
|
```jinja2
|
||
|
|
{{ variable | default(value="") }}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Rendering Errors
|
||
|
|
|
||
|
|
Enable debug mode to see detailed error messages:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
let tera = Tera::new("templates/**/*.tera")?;
|
||
|
|
tera.autoescape_on(vec![]); // Disable autoescaping for markdown
|
||
|
|
```
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- [Tera Documentation](https://keats.github.io/tera/)
|
||
|
|
- [Logseq Markdown Format](https://docs.logseq.com/)
|
||
|
|
- kogral-core models: `crates/kogral-core/src/models.rs`
|
||
|
|
- Template engine: `crates/kogral-core/src/export/tera.rs`
|