self-review 2026-08-01: fix double-encode score mangling; expose similarity probe; presence-aware defaults
- route_create_node passed already-boxed Floats through el_from_float a second time, reinterpreting boxed bits as raw doubles — every HTTP-created node silently stored default salience/importance/confidence regardless of input (verified live: 0.9/0.25/0.6 in -> 0.5/0.5/1.0 stored). Floats now passed bare, matching the route_emit_ise pattern that always worked. - Presence-aware defaults via json_get_raw: absent key != explicit value; confidence now honored from payload instead of hardcoded 1.0. - GET /api/similarity?a=&b= wires engram_cosine_sim (built 2026-07-24, zero callers until now) into the introspection API. - /health reports live node/edge counts instead of a hardcoded literal.
This commit is contained in:
+55
-8
@@ -111,22 +111,39 @@ fn persist_canonical() -> Int {
|
|||||||
// Observed live: the soul's boot-counter write-back landed with
|
// Observed live: the soul's boot-counter write-back landed with
|
||||||
// label="soul:boot_count:99" (content), importance 0.5, no tags. Honor the
|
// label="soul:boot_count:99" (content), importance 0.5, no tags. Honor the
|
||||||
// full field set via engram_node_full when any of them is supplied.
|
// full field set via engram_node_full when any of them is supplied.
|
||||||
|
// PRESENCE-AWARE DEFAULTS (2026-08-01 self-review): the old pattern
|
||||||
|
// `if x == 0.0 { default }` made a legitimate 0.0 unrepresentable — a caller
|
||||||
|
// setting salience/importance/weight to zero silently got 0.5. json_get_raw
|
||||||
|
// returns "" when the key is ABSENT and the raw token when present, so
|
||||||
|
// absence and zero are now distinguishable. Also: confidence was hardcoded
|
||||||
|
// to 1.0 regardless of input — every HTTP-created node claimed full
|
||||||
|
// epistemic confidence. Now honored from the payload (default 1.0).
|
||||||
fn route_create_node(method: String, path: String, body: String) -> String {
|
fn route_create_node(method: String, path: String, body: String) -> String {
|
||||||
let content: String = json_get_string(body, "content")
|
let content: String = json_get_string(body, "content")
|
||||||
let nt_raw: String = json_get_string(body, "node_type")
|
let nt_raw: String = json_get_string(body, "node_type")
|
||||||
let node_type: String = if str_eq(nt_raw, "") { "Memory" } else { nt_raw }
|
let node_type: String = if str_eq(nt_raw, "") { "Memory" } else { nt_raw }
|
||||||
let sal_raw: Float = json_get_float(body, "salience")
|
let sal_present: String = json_get_raw(body, "salience")
|
||||||
let salience: Float = if sal_raw == 0.0 { 0.5 } else { sal_raw }
|
let salience: Float = if str_eq(sal_present, "") { 0.5 } else { json_get_float(body, "salience") }
|
||||||
let label_raw: String = json_get_string(body, "label")
|
let label_raw: String = json_get_string(body, "label")
|
||||||
let label: String = if str_eq(label_raw, "") { content } else { label_raw }
|
let label: String = if str_eq(label_raw, "") { content } else { label_raw }
|
||||||
let imp_raw: Float = json_get_float(body, "importance")
|
let imp_present: String = json_get_raw(body, "importance")
|
||||||
let importance: Float = if imp_raw == 0.0 { 0.5 } else { imp_raw }
|
let importance: Float = if str_eq(imp_present, "") { 0.5 } else { json_get_float(body, "importance") }
|
||||||
|
let conf_present: String = json_get_raw(body, "confidence")
|
||||||
|
let confidence: Float = if str_eq(conf_present, "") { 1.0 } else { json_get_float(body, "confidence") }
|
||||||
let tier_raw: String = json_get_string(body, "tier")
|
let tier_raw: String = json_get_string(body, "tier")
|
||||||
let tier: String = if str_eq(tier_raw, "") { "Working" } else { tier_raw }
|
let tier: String = if str_eq(tier_raw, "") { "Working" } else { tier_raw }
|
||||||
let tags: String = json_get_string(body, "tags")
|
let tags: String = json_get_string(body, "tags")
|
||||||
|
// NO el_from_float WRAPPER (2026-08-01 self-review): salience/importance/
|
||||||
|
// confidence are already Float (el_val_t) values — json_get_float and
|
||||||
|
// Float literals both encode. Wrapping them in el_from_float AGAIN
|
||||||
|
// reinterpreted the boxed bits as a raw double, producing garbage that
|
||||||
|
// failed engram_decode_score's range check and clamped every HTTP-created
|
||||||
|
// node to defaults (salience 0.9 in → 0.5 stored; confidence 0.6 in → 1.0
|
||||||
|
// stored — verified live). route_emit_ise always passed Floats bare and
|
||||||
|
// its 0.3/0.3/0.8 stored correctly; this call now does the same.
|
||||||
let id: String = engram_node_full(
|
let id: String = engram_node_full(
|
||||||
content, node_type, label,
|
content, node_type, label,
|
||||||
el_from_float(salience), el_from_float(importance), el_from_float(1.0),
|
salience, importance, confidence,
|
||||||
tier, tags
|
tier, tags
|
||||||
)
|
)
|
||||||
let saved: Int = persist_canonical()
|
let saved: Int = persist_canonical()
|
||||||
@@ -194,8 +211,10 @@ fn route_create_edge(method: String, path: String, body: String) -> String {
|
|||||||
let to_id: String = json_get_string(body, "to_id")
|
let to_id: String = json_get_string(body, "to_id")
|
||||||
let rel_raw: String = json_get_string(body, "relation")
|
let rel_raw: String = json_get_string(body, "relation")
|
||||||
let relation: String = if str_eq(rel_raw, "") { "associates" } else { rel_raw }
|
let relation: String = if str_eq(rel_raw, "") { "associates" } else { rel_raw }
|
||||||
let w_raw: Float = json_get_float(body, "weight")
|
// Presence-aware (2026-08-01): weight 0.0 is a legitimate edge weight
|
||||||
let weight: Float = if w_raw == 0.0 { 0.5 } else { w_raw }
|
// (dormant association); only default when the key is absent.
|
||||||
|
let w_present: String = json_get_raw(body, "weight")
|
||||||
|
let weight: Float = if str_eq(w_present, "") { 0.5 } else { json_get_float(body, "weight") }
|
||||||
engram_connect(from_id, to_id, weight, relation)
|
engram_connect(from_id, to_id, weight, relation)
|
||||||
let saved: Int = persist_canonical()
|
let saved: Int = persist_canonical()
|
||||||
"{\"ok\":true,\"from_id\":\"" + from_id + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + relation + "\"}"
|
"{\"ok\":true,\"from_id\":\"" + from_id + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + relation + "\"}"
|
||||||
@@ -242,8 +261,12 @@ fn route_load(method: String, path: String, body: String) -> String {
|
|||||||
ok_json()
|
ok_json()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (2026-08-01 self-review) Health previously returned a hardcoded literal —
|
||||||
|
// it reported "ok" even when the snapshot failed to load and the store was
|
||||||
|
// empty. Now reports live counts so a monitor can distinguish "up and
|
||||||
|
// loaded" from "up and hollow" (node_count=0 after boot = failed load).
|
||||||
fn route_health(method: String, path: String, body: String) -> String {
|
fn route_health(method: String, path: String, body: String) -> String {
|
||||||
"{\"status\":\"ok\",\"engine\":\"engram-runtime-native\"}"
|
"{\"status\":\"ok\",\"engine\":\"engram-runtime-native\",\"node_count\":" + int_to_str(engram_node_count()) + ",\"edge_count\":" + int_to_str(engram_edge_count()) + "}"
|
||||||
}
|
}
|
||||||
|
|
||||||
// route_embed_backfill — GET/POST /api/embed-backfill?n=48
|
// route_embed_backfill — GET/POST /api/embed-backfill?n=48
|
||||||
@@ -410,6 +433,25 @@ fn route_capture_knowledge(method: String, path: String, body: String) -> String
|
|||||||
"{\"ok\":true,\"id\":\"" + id + "\"}"
|
"{\"ok\":true,\"id\":\"" + id + "\"}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// route_similarity — GET /api/similarity?a=<id>&b=<id>
|
||||||
|
//
|
||||||
|
// (2026-08-01 self-review) engram_cosine_sim was added 2026-07-24
|
||||||
|
// (bl-b2d1c944) with the stated purpose of exposing semantic distance to
|
||||||
|
// "EL code and the introspection API" — but it had ZERO callers anywhere:
|
||||||
|
// no route, no soul-daemon use. The activation path uses embeddings
|
||||||
|
// internally (semantic seeding, Pass-2 additive term), but there was no way
|
||||||
|
// to probe pairwise node similarity from outside. This closes that: cosine
|
||||||
|
// in [-1,1], or -2 when either node is missing or not yet embedded (so
|
||||||
|
// "not comparable" is distinguishable from "genuinely orthogonal" 0.0).
|
||||||
|
fn route_similarity(method: String, path: String, body: String) -> String {
|
||||||
|
let a: String = query_param(path, "a")
|
||||||
|
let b: String = query_param(path, "b")
|
||||||
|
if str_eq(a, "") { return err_json("missing a") }
|
||||||
|
if str_eq(b, "") { return err_json("missing b") }
|
||||||
|
let sim: Float = engram_cosine_sim(a, b)
|
||||||
|
"{\"a\":\"" + a + "\",\"b\":\"" + b + "\",\"cosine\":" + float_to_str(sim) + "}"
|
||||||
|
}
|
||||||
|
|
||||||
// ── Auth ──────────────────────────────────────────────────────────────────────
|
// ── Auth ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
fn check_auth_ok(method: String, body: String) -> Bool {
|
fn check_auth_ok(method: String, body: String) -> Bool {
|
||||||
@@ -522,6 +564,11 @@ fn handle_request(method: String, path: String, body: String) -> String {
|
|||||||
return route_embed_backfill(method, path, body)
|
return route_embed_backfill(method, path, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Semantic similarity probe (2026-08-01)
|
||||||
|
if str_eq(method, "GET") && str_starts_with(clean, "/api/similarity") {
|
||||||
|
return route_similarity(method, path, body)
|
||||||
|
}
|
||||||
|
|
||||||
"{\"error\":\"not found\",\"path\":\"" + clean + "\"}"
|
"{\"error\":\"not found\",\"path\":\"" + clean + "\"}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user