b77f537dc6
- neuron-runtime, neuron-store, neuron-migrate: fix path deps (products/engram/ → foundation/engram/engrams/, products/el/ → foundation/el/engrams/) - neuron-rs workspace: fix axon-events/axon-protocol paths (../../../platform/ → ../../platform/, paths were off by one level) - neuron-lang/compiler/ removed (el self-hosting compiler now lives in foundation/el/el-compiler/)
145 lines
5.1 KiB
EmacsLisp
145 lines
5.1 KiB
EmacsLisp
// knowledge.el — Knowledge base subsystem.
|
|
//
|
|
// Knowledge is stable reference material: architecture docs, coding standards,
|
|
// proven patterns, whitepapers. Unlike memories (which are ephemeral
|
|
// observations), knowledge nodes are meant to persist across many sessions
|
|
// and become more authoritative over time.
|
|
//
|
|
// The tier system enforces epistemological discipline:
|
|
// note → raw observation (default)
|
|
// lesson → validated pattern (proven ≥2 times)
|
|
// canonical → authoritative reference (stable, widely referenced)
|
|
//
|
|
// Never skip tiers. A pattern observed once is a note, not a lesson.
|
|
|
|
from types import {
|
|
Knowledge,
|
|
SearchResult,
|
|
NeuronError,
|
|
}
|
|
|
|
// ── Key path utilities ────────────────────────────────────────────────────────
|
|
|
|
// Knowledge keys use path notation: "architecture/vbd/foundations.md"
|
|
// The key doubles as a stable human-readable address and the graph node ID.
|
|
// When evolving knowledge, the key stays stable — only content and tier change.
|
|
|
|
// ── Public API ────────────────────────────────────────────────────────────────
|
|
|
|
// capture_knowledge — store a new knowledge node.
|
|
//
|
|
// The key should be a path-style string that describes where this knowledge
|
|
// lives in the taxonomy: "architecture/styles/vbd/foundations.md",
|
|
// "coding/rust/error-handling.md", etc.
|
|
@manager
|
|
fn capture_knowledge(
|
|
title: String,
|
|
content: String,
|
|
category: String,
|
|
tier: String,
|
|
tags: [String],
|
|
project: String,
|
|
) -> Result<Knowledge, NeuronError> {
|
|
let id = native_uuid()
|
|
let now = native_now()
|
|
// Derive a stable key from category + title (slugified by runtime).
|
|
let key = category + "/" + title
|
|
let knowledge = Knowledge {
|
|
id: id,
|
|
key: key,
|
|
title: title,
|
|
content: content,
|
|
category: category,
|
|
tier: tier,
|
|
tags: tags,
|
|
project: project,
|
|
created_at: now,
|
|
}
|
|
native_store_knowledge(knowledge)?
|
|
native_emit("knowledge.captured", {"id": id, "tier": tier, "category": category})
|
|
Ok(knowledge)
|
|
}
|
|
|
|
// retrieve_knowledge — fetch a knowledge node by its path key.
|
|
//
|
|
// This is the primary retrieval path for known knowledge. When you know the
|
|
// key ("architecture/vbd/fundamentals.md"), use this. For exploratory queries,
|
|
// use search_knowledge.
|
|
@accessor
|
|
fn retrieve_knowledge(key: String) -> Result<Knowledge, NeuronError> {
|
|
// The native layer maps key → graph node via an index.
|
|
let results = activate Knowledge where "key:{key}"
|
|
// Return the first (most relevant) result or not-found.
|
|
let knowledge = native_get_knowledge(key)?
|
|
Ok(knowledge)
|
|
}
|
|
|
|
// search_knowledge — semantic search over the knowledge graph.
|
|
//
|
|
// Supports optional category and tier filters. Always search before
|
|
// implementing anything — the knowledge base contains patterns and
|
|
// decisions that should not be reinvented.
|
|
@accessor
|
|
fn search_knowledge(
|
|
query: String,
|
|
category: String,
|
|
tier: String,
|
|
limit: Int,
|
|
) -> Result<[Knowledge], NeuronError> {
|
|
let results = activate Knowledge where "{query} category:{category} tier:{tier} limit:{limit}"
|
|
Ok(results)
|
|
}
|
|
|
|
// browse_knowledge — list knowledge nodes by category.
|
|
//
|
|
// Used to orient at session start or when exploring an unfamiliar domain.
|
|
// Returns a summary list, not full content — use retrieve_knowledge for
|
|
// the full text of a specific node.
|
|
@accessor
|
|
fn browse_knowledge(category: String) -> Result<[Knowledge], NeuronError> {
|
|
let knowledge_list = native_list_knowledge(category)?
|
|
Ok(knowledge_list)
|
|
}
|
|
|
|
// evolve_knowledge — update an existing knowledge node.
|
|
//
|
|
// When new evidence supersedes an existing canonical, call this rather than
|
|
// capture_knowledge. The old node is soft-deleted; the new one inherits the
|
|
// key path so all existing references remain valid.
|
|
@manager
|
|
fn evolve_knowledge(
|
|
id: String,
|
|
new_content: String,
|
|
new_tier: String,
|
|
supersedes_id: String?,
|
|
) -> Result<Knowledge, NeuronError> {
|
|
let old = native_get_knowledge(id)?
|
|
let now = native_now()
|
|
let evolved = Knowledge {
|
|
id: native_uuid(),
|
|
key: old.key,
|
|
title: old.title,
|
|
content: new_content,
|
|
category: old.category,
|
|
tier: new_tier,
|
|
tags: old.tags,
|
|
project: old.project,
|
|
created_at: now,
|
|
}
|
|
native_store_knowledge(evolved)?
|
|
native_emit("knowledge.evolved", {"old_id": id, "new_id": evolved.id, "tier": new_tier})
|
|
Ok(evolved)
|
|
}
|
|
|
|
// remove_knowledge — delete a knowledge node.
|
|
//
|
|
// Use sparingly. Knowledge is meant to accumulate. Only remove nodes that
|
|
// are factually wrong, not just outdated (prefer evolve_knowledge for
|
|
// supersession).
|
|
@manager
|
|
fn remove_knowledge(id: String) -> Result<Knowledge, NeuronError> {
|
|
let knowledge = native_get_knowledge(id)?
|
|
native_emit("knowledge.removed", {"id": id, "key": knowledge.key})
|
|
Ok(knowledge)
|
|
}
|