Files
el/engram/src/server.el
T
bigmerge d3d550664e
El SDK CI - dev / build-and-test (pull_request) Failing after 14m53s
Unify write/supersede/reframe onto one set-based region operation
Collapses three separate mutation paths (node write, node supersede, and
ad-hoc bulk edits) into a single reframe_core: isolate a region (cosine +
1-hop adjacency), tombstone-supersede it as an immutable set, insert the
replacement manifold, rebind edges by cosine, and persist atomically.
write and supersede become the region-size-0 and region-size-1 degenerate
cases of the same path, eliminating divergent per-route logic. Identity
keystones remain write-protected across all three entry points.
2026-08-15 14:25:41 -05:00

831 lines
40 KiB
EmacsLisp
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// server.el Engram HTTP server.
//
// Engram is the in-process graph store. The runtime owns the data; this
// file is the thin HTTP face. Every route maps to one or two engram_*
// builtins. There is no SQL, no db layer, no SQLite the runtime IS the
// database.
//
// Built and linked with:
// elc src/server.el > server.c
// cc -std=c11 -O2 -lcurl -lpthread -o engram server.c el_runtime.c
// ./engram
//
// Configuration via environment:
// ENGRAM_BIND host:port (default :8742)
// ENGRAM_API_KEY bearer auth (optional)
// ENGRAM_DATA_DIR snapshot location (default ~/.neuron/engram)
// Helpers
fn parse_port(bind: String) -> Int {
// ":8742" 8742; "0.0.0.0:8742" → 8742; bare "8742" → 8742
let colon: Int = str_index_of(bind, ":")
if colon < 0 {
return str_to_int(bind)
}
let after: String = str_slice(bind, colon + 1, str_len(bind))
return str_to_int(after)
}
fn ok_json() -> String {
"{\"ok\":true}"
}
fn err_json(msg: String) -> String {
"{\"error\":\"" + msg + "\"}"
}
fn strip_query(path: String) -> String {
let q: Int = str_index_of(path, "?")
if q < 0 { return path }
str_slice(path, 0, q)
}
fn query_param(path: String, key: String) -> String {
let q: Int = str_index_of(path, "?")
if q < 0 { return "" }
let qs: String = str_slice(path, q + 1, str_len(path))
let needle: String = key + "="
let pos: Int = str_index_of(qs, needle)
if pos < 0 { return "" }
let after: String = str_slice(qs, pos + str_len(needle), str_len(qs))
let amp: Int = str_index_of(after, "&")
if amp < 0 { return after }
str_slice(after, 0, amp)
}
fn query_int(path: String, key: String, default_val: Int) -> Int {
let v: String = query_param(path, key)
if str_eq(v, "") { return default_val }
str_to_int(v)
}
// Extract last path segment after a known prefix: extract_id("/api/nodes/abc-123", "/api/nodes/") "abc-123"
fn extract_id(path: String, prefix: String) -> String {
let clean: String = strip_query(path)
if !str_starts_with(clean, prefix) { return "" }
let after: String = str_slice(clean, str_len(prefix), str_len(clean))
let slash: Int = str_index_of(after, "/")
if slash < 0 { return after }
str_slice(after, 0, slash)
}
// Routes
fn route_stats(method: String, path: String, body: String) -> String {
engram_stats_json()
}
// (2026-07-18 self-review) Scoping sweep: `let` inside an if-block creates an
// inner scope only it does NOT mutate the outer binding (documented with
// evidence in awareness.el, 2026-05-25). Every default/reassignment below used
// that broken pattern, so defaults never applied: nodes were created with
// node_type="" and salience=0.0, /api/search and /api/activate ALWAYS ran with
// q="" regardless of input, edges defaulted to relation=""/weight=0.0, and
// save/load with no "path" hit engram_save(""). Rewritten to the
// `let x = if cond { a } else { b }` expression form (the pattern the newer
// routes route_emit_ise/route_capture_knowledge already use correctly).
// persist_canonical save the canonical snapshot after a durable write.
//
// WHY (2026-07-22 self-review): the 2026-07-21 fix correctly stopped READ
// routes from writing the canonical snapshot.json but nothing was left
// that saved it on WRITE. Every mutation (node create, edge create,
// knowledge capture, forget, merge) lived only in RAM until someone POSTed
// /api/save manually; a process restart silently discarded everything since
// the last manual save. Observed live: two engram restarts during the
// 2026-07-22 review reverted the store to a ~17h-old snapshot, destroying
// same-day writes. Reads must never write the canonical; writes must always
// persist it. ISE telemetry is deliberately excluded (48h-pruned, loss-
// tolerant, ~2/min snapshotting the whole store per heartbeat is waste;
// any durable write that follows persists the pruning too).
fn persist_canonical() -> Int {
let dir_raw: String = env("ENGRAM_DATA_DIR")
let dir: String = if str_eq(dir_raw, "") { "/tmp/engram" } else { dir_raw }
engram_save(dir + "/snapshot.json")
return 1
}
fn route_create_node(method: String, path: String, body: String) -> String {
let content: String = json_get_string(body, "content")
let nt_raw: String = json_get_string(body, "node_type")
let node_type: String = if str_eq(nt_raw, "") { "Memory" } else { nt_raw }
let sal_raw: Float = json_get_float(body, "salience")
let salience: Float = if sal_raw == 0.0 { 0.5 } else { sal_raw }
let id: String = engram_node(content, node_type, salience)
let saved: Int = persist_canonical()
"{\"id\":\"" + id + "\",\"content\":\"" + content + "\",\"node_type\":\"" + node_type + "\"}"
}
fn route_get_node(method: String, path: String, body: String) -> String {
let id: String = extract_id(path, "/api/nodes/")
if str_eq(id, "") { return err_json("missing id") }
return engram_get_node_json(id)
}
fn route_scan_nodes(method: String, path: String, body: String) -> String {
let limit: Int = query_int(path, "limit", 50)
let offset: Int = query_int(path, "offset", 0)
let nt: String = query_param(path, "node_type")
if str_eq(nt, "") {
return engram_scan_nodes_json(limit, offset)
}
return engram_scan_nodes_by_type_json(nt, limit, offset)
}
// route_scan_edges bulk export of all edges as a JSON array. Implemented
// via engram_save fs_read of a SCRATCH export path. (2026-07-21 self-review:
// previously this saved over the canonical snapshot.json on every GET if the
// process ever booted with a partial/empty store, the first read request
// clobbered the good snapshot. Read routes must never write the canonical path.)
fn route_scan_edges(method: String, path: String, body: String) -> String {
let dir_raw: String = env("ENGRAM_DATA_DIR")
let dir: String = if str_eq(dir_raw, "") { "/tmp/engram" } else { dir_raw }
let snap_path: String = dir + "/.scan-export.json"
engram_save(snap_path)
let snap: String = fs_read(snap_path)
if str_eq(snap, "") { return "[]" }
// json_get truncates at the first delimiter (no bracket depth tracking),
// so for the edges ARRAY value we need json_get_raw, which honors
// brackets and returns the full sub-JSON.
let edges: String = json_get_raw(snap, "edges")
if str_eq(edges, "") { return "[]" }
return edges
}
fn route_search(method: String, path: String, body: String) -> String {
let q: String = if str_eq(method, "GET") { query_param(path, "q") } else { json_get_string(body, "query") }
let lim_url: Int = query_int(path, "limit", 0)
let lim_body: Int = json_get_int(body, "limit")
let lim_either: Int = if lim_url > 0 { lim_url } else { lim_body }
let limit: Int = if lim_either > 0 { lim_either } else { 20 }
return engram_search_json(q, limit)
}
fn route_activate(method: String, path: String, body: String) -> String {
let q: String = if str_eq(method, "GET") { query_param(path, "q") } else { json_get_string(body, "query") }
// Guard: engram_activate with an empty query matches zero seeds, which
// zeroes ALL carried working-memory weights (documented in awareness.el
// perceive()). Never let an empty activation through to wipe WM.
if str_eq(q, "") { return err_json("missing query") }
let d_raw: Int = if str_eq(method, "GET") { query_int(path, "depth", 3) } else { json_get_int(body, "depth") }
let depth: Int = if d_raw > 0 { d_raw } else { 3 }
return "{\"results\":" + engram_activate_json(q, depth) + "}"
}
fn route_create_edge(method: String, path: String, body: String) -> String {
let from_id: String = json_get_string(body, "from_id")
let to_id: String = json_get_string(body, "to_id")
let rel_raw: String = json_get_string(body, "relation")
let relation: String = if str_eq(rel_raw, "") { "associates" } else { rel_raw }
let w_raw: Float = json_get_float(body, "weight")
let weight: Float = if w_raw == 0.0 { 0.5 } else { w_raw }
engram_connect(from_id, to_id, weight, relation)
let saved: Int = persist_canonical()
"{\"ok\":true,\"from_id\":\"" + from_id + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + relation + "\"}"
}
fn route_neighbors(method: String, path: String, body: String) -> String {
let id: String = extract_id(path, "/api/neighbors/")
if str_eq(id, "") { return err_json("missing id") }
let depth: Int = query_int(path, "depth", 1)
return engram_neighbors_json(id, depth, "both")
}
fn route_strengthen(method: String, path: String, body: String) -> String {
let id: String = json_get_string(body, "node_id")
if str_eq(id, "") { return err_json("missing node_id") }
engram_strengthen(id)
let saved: Int = persist_canonical()
ok_json()
}
fn route_forget(method: String, path: String, body: String) -> String {
let id: String = extract_id(path, "/api/nodes/")
if str_eq(id, "") { return err_json("missing id") }
engram_forget(id)
let saved: Int = persist_canonical()
ok_json()
}
fn route_save(method: String, path: String, body: String) -> String {
let p_raw: String = json_get_string(body, "path")
let dir_raw: String = env("ENGRAM_DATA_DIR")
let dir: String = if str_eq(dir_raw, "") { "/tmp/engram" } else { dir_raw }
let p: String = if str_eq(p_raw, "") { dir + "/snapshot.json" } else { p_raw }
engram_save(p)
"{\"ok\":true,\"path\":\"" + p + "\"}"
}
fn route_load(method: String, path: String, body: String) -> String {
let p_raw: String = json_get_string(body, "path")
let dir_raw: String = env("ENGRAM_DATA_DIR")
let dir: String = if str_eq(dir_raw, "") { "/tmp/engram" } else { dir_raw }
let p: String = if str_eq(p_raw, "") { dir + "/snapshot.json" } else { p_raw }
engram_load(p)
ok_json()
}
fn route_health(method: String, path: String, body: String) -> String {
"{\"status\":\"ok\",\"engine\":\"engram-runtime-native\"}"
}
// route_sync return a snapshot of non-ISE/non-Working nodes for the soul daemon
// to merge into its in-process graph via engram_load_merge.
//
// The soul calls GET /api/sync every SOUL_REFRESH_MS (default 10 min) to pull
// new Knowledge/Memory/BacklogItem nodes from the authoritative HTTP Engram into
// its in-process working store. Previously this returned 404 "not found", causing
// the soul to write the error JSON to a temp file and attempt an empty merge.
//
// Strategy: save the current snapshot to disk, read it back, return the full
// snapshot JSON. The soul's engram_load_merge handles large files gracefully
// (it skips nodes already present by ID). Auth-exempt: same-host internal call.
// (2026-06-27 self-review: added this route to fix silent 10-min sync failures)
fn route_sync(method: String, path: String, body: String) -> String {
let dir_raw: String = env("ENGRAM_DATA_DIR")
let dir: String = if str_eq(dir_raw, "") { "/tmp/engram" } else { dir_raw }
// 2026-07-21 self-review: export to a scratch path, never the canonical
// snapshot.json read routes must not be able to clobber the good snapshot.
let snap_path: String = dir + "/.sync-export.json"
engram_save(snap_path)
let snap: String = fs_read(snap_path)
if str_eq(snap, "") { return "{\"nodes\":[],\"edges\":[]}" }
return snap
}
// route_load_merge POST /api/load-merge {"path": "..."} merge a snapshot
// file into the live store WITHOUT resetting it (engram_load_merge skips nodes
// already present by id). Added 2026-07-21 self-review to restore the 244 kn-
// identity Knowledge nodes lost from the snapshot lineage between 05-13 and
// 07-13. Requires an explicit path: refuses to run without one so it can never
// be triggered accidentally against a default.
fn route_load_merge(method: String, path: String, body: String) -> String {
let p: String = json_get_string(body, "path")
if str_eq(p, "") { return err_json("path is required") }
if str_eq(fs_read(p), "") { return err_json("file missing or empty") }
let before_n: Int = engram_node_count()
let before_e: Int = engram_edge_count()
engram_load_merge(p)
let added_n: Int = engram_node_count() - before_n
let added_e: Int = engram_edge_count() - before_e
let saved: Int = persist_canonical()
"{\"ok\":true,\"nodes_added\":" + int_to_str(added_n) + ",\"edges_added\":" + int_to_str(added_e) + ",\"node_count\":" + int_to_str(engram_node_count()) + "}"
}
// route_emit_ise write an InternalStateEvent node from the soul daemon.
//
// Endpoint: POST /api/neuron/state-events
// Body: {"content": "<json-string>"}
//
// Auth: exempt (internal endpoint, soul daemon on same host, no _auth needed).
// The soul's ise_post() sends {"content":"..."} without _auth; enforcing auth
// here would silently drop all heartbeat/curiosity ISEs. Unauthenticated POST
// to this endpoint is acceptable: ISE writes are observability-only, append-only,
// and come from a trusted process on localhost.
//
// Salience/importance set to match engram_node_full ISE defaults used by the
// in-process fallback path in awareness.el (salience=0.3, importance=0.3,
// confidence=0.8, tier=Episodic).
// (2026-06-26 self-review: added this route after discovering ise_post was
// silently failing the soul posts here but the endpoint didn't exist.)
//
// Retention (2026-07-16 self-review): an earlier comment here claimed ISEs
// got temporal_decay_rate=1.617 that was never implemented (engram_node_full
// hardcodes 0.0), and per-node decay only dampens activation anyway; it never
// removes nodes. By 2026-07-16 ISEs were 75% of the store (10,175 of 13,522
// nodes, ~4,300/day, unbounded). ISEs are already WM-excluded in
// engram_activate, so the fix is retention, not decay: every insert calls
// engram_prune_telemetry(), a single O(nodes+edges) compaction pass that
// removes ISEs older than ENGRAM_ISE_RETENTION_MS (default 48h), protecting
// "session-start" labels and self_review events as durable history. At
// ~3 ISEs/min this bounds telemetry at ~8.6k nodes instead of growing forever.
fn route_emit_ise(method: String, path: String, body: String) -> String {
let content: String = json_get_string(body, "content")
if str_eq(content, "") { return err_json("missing content") }
let sal: Float = 0.3
let imp: Float = 0.3
let conf: Float = 0.8
let id: String = engram_node_full(
content, "InternalStateEvent", "state-event",
sal, imp, conf,
"Episodic", "[\"internal-state\",\"InternalStateEvent\"]"
)
let ret_raw: String = env("ENGRAM_ISE_RETENTION_MS")
let ret_ms: Int = if str_eq(ret_raw, "") { 172800000 } else { str_to_int(ret_raw) }
let pruned: Int = engram_prune_telemetry(ret_ms)
"{\"ok\":true,\"id\":\"" + id + "\",\"pruned\":" + int_to_str(pruned) + "}"
}
// Knowledge capture
//
// route_capture_knowledge direct Knowledge-node capture over HTTP.
//
// Endpoint: POST /api/neuron/knowledge/capture (auth required: "_auth" in body)
// Body: {"content": "...", "title": "...", "category": "...",
// "tier": "note|lesson|canonical", "tags": [...], "project": "...",
// "_auth": "<key>"}
//
// WHY (2026-07-15 self-review): the world-ingestor integrator was designed
// against this endpoint (its MCP-unavailable fallback), but the route never
// existed every direct push 404'd, and because the auth gate ran before
// routing, the failure surfaced as {"error":"unauthorized"} and was
// misdiagnosed for two weeks while world knowledge silently dropped.
// POST /api/nodes was no substitute: it discards label/tags/tier, which
// makes captured knowledge invisible to tag-scoped search and curiosity.
//
// The incoming knowledge tier (note/lesson/canonical) is preserved as a
// "tier:<x>" tag rather than mapped onto Engram's cognitive tiers Knowledge
// nodes land in Semantic (stable reference), and the epistemic tier stays
// queryable without inventing a lossy mapping.
fn route_capture_knowledge(method: String, path: String, body: String) -> String {
let content: String = json_get_string(body, "content")
if str_eq(content, "") { return err_json("missing content") }
let title: String = json_get_string(body, "title")
let label: String = if str_eq(title, "") { str_slice(content, 0, 60) } else { title }
let category_raw: String = json_get_string(body, "category")
let category: String = if str_eq(category_raw, "") { "other" } else { category_raw }
let ktier_raw: String = json_get_string(body, "tier")
let ktier: String = if str_eq(ktier_raw, "") { "note" } else { ktier_raw }
let project: String = json_get_string(body, "project")
let tags_raw: String = json_get_raw(body, "tags")
let tags_base: String = if str_eq(tags_raw, "") { "[]" } else { tags_raw }
// Merge category/tier/project markers into the tag array. Search matches
// against the tags string, so these make captures findable by facet.
let base_len: Int = str_len(tags_base)
let head: String = str_slice(tags_base, 0, base_len - 1)
let sep: String = if str_eq(head, "[") { "" } else { "," }
let safe_cat: String = str_replace(category, "\"", "'")
let safe_tier: String = str_replace(ktier, "\"", "'")
let safe_proj: String = str_replace(project, "\"", "'")
let proj_tag: String = if str_eq(safe_proj, "") { "" } else { ",\"project:" + safe_proj + "\"" }
let tags: String = head + sep + "\"category:" + safe_cat + "\",\"tier:" + safe_tier + "\"" + proj_tag + "]"
let sal: Float = 0.5
let imp: Float = 0.5
let conf: Float = 0.9
let id: String = engram_node_full(
content, "Knowledge", label,
sal, imp, conf,
"Semantic", tags
)
let saved: Int = persist_canonical()
"{\"ok\":true,\"id\":\"" + id + "\"}"
}
//
// THE UNIVERSAL ENGRAM OPERATION reframe_region (native, set-based).
//
// There is ONE operation on the engram: isolate a discrete sub-manifold (a
// REGION) and operate on it AS A WHOLE a set operation:
// isolate (cosine retrieval + adjacency the SET of nodes)
// supersede the stale region as a set (immutable tombstone; originals kept)
// insert the new manifold as a set (dedup/load-merge path)
// rebind edges by cosine
// verify + one atomic persist.
// new = (region superseded) new_manifold.
//
// 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)
// supersede(id,new) = reframe(region={id}, manifold=[1 node]) (route_supersede)
// relate(a,b,rel) = the rebind sub-op in isolation (route_create_edge)
// 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
// INSIDE the one operation is set construction, not the sin.
//
// Spec: knowledge e7a03a94 / f999c5ff. Keystones kn-efeb4a5b / kn-5b606390 are
// write-protected never superseded, never inserted-as identity.
//
fn is_keystone(id: String) -> Bool {
if str_eq(id, "kn-efeb4a5b-5aff-4759-8a97-7233099be6ee") { return true }
if str_eq(id, "kn-5b606390-a52d-4ca2-8e0e-eba141d13440") { return true }
return false
}
// membership test in a [String] set
fn set_has(ids: [String], id: String) -> Bool {
let n: Int = el_list_len(ids)
let i: Int = 0
while i < n {
if str_eq(el_list_get(ids, i), id) { return true }
i = i + 1
}
return false
}
// ISOLATE
// Select the region as a SET: cosine/token retrieval around the vantage
// (aperture k), optionally unioned with the 1-hop adjacency of each hit.
// Keystones are excluded from the mutable region by construction.
fn isolate_region(vantage: String, k: Int, expand: Int) -> [String] {
let ids: [String] = el_list_empty()
if str_eq(vantage, "") { return ids }
// (a) cosine/token retrieval a clean node array [{"id":..},..]
let arr: String = engram_search_json(vantage, k)
let n: Int = json_array_len(arr)
let i: Int = 0
while i < n {
let hit: String = json_array_get(arr, i)
let id: String = json_get_string(hit, "id")
if !str_eq(id, "") {
if !is_keystone(id) {
if !set_has(ids, id) { ids = el_list_append(ids, id) }
}
}
i = i + 1
}
// (b) adjacency: union the 1-hop neighbourhood of each retrieved node.
// Iterate only over the original cosine seeds [0, seeds); neighbours append
// past that bound, so this is one hop, not a transitive sweep.
if expand > 0 {
let seeds: Int = el_list_len(ids)
let s: Int = 0
while s < seeds {
let seed: String = el_list_get(ids, s)
let nb: String = engram_neighbors_json(seed, 1, "both")
let m: Int = json_array_len(nb)
let j: Int = 0
while j < m {
let elem: String = json_array_get(nb, j)
let nodeobj: String = json_get_raw(elem, "node")
let nid: String = json_get_string(nodeobj, "id")
if !str_eq(nid, "") {
if !is_keystone(nid) {
if !set_has(ids, nid) { ids = el_list_append(ids, nid) }
}
}
j = j + 1
}
s = s + 1
}
}
return ids
}
// SUPERSEDE (set)
// Retire the region AS A WHOLE: one region-tombstone marker carries the
// provenance (reason + the full superseded id set); every region node is bound
// to it with a "superseded_by" edge. Originals are RETAINED immutable
// tombstone, never a hard delete (engram_forget is deliberately NOT used).
// Returns the tombstone marker id ("" if the region is empty).
fn supersede_set(region: [String], reason: String) -> String {
let n: Int = el_list_len(region)
if n == 0 { return "" }
let csv: String = ""
let i0: Int = 0
while i0 < n {
let sep: String = if i0 == 0 { "" } else { "," }
csv = csv + sep + el_list_get(region, i0)
i0 = i0 + 1
}
let content: String = "region-tombstone: " + reason + " | superseded " + int_to_str(n) + " nodes: " + csv
let tomb: String = engram_node_full(content, "Tombstone", "region-tombstone", 0.1, 0.1, 1.0, "Episodic", "[\"tombstone\",\"region-supersede\"]")
let i: Int = 0
while i < n {
let rid: String = el_list_get(region, i)
engram_connect(rid, tomb, 1.0, "superseded_by")
i = i + 1
}
return tomb
}
// INSERT (manifold)
// Insert the new manifold as a SET. Inline JSON array of node objects
// {content, node_type?, tier?, tags?}. Each becomes a real embedded node
// (engram_node_full is the n=1 insert atom); the manifold is the set built from
// those atoms, wired with internal "manifold_member" edges so it enters as one
// connected sub-graph. Identity node_types (self/values) are demoted to Memory
// identity can never be minted through reframe. Returns the new node ids.
fn insert_manifold_json(manifold: String) -> [String] {
let out: [String] = el_list_empty()
if str_eq(manifold, "") { return out }
let n: Int = json_array_len(manifold)
if n <= 0 { return out }
let i: Int = 0
let prev: String = ""
while i < n {
let obj: String = json_array_get(manifold, i)
let content: String = json_get_string(obj, "content")
if !str_eq(content, "") {
let nt_raw: String = json_get_string(obj, "node_type")
let nt: String = if str_eq(nt_raw, "") { "Memory" } else { nt_raw }
if str_eq(nt, "self") { nt = "Memory" }
if str_eq(nt, "values") { nt = "Memory" }
let tier_raw: String = json_get_string(obj, "tier")
let tier: String = if str_eq(tier_raw, "") { "Working" } else { tier_raw }
let tags_raw: String = json_get_raw(obj, "tags")
let tags: String = if str_eq(tags_raw, "") { "" } else { tags_raw }
let label: String = str_slice(content, 0, 60)
let id: String = engram_node_full(content, nt, label, 0.5, 0.5, 0.9, tier, tags)
out = el_list_append(out, id)
if !str_eq(prev, "") { engram_connect(prev, id, 0.6, "manifold_member") }
prev = id
}
i = i + 1
}
return out
}
// REBIND (edges by cosine)
// Re-embed the new manifold into the surrounding geometry: bind each new node
// to the tombstone marker (provenance: new region -reframes-> retired region),
// then to its top cosine/token neighbours in the store (skipping itself, the
// new set, keystones, tombstones). Returns the number of edges bound.
fn rebind_cosine(new_ids: [String], tomb: String) -> Int {
let bound: Int = 0
let n: Int = el_list_len(new_ids)
let i: Int = 0
while i < n {
let nid: String = el_list_get(new_ids, i)
if !str_eq(tomb, "") {
engram_connect(nid, tomb, 0.8, "reframes")
bound = bound + 1
}
let node_json: String = engram_get_node_json(nid)
let content: String = json_get_string(node_json, "content")
let arr: String = engram_search_json(content, 5)
let m: Int = json_array_len(arr)
let j: Int = 0
while j < m {
let hit: String = json_array_get(arr, j)
let hid: String = json_get_string(hit, "id")
if !str_eq(hid, "") {
if !str_eq(hid, nid) {
if !is_keystone(hid) {
if !set_has(new_ids, hid) {
let htype: String = json_get_string(hit, "node_type")
if !str_eq(htype, "Tombstone") {
engram_connect(nid, hid, 0.5, "related")
bound = bound + 1
}
}
}
}
}
j = j + 1
}
i = i + 1
}
return bound
}
// THE OPERATION
// isolate (done by caller) supersede region insert manifold rebind
// one atomic persist verify report. This is the whole operation; every
// mutation route below is a projection of it.
fn reframe_core(region: [String], manifold: 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 { "" }
let new_ids: [String] = insert_manifold_json(manifold)
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
}
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) +
",\"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.
fn route_reframe(method: String, path: String, body: String) -> String {
let region_csv: String = json_get_string(body, "region_ids")
let vantage: String = json_get_string(body, "vantage")
let region: [String] = el_list_empty()
if !str_eq(region_csv, "") {
let parts: [String] = str_split(region_csv, ",")
let pn: Int = el_list_len(parts)
let i: Int = 0
while i < pn {
let id: String = str_trim(el_list_get(parts, i))
if !str_eq(id, "") {
if is_keystone(id) { return err_json("reframe: identity keystone write-protected") }
if !set_has(region, id) { region = el_list_append(region, id) }
}
i = i + 1
}
} else {
if !str_eq(vantage, "") {
let kv: Int = json_get_int(body, "k")
let kk: Int = if kv > 0 { kv } else { 12 }
let expand: Int = json_get_int(body, "expand")
region = isolate_region(vantage, kk, expand)
}
}
let manifold: String = json_get_raw(body, "manifold")
let reason_raw: String = json_get_string(body, "reason")
let reason: String = if str_eq(reason_raw, "") { "reframe" } else { reason_raw }
// rebind defaults ON for reframe (absent 1); explicit 0 disables.
let rebind_raw: String = json_get_raw(body, "rebind")
let do_rebind: Int = if str_eq(rebind_raw, "") { 1 } else { json_get_int(body, "rebind") }
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?}
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") }
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)
}
// supersede DEGENERATE n=1 of reframe: region={id}, manifold=[1 node]. The
// SAME reframe_core path with a size-1 region. Original retained (immutable);
// new node inserted and cosine-rebound; provenance edge new-reframes-tomb.
// POST /api/supersede {id, content, node_type?, tier?, tags?, reason?}
fn route_supersede(method: String, path: String, body: String) -> String {
let id: String = json_get_string(body, "id")
if str_eq(id, "") { return err_json("supersede: id required") }
if is_keystone(id) { return err_json("supersede: identity keystone write-protected") }
let content: String = json_get_string(body, "content")
if str_eq(content, "") { return err_json("supersede: content required") }
let region: [String] = el_list_empty()
region = el_list_append(region, id)
let manifold: String = "[" + body + "]"
let reason_raw: String = json_get_string(body, "reason")
let reason: String = if str_eq(reason_raw, "") { "supersede " + id } else { reason_raw }
return reframe_core(region, manifold, reason, 1)
}
// Auth
fn check_auth_ok(method: String, body: String) -> Bool {
let key: String = env("ENGRAM_API_KEY")
if str_eq(key, "") { return true }
// Read-only methods don't require auth. Until http_serve surfaces
// request headers we can't accept a Bearer token cleanly; mutating
// requests must include "_auth": "<key>" in the JSON body.
if str_eq(method, "GET") { return true }
let provided: String = json_get_string(body, "_auth")
if str_eq(provided, key) { return true }
return false
}
// Dispatcher
fn handle_request(method: String, path: String, body: String) -> String {
let clean: String = strip_query(path)
// Health is always reachable
if str_eq(method, "GET") {
if str_eq(clean, "/health") || str_eq(clean, "/") {
return route_health(method, path, body)
}
}
// ISE posting is auth-exempt (internal soul daemon, same host, no _auth key)
if str_eq(method, "POST") && str_eq(clean, "/api/neuron/state-events") {
return route_emit_ise(method, path, body)
}
// Auth (when ENGRAM_API_KEY is set)
if !check_auth_ok(method, body) {
return err_json("unauthorized")
}
// Knowledge capture (auth enforced above; the world-ingestor integrator
// and any headless session without MCP push knowledge through this)
if str_eq(method, "POST") && str_eq(clean, "/api/neuron/knowledge/capture") {
return route_capture_knowledge(method, path, body)
}
// Stats
if str_eq(method, "GET") && (str_eq(clean, "/api/stats") || str_eq(clean, "/stats")) {
return route_stats(method, path, body)
}
// The universal set-based operation and its n=1 degenerate projections
// reframe = isolate supersede-region insert-manifold rebind. write and
// supersede are the SAME reframe_core path at region size 0 and 1.
if str_eq(method, "POST") && (str_eq(clean, "/api/reframe") || str_eq(clean, "/reframe")) {
return route_reframe(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/write") || str_eq(clean, "/write")) {
return route_write(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/supersede") || str_eq(clean, "/supersede")) {
return route_supersede(method, path, body)
}
// Nodes
if str_eq(method, "POST") && (str_eq(clean, "/api/nodes") || str_eq(clean, "/nodes")) {
return route_create_node(method, path, body)
}
if str_eq(method, "GET") && (str_eq(clean, "/api/nodes") || str_eq(clean, "/nodes") || str_eq(clean, "/nodes/list") || str_eq(clean, "/api/nodes/list")) {
return route_scan_nodes(method, path, body)
}
if str_eq(method, "GET") && (str_eq(clean, "/api/edges") || str_eq(clean, "/edges")) {
return route_scan_edges(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/nodes/") {
return route_get_node(method, path, body)
}
if str_eq(method, "DELETE") && str_starts_with(clean, "/api/nodes/") {
return route_forget(method, path, body)
}
// Edges
if str_eq(method, "POST") && (str_eq(clean, "/api/edges") || str_eq(clean, "/edges")) {
return route_create_edge(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/neighbors/") {
return route_neighbors(method, path, body)
}
// Activation + Search
if str_eq(method, "POST") && (str_eq(clean, "/api/activate") || str_eq(clean, "/activate")) {
return route_activate(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/activate") {
return route_activate(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/search") || str_eq(clean, "/search")) {
return route_search(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/search") {
return route_search(method, path, body)
}
// Strengthen
if str_eq(method, "POST") && (str_eq(clean, "/api/strengthen") || str_eq(clean, "/strengthen")) {
return route_strengthen(method, path, body)
}
// Persistence
if str_eq(method, "POST") && (str_eq(clean, "/api/save") || str_eq(clean, "/save")) {
return route_save(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/load") || str_eq(clean, "/load")) {
return route_load(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/load-merge") || str_eq(clean, "/load-merge")) {
return route_load_merge(method, path, body)
}
// Sync soul daemon periodic pull of non-ISE knowledge into in-process graph
if str_eq(method, "GET") && str_eq(clean, "/api/sync") {
return route_sync(method, path, body)
}
"{\"error\":\"not found\",\"path\":\"" + clean + "\"}"
}
// Entry
let bind_raw: String = env("ENGRAM_BIND")
let bind_str: String = if str_eq(bind_raw, "") { ":8742" } else { bind_raw }
let port: Int = parse_port(bind_str)
// On startup, try to load any existing snapshot (best effort).
let data_dir_raw: String = env("ENGRAM_DATA_DIR")
let data_dir: String = if str_eq(data_dir_raw, "") { "/tmp/engram" } else { data_dir_raw }
let snapshot_path: String = data_dir + "/snapshot.json"
engram_load(snapshot_path)
// 2026-07-21 self-review boot guard: if the snapshot file has content but the
// load produced 0 nodes, something is wrong (corrupt file / parse failure).
// Preserve the evidence and warn loudly and since read routes no longer write
// the canonical path, a bad boot can no longer clobber the good snapshot.
let boot_snap: String = fs_read(snapshot_path)
if !str_eq(boot_snap, "") {
if engram_node_count() == 0 {
println("[engram] WARNING: snapshot.json is non-empty but load produced 0 nodes — preserving copy at snapshot.failed-load.json")
fs_write(data_dir + "/snapshot.failed-load.json", boot_snap)
} else {
// Good load: keep a boot-time backup of the snapshot as loaded.
fs_write(data_dir + "/snapshot.boot-backup.json", boot_snap)
}
}
println("[engram] runtime-native graph engine")
println("[engram] data_dir=" + data_dir)
println("[engram] node_count=" + int_to_str(engram_node_count()))
println("[engram] edge_count=" + int_to_str(engram_edge_count()))
println("[engram] listening on " + int_to_str(port))
http_set_handler("handle_request")
http_serve(port, "handle_request")