diff --git a/engram/src/server.el b/engram/src/server.el index 76480ea..53e3dc2 100644 --- a/engram/src/server.el +++ b/engram/src/server.el @@ -1469,9 +1469,16 @@ fn route_guide_summon(method: String, path: String, body: String) -> String { // // The SINGLE NODE is the DEGENERATE n=1 case of this SAME operation — not a // separate CRUD path: -// write(content) = reframe(region=∅, manifold=[1 node]) (route_write) +// write(signal) = realize(signal) → reframe(region=∅, manifold) (route_write) // supersede(id,new) = reframe(region={id}, manifold=[1 node]) (route_supersede) // relate(a,b,rel) = the rebind sub-op in isolation (route_create_edge) +// +// CORRECTED 2026-08-16: write was documented above as +// "reframe(region=∅, manifold=[1 node])", and the "[1 node]" was not the design +// — it was the DEFECT. A node is an OUTPUT of realization, never an INPUT to +// it. What arrives at an intake route is a SIGNAL, and how many nodes it +// becomes is for the realizer to say, not for the route to assume. See +// "INTAKE" below. // The ONLY anti-pattern is decomposing a region-scale change into a LOOP of // independent top-level per-node updates. Here the region is the unit: one // isolate, one atomic set-replace, one persist, one verify — iterating members @@ -1686,6 +1693,174 @@ fn reframe_core(region: [String], manifold: String, reason: String, do_rebind: I ",\"keystones_protected\":true}" } +// ═══════════════════════════════════════════════════════════════════════════ +// INTAKE — the ONE door: signal → realization → manifold → store. +// +// THERE IS NO WRITE NODE. What arrives at an intake route is a SIGNAL. A node +// is an OUTPUT of realization, never an INPUT to it. route_write used to say: +// +// let manifold: String = "[" + body + "]" // the body IS a valid manifold node object +// +// and hand that to reframe_core. That is not a manifold — it is the request +// body wearing the word, and the comment stated the wrong assumption out loud. +// It is why a compound signal landed as ONE flat node with ZERO edges. Measured +// before this change, on a cp -Rc clone: +// POST /api/write {"type":"memory","content":"A cathedral is stone holding a +// shape that stone alone would not hold."} +// → {"ok":true,"inserted":1,"nodes_added":1,"edges_added":0,...} +// GET /api/neighbors/ → [] (read back out, not taken on trust) +// +// NOTHING IS DECOMPOSED HERE, AND NOTHING MAY EVER BE. transduce(signal, +// modality) IS the realization primitive (el_runtime.c: "Manifold", +// "Realizers + transduce"). It dispatches through the dlsym realizer registry, +// so ADDING A MODALITY IS REGISTERING A REALIZER — never an edit to this file, +// and never a patch to the runtime. This function only carries what the +// primitive returns into the store, which is the one thing the engram's HTTP +// surface has never done: `grep -n 'transduce\|realize\|Manifold\|decompos' +// engram/src/server.el` returned exactly one line before this change, a comment. +// +// GENERAL BY CONSTRUCTION, NOT SPECIAL-CASED TO route_write. Five of the six +// intake doors (write, supersede, nodes, neuron/knowledge/capture, +// neuron/state-events) are the same hand-written "content string → +// engram_node_full → one flat node", differing ONLY in the node_type / tier / +// tags they hardcode. Those are parameters here, so each door can be moved onto +// this one function as it is transitioned. Only /api/write rides it in this +// pass; the rest are listed as remaining work. +// +// WHEN THERE IS NO ORGAN the signal is stored flat exactly as before, and the +// response SAYS SO ("realized":false, "organ":false). Silent flattening is the +// actual defect — a caller could not distinguish "nothing decomposed me" from +// "I decomposed into one component". el_runtime.c draws the same line at +// registration time, between an absent organ and a broken one, for the same +// reason: those two must not look alike. +// ═══════════════════════════════════════════════════════════════════════════ + +// Resolve a component KEY to the node id it was inserted as. Components are +// addressed BY KEY, never by index (el_runtime.c, "Manifold"), because the key +// is what survives persistence — so relations are resolved by key too. +fn key_to_id(keys: [String], ids: [String], key: String) -> String { + let n: Int = el_list_len(keys) + let i: Int = 0 + while i < n { + if str_eq(el_list_get(keys, i), key) { return el_list_get(ids, i) } + i = i + 1 + } + return "" +} + +fn intake_signal(signal: String, modality: String, region: [String], + nt_in: String, tier_in: String, tags: String, + reason: String, do_rebind: Int) -> String { + let n_before: Int = engram_node_count() + let e_before: Int = engram_edge_count() + let region_n: Int = el_list_len(region) + let tomb: String = if region_n > 0 { supersede_set(region, reason) } else { "" } + + // Identity can never be minted through intake — the same rule + // insert_manifold_json holds, applied at the one door instead of per-route. + let nt: String = if str_eq(nt_in, "") { "Memory" } else { nt_in } + if str_eq(nt, "self") { nt = "Memory" } + if str_eq(nt, "values") { nt = "Memory" } + let tier: String = if str_eq(tier_in, "") { "Working" } else { tier_in } + + let has_organ: Int = realizer_has(modality) + let new_ids: [String] = el_list_empty() + let keys: [String] = el_list_empty() + let ncomp: Int = 0 + let nrel: Int = 0 + let realized: Int = 0 + + if has_organ > 0 { + let m: Manifold = transduce(signal, modality) + // A realizer that returns a bare Geometry transduces NOTHING by design + // (el_runtime.c) — manifold_is() is the check, so a fingerprinting organ + // is not silently mistaken for a decomposing one. + if manifold_is(m) > 0 { + realized = 1 + ncomp = manifold_size(m) + let i: Int = 0 + let prev: String = "" + while i < ncomp { + let key: String = manifold_key(m, i) + let role: String = manifold_role(m, i) + // The component's OWN geometry, at its own width — this is the + // whole point of a manifold over a fingerprint, and it is why + // node_attach_geometry is used rather than re-embedding the + // component's name as text. + let g: Geometry = manifold_geometry(m, i) + let ctags: String = "[\"component\",\"role:" + role + "\",\"modality:" + modality + "\"]" + let cid: String = engram_node_full(key, nt, key, 0.5, 0.5, 0.9, tier, ctags) + let landed: Int = node_attach_geometry(cid, g) + let freed: Int = geometry_free(g) + new_ids = el_list_append(new_ids, cid) + keys = el_list_append(keys, key) + // PRESERVED CONTRACT: manifold_member wires the inserted set + // into one connected sub-graph, exactly as insert_manifold_json + // already did. Not reinvented — reused. + if !str_eq(prev, "") { engram_connect(prev, cid, 0.6, "manifold_member") } + prev = cid + i = i + 1 + } + // THE RELATIONS ARE THE CONTENT. Relation weight IS the grounding + // (correspondence-and-censorship §1) — it arrives on the edge from + // the realizer and nothing here computes or second-guesses it. + nrel = manifold_rel_count(m) + let j: Int = 0 + while j < nrel { + let fk: String = manifold_rel_from(m, j) + let rn: String = manifold_rel_name(m, j) + let tk: String = manifold_rel_to(m, j) + let w: Float = manifold_rel_weight(m, j) + let fid: String = key_to_id(keys, new_ids, fk) + let tid: String = key_to_id(keys, new_ids, tk) + if !str_eq(fid, "") { + if !str_eq(tid, "") { + engram_connect(fid, tid, w, rn) + } + } + j = j + 1 + } + let mfreed: Int = manifold_free(m) + } + } + + // NO ORGAN: store the signal flat, as before — but say so. This is the + // pre-existing behaviour preserved verbatim, not a new fallback path. + if realized == 0 { + let label: String = str_slice(signal, 0, 60) + let fid: String = engram_node_full(signal, nt, label, 0.5, 0.5, 0.9, tier, tags) + new_ids = el_list_append(new_ids, fid) + } + + let inserted: Int = el_list_len(new_ids) + let bound: Int = if do_rebind > 0 { rebind_cosine(new_ids, tomb) } else { 0 } + let saved: Int = persist_canonical() + let new_csv: String = "" + let k: Int = 0 + while k < inserted { + let sep: String = if k == 0 { "" } else { "," } + new_csv = new_csv + sep + "\"" + el_list_get(new_ids, k) + "\"" + k = k + 1 + } + let realized_s: String = if realized > 0 { "true" } else { "false" } + let organ_s: String = if has_organ > 0 { "true" } else { "false" } + return "{\"ok\":true,\"region_superseded\":" + int_to_str(region_n) + + ",\"tombstone_id\":\"" + tomb + "\"" + + ",\"inserted\":" + int_to_str(inserted) + + ",\"new_ids\":[" + new_csv + "]" + + ",\"edges_rebound\":" + int_to_str(bound) + + ",\"realized\":" + realized_s + + ",\"modality\":\"" + modality + "\"" + + ",\"organ\":" + organ_s + + ",\"components\":" + int_to_str(ncomp) + + ",\"relations\":" + int_to_str(nrel) + + ",\"nodes_added\":" + int_to_str(engram_node_count() - n_before) + + ",\"edges_added\":" + int_to_str(engram_edge_count() - e_before) + + ",\"node_count\":" + int_to_str(engram_node_count()) + + ",\"edge_count\":" + int_to_str(engram_edge_count()) + + ",\"keystones_protected\":true}" +} + // POST /api/reframe — the universal set-based mutation. // Body: {vantage?, region_ids?(csv), k?, expand?, manifold(json array), reason?, rebind?} // region_ids (explicit) wins; else cosine-isolate around vantage. @@ -1722,18 +1897,32 @@ fn route_reframe(method: String, path: String, body: String) -> String { return reframe_core(region, manifold, reason, do_rebind) } -// write — DEGENERATE n=1 of reframe: region=∅, manifold=[1 node]. The SAME -// reframe_core path. rebind off so the pure-add matches plain node creation. -// POST /api/write {content, node_type?, tier?, tags?} +// write — INTAKE OF A SIGNAL. Not "reframe with a manifold of one node": the +// route no longer decides how many nodes the signal is. It hands the signal to +// the realization primitive and stores whatever manifold comes back. +// +// The line this replaces was: +// let manifold: String = "[" + body + "]" // the body IS a valid manifold node object +// which asserted that a request body is a manifold. It is not, and that single +// assertion is the whole measured defect (1 node, 0 edges, [] neighbors). +// +// rebind stays off so a pure add still matches plain node creation. +// POST /api/write {content, modality?, node_type?, tier?, tags?} fn route_write(method: String, path: String, body: String) -> String { let content: String = json_get_string(body, "content") if str_eq(content, "") { return err_json("write: content required") } let nt: String = json_get_string(body, "node_type") if str_eq(nt, "self") { return err_json("write: identity is write-protected") } if str_eq(nt, "values") { return err_json("write: identity is write-protected") } + // The modality names which organ to sense with. It is data, never a branch: + // a new modality is a realizer_register call somewhere else in the program, + // not another endpoint and not another case here. + let mod_raw: String = json_get_string(body, "modality") + let modality: String = if str_eq(mod_raw, "") { "text" } else { mod_raw } + let tier: String = json_get_string(body, "tier") + let tags: String = json_get_raw(body, "tags") let empty: [String] = el_list_empty() - let manifold: String = "[" + body + "]" // the body IS a valid manifold node object - return reframe_core(empty, manifold, "write", 0) + return intake_signal(content, modality, empty, nt, tier, tags, "write", 0) } // supersede — DEGENERATE n=1 of reframe: region={id}, manifold=[1 node]. The