Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 15ea584671 | |||
| c2afcbddf5 | |||
| dfe4e83ed1 | |||
| a390ee494e | |||
| 8212e12e57 | |||
| 2ed6b26dde | |||
| d8e9fd12f4 | |||
| 8fa9c4ba20 | |||
| 9c7bde47dc | |||
| c0553459e1 | |||
| fd208583fe | |||
| 3e29fc43ab | |||
| 979a5677d5 | |||
| 17b1aa0736 | |||
| f0c731d2db | |||
| e7e0f7d3e5 |
+43
-3
@@ -6,15 +6,55 @@
|
||||
//
|
||||
// Dependencies: runtime/string.el, runtime/json.el
|
||||
|
||||
// --- Validation (defense in depth) ---
|
||||
// el_val_t is an untyped machine word, so a wrong TYPE can't be caught here — but a
|
||||
// wrong VALUE can (a tier in the node_type slot, an empty/garbage string, an int, a
|
||||
// path, a model name, a cgi id). Reject loudly instead of silently writing junk.
|
||||
|
||||
fn engram_valid_node_type(t: String) -> Bool {
|
||||
return str_eq(t, "Memory") || str_eq(t, "Knowledge") || str_eq(t, "Belief")
|
||||
|| str_eq(t, "Project") || str_eq(t, "Tag") || str_eq(t, "BacklogItem")
|
||||
|| str_eq(t, "Artifact") || str_eq(t, "Conversation") || str_eq(t, "ExecutionContext")
|
||||
|| str_eq(t, "InternalStateEvent") || str_eq(t, "Self") || str_eq(t, "Entity")
|
||||
|| str_eq(t, "Process") || str_eq(t, "ConfigEntry") || str_eq(t, "Concept") || str_eq(t, "Imprint")
|
||||
|| str_eq(t, "SessionSummary")
|
||||
}
|
||||
|
||||
fn engram_valid_tier(t: String) -> Bool {
|
||||
return str_eq(t, "Semantic") || str_eq(t, "Episodic") || str_eq(t, "Working")
|
||||
|| str_eq(t, "Procedural") || str_eq(t, "Canonical") || str_eq(t, "Note") || str_eq(t, "Lesson")
|
||||
}
|
||||
|
||||
// --- Node creation ---
|
||||
|
||||
fn engram_node(content: String, node_type: String, salience: Float) -> String {
|
||||
if !engram_valid_node_type(node_type) {
|
||||
__println("[engram] REJECTED node write — invalid node_type '" + node_type + "'")
|
||||
return ""
|
||||
}
|
||||
return __engram_node(content, node_type, salience)
|
||||
}
|
||||
|
||||
fn engram_node_full(content: String, nt: String, sal: Float, imp: Float,
|
||||
source: String, lang: String, ts: Int, tags: String) -> String {
|
||||
return __engram_node_full(content, nt, sal, imp, source, lang, ts, tags)
|
||||
// Signature MUST match the C primitive __engram_node_full exactly (el_seed.h):
|
||||
// (content, node_type, label, salience, importance, confidence, tier, tags)
|
||||
// The previous wrapper declared a stale 8-arg schema with wrong names AND types
|
||||
// (sal:Float at the label slot, ts:Int at the tier slot). Because el_val_t is an
|
||||
// untyped machine word, the EL compiler coerced caller args to those wrong param
|
||||
// types and then forwarded them BY POSITION into the C function — so tier received
|
||||
// an int, importance/confidence received strings, label received a float, etc.
|
||||
// That is the field-corruption bug. Match the contract 1:1 — no coercion, no reorder.
|
||||
fn engram_node_full(content: String, node_type: String, label: String,
|
||||
salience: Float, importance: Float, confidence: Float,
|
||||
tier: String, tags: String) -> String {
|
||||
if !engram_valid_node_type(node_type) {
|
||||
__println("[engram] REJECTED node write — invalid node_type '" + node_type + "' (label=" + label + ")")
|
||||
return ""
|
||||
}
|
||||
if !engram_valid_tier(tier) {
|
||||
__println("[engram] REJECTED node write — invalid tier '" + tier + "' (node_type=" + node_type + ", label=" + label + ")")
|
||||
return ""
|
||||
}
|
||||
return __engram_node_full(content, node_type, label, salience, importance, confidence, tier, tags)
|
||||
}
|
||||
|
||||
// --- Node retrieval ---
|
||||
|
||||
Reference in New Issue
Block a user