Merge pull request 'runtime: restore engram_recall_json + cgi_* accessors (unblocks the soul build)' (#126) from fix/elc-rebuildable-compiler-builtins into dev
El SDK CI - dev / build-and-test (push) Failing after 10m15s

This commit was merged in pull request #126.
This commit is contained in:
2026-08-16 00:57:11 +00:00
2 changed files with 67 additions and 0 deletions
+58
View File
@@ -18271,3 +18271,61 @@ el_val_t el_mem_check(void) {
}
return 0;
}
/* ── engram_recall_json / cgi_* accessors — restored 2026-08-15 ──────────────
*
* These existed in the runtime neuron vendored (v1.0.0-20260501) and were lost
* when this runtime moved on, so a soul built against current el would fail to
* link and, worse, the naive "fix" of pointing recall at engram_search_json
* would have SILENTLY DOWNGRADED the mind's whole retrieval surface from
* semantic to lexical, with no error at any layer.
*
* The lexical/semantic split is a real safety boundary, not redundant naming
* (neuron-api.el:613 documents it): engram_search_json stays LEXICAL because
* ~40 internal call sites pass a KEY and seven of them DELETE every record
* returned making those semantic would delete fuzzy matches. recall is the
* SEMANTIC surface, used by the retrieval routes.
*
* The old implementation was eg_search_json_impl(q, limit, with_legs=1): embed
* the query, cosine over the corpus, then a graph leg from semantic seeds.
* In this runtime that is exactly what engram_activate() already does (it
* embeds via eg_embed_fetch, scores by cosine, then spreads activation), so
* recall delegates to it rather than re-deriving a second semantic path.
* Output shape matches engram_search_json a flat array of node objects via
* engram_emit_node_json because existing callers (memory.el:80,
* neuron-api.el:618) parse it as search's shape, not activate's envelope.
* */
el_val_t engram_recall_json(el_val_t query, el_val_t limit) {
int64_t lim = (int64_t)limit;
if (lim <= 0) lim = 100;
/* depth 1: the associative leg, one hop out from the semantic seeds. */
el_val_t lst = engram_activate(query, (el_val_t)(int64_t)1);
ElList* arr = (ElList*)(uintptr_t)lst;
JsonBuf b; jb_init(&b);
jb_putc(&b, '[');
int64_t emitted = 0;
if (arr) {
for (int64_t i = 0; i < arr->length && emitted < lim; i++) {
if (!arr->elems[i]) continue;
el_val_t node_map = el_map_get(arr->elems[i], EL_STR("node"));
el_val_t id_v = el_map_get(node_map, EL_STR("id"));
const char* id_s = EL_CSTR(id_v);
EngramNode* n = id_s ? engram_find_node(id_s) : NULL;
if (!n) continue;
if (emitted > 0) jb_putc(&b, ',');
engram_emit_node_json(&b, n, 0);
emitted++;
}
}
jb_putc(&b, ']');
return el_wrap_str(b.buf);
}
/* cgi_* — read-only identity accessors over the process-wide CGI registration
* set by cgi_register(). Read-only by design: there is no setter (studio.el:66). */
el_val_t cgi_principal(void) { return EL_STR(_el_cgi_principal ? _el_cgi_principal : ""); }
el_val_t cgi_network(void) { return EL_STR(_el_cgi_network ? _el_cgi_network : ""); }
el_val_t cgi_engram(void) { return EL_STR(_el_cgi_engram ? _el_cgi_engram : ""); }
+9
View File
@@ -1017,6 +1017,15 @@ el_val_t stdout_to_file(el_val_t path);
el_val_t stdout_restore(void);
el_val_t el_mem_check(void);
/* Semantic retrieval surface. NOT interchangeable with engram_search_json,
* which is lexical by design — see the note at the definition. */
el_val_t engram_recall_json(el_val_t query, el_val_t limit);
/* CGI identity accessors (read-only). */
el_val_t cgi_principal(void);
el_val_t cgi_network(void);
el_val_t cgi_engram(void);
#ifdef __cplusplus
}
#endif