Reasoning layer: analogy/induction/abduction/causal/planning over §5 geometry ops
Compose the live relational-neighborhood geometry OPERATORS into five reasoning
modes as pure, read-only C (engram_reason.{h,c}); each is proven with closed-form
constructed tests before it ships, not declared.
- ANALOGY (Procrustes R + residual translation, apply to C, rank candidates)
- INDUCTION (combine-pooled rule geometry + point-to-manifold membership)
- ABDUCTION (best-explaining structure by point-to-manifold fit)
- CAUSAL (centroid-cosine correlation vs directed influence: temporal
precedence + association surviving confounder control via subtract;
emits a correlation-vs-causation flag)
- PLANNING (geo-distance edges + Dijkstra → discrete geodesic path)
A shared point-to-manifold fit primitive underlies induction membership and
abduction ranking. engram/test/run_reason_tests.sh: 33/33 checks on both PERF
and ASan/UBSan passes; macOS leaks 0/0.
ANALOGY is surfaced as an el builtin (engram_reason_analogy_json) via the same
pass-through the §5 operators use — demonstrated callable from compiled El with a
container-capped fold (no self-host fold). The other four are C-layer only: their
set/point/timestamp inputs do not map to the flat-CSV el ABI without touching
codegen (deferred). engram_reason.c must join the server link line beside
engram_geometry.c at cutover. See docs/runbooks/2026-08-13-reasoning-operators-*.
This commit is contained in:
@@ -7446,6 +7446,7 @@ static char* engram_first_n_chars(const char* s, size_t n) {
|
||||
#include "engram_store.h"
|
||||
#include "engram_vindex.h" /* M8: ANN (HNSW) index for activation seed selection */
|
||||
#include "engram_geometry.h" /* M9: centered relational-neighborhood geometry (priming) */
|
||||
#include "engram_reason.h" /* reasoning layer: compositions over the §5 operators */
|
||||
|
||||
/* M10 REIFICATION: resident loaded form of the first-class persisted neighborhood
|
||||
* records (Neighborhood + GeoMeanFrame). Built once at boot from the durable store
|
||||
@@ -12395,6 +12396,32 @@ el_val_t engram_geo_analogy_json(el_val_t a_seeds, el_val_t b_seeds) {
|
||||
return el_wrap_str(b.buf);
|
||||
}
|
||||
|
||||
/* engram_reason_analogy_json(a_csv, b_csv, c_csv) — REASONING: "A:B :: C:?".
|
||||
* Learns the A→B transform (Procrustes rotation + residual translation) and applies
|
||||
* it to C, returning the predicted point + the Procrustes frame-fit residual. This
|
||||
* is the analogy MODE (engram_reason.c) surfaced over the same flat-CSV seed ABI as
|
||||
* the §5 operators. The remaining reasoning modes (induction/abduction/causal/
|
||||
* planning) take candidate-set / point / timestamp inputs that do not map to flat
|
||||
* CSV and are C-layer only for now (see the reasoning-operators runbook). */
|
||||
el_val_t engram_reason_analogy_json(el_val_t a_seeds, el_val_t b_seeds, el_val_t c_seeds) {
|
||||
GeoDescriptor* A = eg_geo_build_desc(EL_CSTR(a_seeds));
|
||||
GeoDescriptor* B = eg_geo_build_desc(EL_CSTR(b_seeds));
|
||||
GeoDescriptor* C = eg_geo_build_desc(EL_CSTR(c_seeds));
|
||||
if (!A || !B || !C) { if (A) engram_geo_free(A); if (B) engram_geo_free(B); if (C) engram_geo_free(C); return eg_geo_err("geometry unavailable"); }
|
||||
GeoAnalogyResult res; char t[80]; JsonBuf b; jb_init(&b);
|
||||
if (engram_reason_analogy(A, B, C, NULL, 0, &res) != 0) {
|
||||
engram_geo_free(A); engram_geo_free(B); engram_geo_free(C);
|
||||
return eg_geo_err("dim/frame mismatch or missing centroid");
|
||||
}
|
||||
jb_putc(&b, '{');
|
||||
snprintf(t, sizeof t, "\"dim\":%d,\"analogy_residual\":%.6g", res.dim, res.analogy_residual); jb_puts(&b, t);
|
||||
jb_puts(&b, ",\"mapped_point\":"); eg_geo_emit_vec(&b, res.mapped_point, res.dim);
|
||||
jb_putc(&b, '}');
|
||||
engram_reason_analogy_free(&res);
|
||||
engram_geo_free(A); engram_geo_free(B); engram_geo_free(C);
|
||||
return el_wrap_str(b.buf);
|
||||
}
|
||||
|
||||
el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction) {
|
||||
/* Re-implement here directly so we serialize without going through
|
||||
* the ElList path. Walks BFS to max_depth, emits {node, edge, hops}
|
||||
|
||||
Reference in New Issue
Block a user