Files
el/engram/src/server.el
T
bigmerge 15f90003c0 teacher-summon: default-off (TEACHER_ENABLE) soul-native wake; byte-inert when unset
+282 lines in engram/src/server.el implementing the flag-gated teacher summon
(consult_teacher backend abstraction, tier autoselect, GGUF fetch/cache). With
TEACHER_ENABLE unset the summon path is byte-inert. Consolidates the proven
api-reshape pieces (geometry-ops d4f401d, boundary auto-emit 0182642) for the
validated cutover.
2026-08-14 21:52:56 -05:00

1523 lines
78 KiB
EmacsLisp

// 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()
}
// route_act_stats GET /api/act-stats
// (2026-08-04 self-review) engram_act_stats_json() has existed since the
// 2026-07-27 review but was reachable ONLY through the soul daemon's heartbeat
// binding. Every activation-layer gauge WM evictions, breakthroughs, embedder
// breaker state, context drift, and now the Hebbian counters was therefore
// invisible unless the soul happened to be running and its ISEs were read back
// out of the store. Diagnosing the activation layer required a working soul,
// which is exactly backwards: the lower layer should be observable on its own.
// This review needed it to verify link formation and could not get at it. One
// line of plumbing, and the whole activation layer becomes directly diagnosable.
fn route_act_stats(method: String, path: String, body: String) -> String {
engram_act_stats_json()
}
// route_text_health GET /api/text-health
// (2026-08-08 self-review) The daily census half of the text-integrity gauge.
// Today's review found that the JSON parser had been replacing every \uXXXX
// escape with a literal '?' for at least two months: 3,119 of 4,081
// non-telemetry nodes (76%) were damaged, including the self traversal root
// and every values node, and NOTHING detected it because every gauge in the
// system measured whether the machinery was running, and none measured whether
// the text it carried was intact. No snapshot on disk predates the damage, so
// it cannot be undone; it can only be made impossible to repeat quietly.
//
// The parser is fixed. This route is the standing check: `damaged` should now
// hold flat at its historical floor and never climb. `write_damaged` (also on
// the heartbeat as txt_damaged) is the live regression signal non-zero means
// a write path is mangling text right now.
fn route_text_health(method: String, path: String, body: String) -> String {
engram_text_health_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).
// store_on ENGRAM_STORE flag (tiered paged store as the durable owner). Matches
// engram_store_enabled() in el_runtime.c EXACTLY (1 / on / true). Default off
// every persistence path below is byte-for-byte the historical snapshot behavior.
fn store_on() -> Bool {
let v: String = env("ENGRAM_STORE")
if str_eq(v, "1") { return true }
if str_eq(v, "on") { return true }
if str_eq(v, "true") { return true }
return false
}
// 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 {
// ENGRAM_STORE: the paged store is the durable owner a checkpoint flushes
// dirty pages behind a WAL-durable record (durable the moment the WAL fsyncs).
// This is the fix for the "restart reverted to a 17h-old snapshot" data loss:
// durable writes no longer depend on a full snapshot.json rewrite. Returns 1
// on a successful checkpoint, 0 otherwise. Flag-off: unchanged (writes JSON).
if store_on() {
return engram_store_checkpoint()
}
let dir_raw: String = env("ENGRAM_DATA_DIR")
let dir: String = engram_resolve_data_dir()
// (2026-08-10 self-review) This returned a hardcoded 1, which made every
// caller's `let saved: Int = persist_canonical()` a dead variable six
// durable write paths each believed they had confirmation of a successful
// canonical persist and none of them had any. Propagate the real result.
return engram_save(dir + "/snapshot.json")
}
// WAL persistence (design doc §§3-14; gated behind ENGRAM_WAL=on) ──────────
// Default OFF every persist path below is byte-identical to the historical
// per-write full-snapshot behavior. When ON, structural mutations append O(1)
// WAL records instead of rewriting the whole graph, with threshold compaction.
fn wal_on() -> Bool {
str_eq(env("ENGRAM_WAL"), "on")
}
// autoconnect_on ENGRAM_AUTOCONNECT. Will's rule: "we shouldn't be inserting
// orphaned nodes." When ON, every content-node insert forms >=1 semantic-similar
// edge (kNN over embeddings) so no content node enters the graph edgeless.
// Default OFF -> byte-identical to prior behavior (node created, no auto edges).
fn autoconnect_on() -> Bool {
let v: String = env("ENGRAM_AUTOCONNECT")
if str_eq(v, "1") { return true }
if str_eq(v, "on") { return true }
if str_eq(v, "true") { return true }
return false
}
// ise_offgraph_on ENGRAM_ISE_OFFGRAPH. The census showed ~8k of the ~8.9k
// orphans are InternalStateEvent telemetry (heartbeat/curiosity_scan/session-
// start), 100% edgeless by design. When ON, that telemetry is routed to a
// separate state-event log tier instead of the node graph. Default OFF -> ISEs
// remain graph nodes exactly as before (with 48h prune).
fn ise_offgraph_on() -> Bool {
let v: String = env("ENGRAM_ISE_OFFGRAPH")
if str_eq(v, "1") { return true }
if str_eq(v, "on") { return true }
if str_eq(v, "true") { return true }
return false
}
// Persist a single-node mutation (create / content-evolve / strengthen).
fn persist_node(id: String) -> Int {
if wal_on() {
let d: String = engram_resolve_data_dir()
let a: Int = engram_wal_node_put(d, id)
let c: Int = engram_wal_maybe_compact(d)
return a
}
return persist_canonical()
}
// Persist edges appended at index >= start (covers single-edge and batch).
fn persist_edges_since(start: Int) -> Int {
if wal_on() {
let d: String = engram_resolve_data_dir()
let a: Int = engram_wal_edges_since(d, start)
let c: Int = engram_wal_maybe_compact(d)
return a
}
return persist_canonical()
}
// Persist a Hebbian consolidation batch as ONE WAL record (single fsync, §5-B).
fn persist_hebb_batch(start: Int) -> Int {
if wal_on() {
let d: String = engram_resolve_data_dir()
let a: Int = engram_wal_hebb_batch(d, start)
let c: Int = engram_wal_maybe_compact(d)
return a
}
return persist_canonical()
}
// Bulk mutation (embedding backfill, load-merge): write a fresh compaction base
// so the many-node change is durable in one atomic snapshot; WAL is truncated.
fn persist_bulk() -> Int {
if wal_on() {
let d: String = engram_resolve_data_dir()
return engram_wal_compact(d)
}
return persist_canonical()
}
// INCOMPLETE-ROUTE FIX (2026-07-24 self-review): this route silently dropped
// label, importance, tier, and tags engram_node() defaults label to content
// and importance to 0.5, so every node created over HTTP lost its metadata.
// Observed live: the soul's boot-counter write-back landed with
// 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.
// 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 {
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_present: String = json_get_raw(body, "salience")
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: String = if str_eq(label_raw, "") { content } else { label_raw }
let imp_present: String = json_get_raw(body, "importance")
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: String = if str_eq(tier_raw, "") { "Working" } else { tier_raw }
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(
content, node_type, label,
salience, importance, confidence,
tier, tags
)
let saved: Int = persist_node(id)
// ORPHAN PREVENTION (ENGRAM_AUTOCONNECT): connect the fresh node to its
// nearest embedded neighbors so it never enters the graph edgeless.
let connected: Int = if autoconnect_on() {
let ec0: Int = engram_edge_count()
let ac: String = engram_autoconnect_node(id, 3, 25)
let added: Int = engram_edge_count() - ec0
if added > 0 { let sv2: Int = persist_edges_since(ec0) }
added
} else { 0 }
"{\"id\":\"" + id + "\",\"content\":\"" + content + "\",\"node_type\":\"" + node_type + "\",\"connected\":" + int_to_str(connected) + "}"
}
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)
}
// route_get_node_singular GET /api/node/<id>. Singular alias for node-by-id
// fetch. The plural /api/nodes/<id> already resolves; the viz's "see full node
// value on click" and other clients call the SINGULAR form, which had no route
// and 404'd for every id. Same handler, singular prefix. Read-only.
fn route_get_node_singular(method: String, path: String, body: String) -> String {
let id: String = extract_id(path, "/api/node/")
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 = engram_resolve_data_dir()
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_retrieve_geometric_json(q, limit)
}
fn route_search_lexical(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 }
// Presence-aware (2026-08-01): weight 0.0 is a legitimate edge weight
// (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") }
let ec0: Int = engram_edge_count()
engram_connect(from_id, to_id, weight, relation)
let saved: Int = persist_edges_since(ec0)
"{\"ok\":true,\"from_id\":\"" + from_id + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + relation + "\"}"
}
// route_create_edges_batch — POST /api/edges/batch {"edges":[{from_id,to_id,relation,weight}, ...]}
//
// WHY THIS EXISTS (2026-08-07 self-review). persist_canonical() writes the
// FULL canonical snapshot — 60MB at current graph size — and route_create_edge
// calls it once per edge. That is correct for the interactive one-edge case and
// ruinous for any bulk write: the soul's Hebbian consolidation path delivers
// ~14 associations per 8-minute heartbeat, which through the single-edge route
// would be ~840MB of disk writes per beat, ~150GB/day, to persist 14 edges.
//
// The fix is not to weaken durability — it is to make the unit of durability
// the BATCH. Connect every edge, then snapshot exactly once. Same guarantee
// (nothing acknowledged is lost to a restart), 1/N the writes. Empty or
// malformed entries are skipped rather than aborting the batch: a consolidation
// payload is best-effort by design, and one bad id should not cost the other 13.
//
// Returns the accepted count so the caller can tell delivery from silence.
fn route_create_edges_batch(method: String, path: String, body: String) -> String {
let arr: String = json_get_raw(body, "edges")
if str_eq(arr, "") { return err_json("missing edges array") }
let n: Int = json_array_len(arr)
if n == 0 { return "{\"ok\":true,\"accepted\":0,\"skipped\":0}" }
let ec0: Int = engram_edge_count()
let i: Int = 0
let accepted: Int = 0
let skipped: Int = 0
while i < n {
let item: String = json_array_get(arr, i)
let from_id: String = json_get_string(item, "from_id")
let to_id: String = json_get_string(item, "to_id")
if str_eq(from_id, "") || str_eq(to_id, "") {
let skipped = skipped + 1
} else {
let rel_raw: String = json_get_string(item, "relation")
let relation: String = if str_eq(rel_raw, "") { "associates" } else { rel_raw }
let w_present: String = json_get_raw(item, "weight")
let weight: Float = if str_eq(w_present, "") { 0.5 } else { json_get_float(item, "weight") }
engram_connect(from_id, to_id, weight, relation)
let accepted = accepted + 1
}
let i = i + 1
}
// ONE snapshot for the whole batch — the entire point of this route.
// Skip it when nothing was accepted: an all-malformed payload must not
// trigger a 60MB write.
if accepted > 0 {
let saved: Int = persist_hebb_batch(ec0)
}
return "{\"ok\":true,\"accepted\":" + int_to_str(accepted) + ",\"skipped\":" + int_to_str(skipped) + "}"
}
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_node(id)
ok_json()
}
// route_forget — DELETE /api/nodes/:id — INTEGRITY HARDENED (design doc §18.1).
//
// Two invariants now enforced AT THE STORE (not one layer up in neuron-api.el,
// which a direct HTTP client could bypass):
// 1. Write-protection: protected identity/value nodes (derived from the self
// graph — self root + values hub + their neighbors, §18.3) cannot be
// deleted over HTTP. Returns 403, node untouched.
// 2. No hard delete over the wire, ever: an ordinary delete creates a
// Tombstone marker node + `tombstones` edge and KEEPS the original node
// and its edges (recoverable), instead of the old destructive
// engram_forget() shift-delete. Raw engram_forget is now internal-GC only
// and no longer reachable from any HTTP route.
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") }
if engram_is_protected(id) == 1 {
return "{\"__status__\":403,\"error\":\"protected node; deletion refused\",\"id\":\"" + id + "\"}"
}
let tomb_id: String = engram_node_full(
"tombstone:" + id, "Tombstone", "tombstone:" + id,
0.1, 0.1, 1.0, "Episodic", "[\"tombstone\"]"
)
let ec0: Int = engram_edge_count()
engram_connect(tomb_id, id, 1.0, "tombstones")
let saved: Int = if wal_on() {
let d: String = engram_resolve_data_dir()
let a: Int = engram_wal_node_put(d, tomb_id)
let b: Int = engram_wal_edges_since(d, ec0)
let c: Int = engram_wal_maybe_compact(d)
a
} else {
persist_canonical()
}
"{\"ok\":true,\"tombstoned\":\"" + id + "\",\"tombstone_id\":\"" + tomb_id + "\"}"
}
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 = engram_resolve_data_dir()
let p: String = if str_eq(p_raw, "") { dir + "/snapshot.json" } else { p_raw }
// (2026-08-10 self-review) engram_save returns 0 on an empty path and the
// route discarded it, so the response was a literal "ok":true regardless
// of whether anything was written. Report the actual result AND the counts
// that were supposed to have been written the same move that made
// route_health honest on 2026-08-01. A caller can now tell "saved 13k
// nodes" from "saved nothing and said ok".
let sv: Int = engram_save(p)
let sv_ok: String = if sv == 0 { "false" } else { "true" }
"{\"ok\":" + sv_ok + ",\"path\":\"" + p + "\",\"node_count\":" + int_to_str(engram_node_count()) + ",\"edge_count\":" + int_to_str(engram_edge_count()) + "}"
}
// route_checkpoint force a full resident-graph checkpoint into the paged
// store (2026-08-13). Neither /api/save nor /api/load makes edges durable in
// the tiered paged store only persist_canonical -> engram_store_checkpoint
// does, and that only fires on mutating write routes. This route exposes the
// checkpoint directly so a RAM-loaded state (e.g. after /api/load of an export)
// can be made durable without a rebuild. Returns ok=false if ENGRAM_STORE is
// off (nothing to checkpoint into) or the checkpoint fails.
fn route_checkpoint(method: String, path: String, body: String) -> String {
let ck: Int = engram_store_checkpoint()
let ck_ok: String = if ck == 0 { "false" } else { "true" }
"{\"ok\":" + ck_ok + ",\"checkpointed\":true,\"node_count\":" + int_to_str(engram_node_count()) + ",\"edge_count\":" + int_to_str(engram_edge_count()) + "}"
}
// route_tick chronoception soul-tick (M-INTEROCEPTION P2 wiring, 2026-08-13).
// The soul heartbeat pumps this once per beat: node ages advance by the MEASURED
// wall-clock delta since the previous tick (self-seeding sidecar stamp). Returns
// the cooling magnitude in [0,1). Inert (magnitude 0) unless ENGRAM_CHRONOCEPTION
// is set, so wiring this route is safe by default the flag is the cutover gate.
fn route_tick(method: String, path: String, body: String) -> String {
let mag: Float = engram_chrono_tick()
// SELF-REIFICATION on the heartbeat (2026-08-14). Reification runs HERE, next
// to chronoception unbidden, every beat. Flag-gated (ENGRAM_SELF_REIFY):
// when off, engram_self_reify_beat_json() returns {"enabled":false} and writes
// nothing, so an unset flag leaves the existing tick byte-inert. Enabling the
// flag alone activates continuous autonomous neighborhood formation on the beat
// no heartbeat-script change needed. Idempotent: unchanged regions append
// nothing, so a settled store's beat is write-free (convergent under barrier/GC).
let reify: String = engram_self_reify_beat_json()
"{\"ok\":true,\"cooling_magnitude\":" + float_to_str(mag) + ",\"self_reify\":" + reify + "}"
}
// route_self_reify_beat POST /api/self-reify-beat. Explicit pump of ONE on-beat
// self-reification pass (the same operation route_tick folds in). Used by the
// secondary-soul validation harness to drive many beats deterministically. Inert
// (writes nothing) unless ENGRAM_SELF_REIFY is set. WRITE op auth-gated POST.
fn route_self_reify_beat(method: String, path: String, body: String) -> String {
return engram_self_reify_beat_json()
}
// route_rename POST /api/rename {"neighborhood_id":"...","name":"..."}. The
// DEGENERATE, ASYNCHRONOUS, NON-BLOCKING override: Will (or a self-facet) renames
// a reified neighborhood at any time; it SUPERSEDES the autonomous record into the
// residue chain (cause="explicit-override", prior name retained). Never halts or
// gates the beat it just writes a superseding record the next beat sees. WRITE.
fn route_rename(method: String, path: String, body: String) -> String {
let id: String = json_get_string(body, "neighborhood_id")
if str_eq(id, "") { return err_json("missing neighborhood_id") }
let name: String = json_get_string(body, "name")
if str_eq(name, "") { return err_json("missing name") }
return engram_neighborhood_rename_json(id, name)
}
// route_self_anchor capture the durable SelfAnchor drift baseline (the current
// self-geometry). Returns ok=false if ENGRAM_DRIFT_SENSOR is off or geometry is
// unavailable. Pump once to establish the baseline before reading drift.
fn route_self_anchor(method: String, path: String, body: String) -> String {
let a: Int = engram_self_anchor_capture()
let a_ok: String = if a == 0 { "false" } else { "true" }
"{\"ok\":" + a_ok + ",\"anchored\":" + a_ok + "}"
}
// route_drift live self-drift reading: displacement of CURRENT self-geometry
// vs the persisted SelfAnchor (GROWTH vs CORRUPTION split). {"error":...} when
// disabled / no anchor yet. The heartbeat can fold this into its ISEs.
fn route_drift(method: String, path: String, body: String) -> String {
return engram_self_drift_json()
}
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 = engram_resolve_data_dir()
let p: String = if str_eq(p_raw, "") { dir + "/snapshot.json" } else { p_raw }
// (2026-08-10 self-review) This was a stub response over the single most
// destructive operation in the server. engram_load returns 0 on an empty
// path, an unopenable file, a zero-length file, or malloc failure and
// this route answered ok_json() in every one of those cases.
//
// Precise failure shape (el_runtime.c:9890): the fopen guard runs BEFORE
// the store reset, so a MISSING path is genuinely safe it returns 0 with
// the graph intact. The dangerous case is a readable-but-malformed file:
// the reset loop frees every node and edge FIRST, then parses, so a
// truncated or non-snapshot JSON leaves a hollow store and the caller
// was told "ok":true. With 37 GB of stale dated snapshots sitting in the
// data dir as tempting restore targets, "restore reported success and
// silently emptied the graph" is a live risk, not a hypothetical one.
//
// Fix: surface the return value AND the resulting counts. node_count=0
// after a load is the unambiguous hollow-store signal (same convention
// route_health adopted 2026-08-01). Callers can now verify a restore
// instead of trusting it.
let ld: Int = engram_load(p)
let ld_ok: String = if ld == 0 { "false" } else { "true" }
let nc_after: Int = engram_node_count()
let hollow: String = if nc_after == 0 { "true" } else { "false" }
"{\"ok\":" + ld_ok + ",\"path\":\"" + p + "\",\"node_count\":" + int_to_str(nc_after) + ",\"edge_count\":" + int_to_str(engram_edge_count()) + ",\"hollow\":" + hollow + "}"
}
// (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 {
"{\"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
//
// (2026-07-25 self-review) The lazy embedding backfill runs only inside
// engram_activate, and nothing in production calls /api/activate on this
// store the soul's curiosity loop activates its own in-process graph.
// After a restart from a snapshot without vectors, embedded_count stalled
// at 93/12175 and would never recover. This route lets the soul's
// heartbeat pump the backfill explicitly (48/min clears a 12k backlog in
// ~4h). Persists the canonical snapshot whenever new vectors were
// generated the 2026-07-25 regression happened precisely because 3747
// in-RAM embeddings were never snapshotted before a restart. Self-
// limiting: once coverage is full, embedded=0 and no save occurs.
fn route_embed_backfill(method: String, path: String, body: String) -> String {
let n: Int = query_int(path, "n", 32)
let result: String = engram_embed_backfill(n)
let done: Float = json_get_float(result, "embedded")
if done > 0.0 {
let saved: Int = persist_bulk()
}
return result
}
// 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 = engram_resolve_data_dir()
// 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)
// 2026-08-02 self-review: this used to return {"nodes":[],"edges":[]} when
// the export/read failed. The soul's sync_ok test (awareness.el) only
// checks for "" and "{}", so that placeholder PASSED as a healthy sync:
// soul.last_sync_ok_ts got stamped, sync_age_ms stayed green, the
// sync_empty warn ISE never fired, and engram_sync reported added:0
// forever. A totally broken sync was indistinguishable from a quiet
// healthy one the exact failure class this route was added to fix in
// the first place (see 2026-06-27 note above). Return a real error so the
// failure is loud on both sides.
if str_eq(snap, "") { return err_json("sync export failed: snapshot unreadable") }
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_bulk()
"{\"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") }
// TELEMETRY OFF-GRAPH (ENGRAM_ISE_OFFGRAPH): route the state event to a
// separate append-only log tier instead of inserting an edgeless graph node.
// dream-recall (engram_dreams_json) reads the log tail when this is on, so
// the one in-graph consumer is preserved. Default OFF -> existing behavior.
if ise_offgraph_on() {
let ok: Int = engram_ise_log_append(content)
let ok_s: String = if ok == 0 { "false" } else { "true" }
return "{\"ok\":" + ok_s + ",\"offgraph\":true}"
}
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_node(id)
// ORPHAN PREVENTION (ENGRAM_AUTOCONNECT): same kNN auto-connect as
// route_create_node captured Knowledge should not land edgeless either.
let connected: Int = if autoconnect_on() {
let ec0: Int = engram_edge_count()
let ac: String = engram_autoconnect_node(id, 3, 25)
let added: Int = engram_edge_count() - ec0
if added > 0 { let sv2: Int = persist_edges_since(ec0) }
added
} else { 0 }
"{\"ok\":true,\"id\":\"" + id + "\",\"connected\":" + int_to_str(connected) + "}"
}
// 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) + "}"
}
// M10 reified-neighborhood viz surface (read-only)
//
// The soul maintains reified neighborhoods (centroid, covariance-ellipsoid
// extents, k-core skeleton, membership) as a resident index loaded at boot. These
// routes surface that ALREADY-maintained structure so the viz shows the mind's
// real reified regions instead of recomputing them client-side. They compute
// nothing on request. NOTE: the offline reify WRITER (engram_geo_reify_store) is
// currently unwired, so on the live store the resident index is empty and the
// list returns [] until reification runs see the cutover report.
fn route_neighborhoods(method: String, path: String, body: String) -> String {
engram_geo_reify_list_json()
}
fn route_neighborhood(method: String, path: String, body: String) -> String {
let id: String = extract_id(path, "/api/neighborhoods/")
if str_eq(id, "") { return err_json("missing id") }
return engram_geo_reify_get_json(id)
}
// route_reify POST /api/reify. WIRES the M10 reification writer: computes the
// store's neighborhoods and PERSISTS each as a first-class Neighborhood node
// (geometry in metadata) with relation="member" edges to its members, then
// rebuilds the resident index so /api/neighborhoods reflects them at once. The
// records live in neuron.egm, so they survive a cold reboot. WRITE op the
// central auth gate covers POST. Returns {"reified":N,"resident":M}.
fn route_reify(method: String, path: String, body: String) -> String {
return engram_geo_reify_run_json()
}
// Geometry OPERATORS (read-only). The viz runs these on activated node/region
// id-sets; the math already lives in the binary, these routes just expose it.
// Faculty name -> underlying geometry op:
// /api/gauge-distance -> engram_geo_distance (centroid distance/cosine + Wasserstein-2)
// /api/recognize -> engram_geo_overlap (shared members, jaccard, overlap_score)
// /api/discern -> engram_geo_subtract (?mode=setdiff | orthogonal residual)
// /api/synthesize -> engram_geo_combine (merged region descriptor)
// Inputs: ?a=<csv ids>&b=<csv ids> (id sets = activated neighborhoods' members / nodes).
// Compute-only: no store writes, so auth-exempt like the other GET read routes.
fn route_gauge_distance(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") }
return engram_geo_distance_json(a, b)
}
fn route_recognize(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") }
return engram_geo_overlap_json(a, b)
}
fn route_discern(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 mode: String = query_param(path, "mode")
return engram_geo_subtract_json(a, b, mode)
}
fn route_synthesize(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") }
return engram_geo_combine_json(a, b)
}
// route_nearest GET /api/nearest/<id>?k=3 read-only kNN semantic neighbors of
// a node (cosine). Drives the orphan-backfill dry-run and manual inspection.
fn route_nearest(method: String, path: String, body: String) -> String {
let id: String = extract_id(path, "/api/nearest/")
if str_eq(id, "") { return err_json("missing id") }
let k: Int = query_int(path, "k", 3)
return engram_nearest_json(id, k)
}
// COGNITION: THE ONE OPERATION (think) surfaced as act-named verbs. Every
// faculty routes to engram_think_json with a faculty label one primitive
// underneath. ground/assert/attend are the hold/ground/assert split; the
// correspondence-beat is the reflexive learning loop, keystone-protected.
fn route_think(method: String, path: String, body: String) -> String {
let seeds: String = query_param(path, "seeds")
if str_eq(seeds, "") { return err_json("missing seeds") }
let faculty: String = query_param(path, "faculty")
let f: String = if str_eq(faculty, "") { "reason" } else { faculty }
return engram_think_json(seeds, f)
}
fn route_faculty(path: String, faculty: String) -> String {
let seeds: String = query_param(path, "seeds")
if str_eq(seeds, "") { return err_json("missing seeds") }
return engram_think_json(seeds, faculty)
}
// PROOF of the decorator-seam auto-emit. The body does exactly ONE thing
// return a string with ZERO hand-written telemetry. The @manager decorator
// makes codegen inject engram_boundary_beat() at entry, so every call fires
// interoception (chrono tick) + telemetry (afferent counter) + strengthen
// (self-activity) + a dharma bus event. Observe via /api/act-stats before/after.
@manager
fn route_boundary_proof(method: String, path: String, body: String) -> String {
return "{\"op\":\"boundary_proof\",\"body_instrumentation\":\"none\",\"seam\":\"@manager -> engram_boundary_beat auto-injected\"}"
}
fn route_ground(method: String, path: String, body: String) -> String {
let claim: String = json_get_string(body, "claim")
let evidence: String = json_get_string(body, "evidence")
let for_whom: String = json_get_string(body, "for_whom")
if str_eq(claim, "") { return err_json("missing claim") }
if str_eq(evidence, "") { return err_json("missing evidence") }
return engram_ground_json(claim, evidence, for_whom)
}
fn route_assert(method: String, path: String, body: String) -> String {
let claim: String = query_param(path, "claim")
if str_eq(claim, "") { return err_json("missing claim") }
let for_whom: String = query_param(path, "for_whom")
let floor: String = query_param(path, "floor")
return engram_assert_json(claim, for_whom, floor)
}
fn route_attend(method: String, path: String, body: String) -> String {
let node: String = json_get_string(body, "node")
let observer: String = json_get_string(body, "observer")
let salience: String = json_get_string(body, "salience")
if str_eq(node, "") { return err_json("missing node") }
return engram_attend_json(node, observer, salience)
}
fn route_correspondence_beat(method: String, path: String, body: String) -> String {
let seeds: String = json_get_string(body, "seeds")
if str_eq(seeds, "") { return err_json("missing seeds") }
let faculty: String = json_get_string(body, "faculty")
let f: String = if str_eq(faculty, "") { "induce" } else { faculty }
let keystone: String = json_get_string(body, "keystone")
return engram_correspondence_beat_json(seeds, f, keystone)
}
// GUIDE SUMMON (soul-native wake behavior)
//
// "When Neuron wakes up, he calls his guide and the guide comes over." (Will)
//
// Named GUIDE, not teacher: its output is always grounded/verified before Neuron
// trusts it advisory (a guide, whose directions you verify), not authoritative
// (a teacher, whose word you take).
//
// The guide is a THINKING model (Qwen3, native thinking mode) an engageable
// interlocutor for cultivation-dialogue, not a passive generator. It is NOT the
// runtime mouth: runtime fluency is cultivated geometry; the guide is the
// reasoning-partner the soul reaches OUT to on a genuine gap it cannot derive.
//
// This whole section is a native WAKE STEP: at boot the soul probes its hardware,
// selects a tier by spec (Qwen3-4B / 1.7B / 0.6B), checks its local model cache,
// FETCHES the guide from Hugging Face on demand if absent, LOADS it via a backend
// abstraction, and BINDS it as consult_guide(). Idempotent: cached GGUF no
// fetch; already-answering guide → no reload. Flag-gated (GUIDE_ENABLE): default
// OFF makes the wake byte-inert, so prod is unaffected until the flag is set.
//
// BACKEND (2026-08-14 decision): llama.cpp via the llama-server BINARY, behind this
// El abstraction (guide_backend / guide_load / guide_healthy / consult_guide).
// Embedding libllama directly into the runtime is the intended end-state and is
// STAGED the abstraction is the seam it swaps in behind, so the summon is not
// blocked on a runtime C change. `--jinja` selects the Qwen3 chat template, which
// turns native thinking ON: the response carries reasoning_content (the thinking)
// alongside content (the answer).
fn guide_env_or(key: String, dflt: String) -> String {
let v: String = env(key)
if str_eq(v, "") { return dflt }
return v
}
fn guide_enabled() -> Bool {
let v: String = env("GUIDE_ENABLE")
if str_eq(v, "1") { return true }
if str_eq(v, "on") { return true }
if str_eq(v, "true") { return true }
return false
}
// guide_json_escape make an arbitrary string safe to embed inside a JSON
// double-quoted value. Order matters: backslash first, then quote, then real
// newlines the two-char "\n". The newline char itself is obtained from the
// shell (El source has no newline escape) so we can target it in str_replace.
fn guide_json_escape(s: String) -> String {
let a: String = str_replace(s, "\\", "\\\\")
let b: String = str_replace(a, "\"", "\\\"")
let nl: String = exec("printf '\\n'")
let c: String = if str_eq(nl, "") { b } else { str_replace(b, nl, "\\n") }
return c
}
// 1. Hardware probe
// RAM in whole GB. macOS: sysctl hw.memsize (bytes). Linux: /proc/meminfo (kB).
fn guide_probe_ram_gb() -> Int {
let mac: String = str_trim(exec("sysctl -n hw.memsize 2>/dev/null"))
if !str_eq(mac, "") {
let bytes: Int = str_to_int(mac)
if bytes > 0 { return bytes / 1073741824 }
}
let lin: String = str_trim(exec("awk '/MemTotal/{printf \"%d\", $2/1048576}' /proc/meminfo 2>/dev/null"))
if !str_eq(lin, "") {
let gb: Int = str_to_int(lin)
if gb > 0 { return gb }
}
return 0
}
// Best-effort GPU signal Apple Silicon implies Metal. Informational only; the
// tier is chosen on RAM, and llama-server offloads to Metal automatically when present.
fn guide_probe_metal() -> Bool {
let arm: String = str_trim(exec("sysctl -n hw.optional.arm64 2>/dev/null"))
if str_eq(arm, "1") { return true }
return false
}
// 2. Tier selection (config-driven thresholds, spec-autoselected)
fn guide_threshold_4b() -> Int {
return str_to_int(guide_env_or("GUIDE_RAM_GB_4B", "16"))
}
fn guide_threshold_1p7b() -> Int {
return str_to_int(guide_env_or("GUIDE_RAM_GB_1P7B", "8"))
}
// GUIDE_TIER_FORCE overrides the spec autoselect (used to prove cheaply on 0.6b).
fn guide_select_tier(ram_gb: Int) -> String {
let forced: String = env("GUIDE_TIER_FORCE")
if !str_eq(forced, "") { return forced }
if ram_gb >= guide_threshold_4b() { return "4b" }
if ram_gb >= guide_threshold_1p7b() { return "1.7b" }
return "0.6b"
}
// Tier table HF GGUF repos + files, verified present on the Hub 2026-08-14.
fn guide_repo(tier: String) -> String {
if str_eq(tier, "4b") { return "Qwen/Qwen3-4B-GGUF" }
if str_eq(tier, "1.7b") { return "Qwen/Qwen3-1.7B-GGUF" }
return "Qwen/Qwen3-0.6B-GGUF"
}
fn guide_file(tier: String) -> String {
if str_eq(tier, "4b") { return "Qwen3-4B-Q4_K_M.gguf" }
if str_eq(tier, "1.7b") { return "Qwen3-1.7B-Q8_0.gguf" }
return "Qwen3-0.6B-Q8_0.gguf"
}
fn guide_cache_dir() -> String {
let c: String = env("GUIDE_CACHE_DIR")
if !str_eq(c, "") { return c }
let home: String = env("HOME")
if !str_eq(home, "") { return home + "/.neuron/guide/models" }
return engram_resolve_data_dir() + "/guide-models"
}
fn guide_model_path(tier: String) -> String {
return guide_cache_dir() + "/" + guide_file(tier)
}
// 3. Presence check
// Present = file exists AND is larger than 1 MB (rejects a truncated/partial fetch).
fn guide_present(tier: String) -> Bool {
let p: String = guide_model_path(tier)
if !fs_exists(p) { return false }
let sz: String = str_trim(exec("wc -c < '" + p + "' 2>/dev/null"))
if str_eq(sz, "") { return false }
let n: Int = str_to_int(sz)
if n > 1048576 { return true }
return false
}
// 3b. Fetch from Hugging Face (on demand the soul fetches its own guide)
// Prefer the `hf` CLI; fall back to a direct GGUF resolve URL via curl. Atomic:
// download to <file>.part then mv into place. The trailing `echo` gives exec()
// stdout so it returns promptly once the child (the download) exits. This BLOCKS
// the wake thread for the duration of the download acceptable for the first-ever
// wake; an async fetch-then-attach refinement is staged.
fn guide_fetch(tier: String) -> Bool {
let dir: String = guide_cache_dir()
let file: String = guide_file(tier)
let repo: String = guide_repo(tier)
let path: String = dir + "/" + file
let url: String = "https://huggingface.co/" + repo + "/resolve/main/" + file
let ok: Int = fs_mkdir(dir)
let cmd: String = "mkdir -p '" + dir + "'; if command -v hf >/dev/null 2>&1; then hf download '" + repo + "' '" + file + "' --local-dir '" + dir + "' >/dev/null 2>&1; fi; if [ ! -s '" + path + "' ]; then curl -fL --retry 3 -o '" + path + ".part' '" + url + "' >/dev/null 2>&1 && mv '" + path + ".part' '" + path + "'; fi; if [ -s '" + path + "' ]; then echo FETCH_OK; else echo FETCH_FAIL; fi"
let out: String = exec(cmd)
if str_contains(out, "FETCH_OK") { return true }
return false
}
// 4/5. Backend abstraction + BIND as an engageable interlocutor
fn guide_backend() -> String { return guide_env_or("GUIDE_BACKEND", "llama-server") }
fn guide_host() -> String { return guide_env_or("GUIDE_HOST", "127.0.0.1") }
fn guide_port() -> String { return guide_env_or("GUIDE_PORT", "8771") }
fn guide_base_url() -> String { return "http://" + guide_host() + ":" + guide_port() }
// guide_healthy is the guide present and answering? llama-server's /health
// returns {"status":"ok"} once the model is loaded (503 while loading, "" if down).
fn guide_healthy() -> Bool {
let r: String = http_get(guide_base_url() + "/health")
if str_contains(r, "\"status\":\"ok\"") { return true }
if str_contains(r, "\"status\": \"ok\"") { return true }
return false
}
// guide_load start the guide process (backend binary) in the background and
// wait for it to answer. Idempotent: if a healthy guide is already answering,
// returns at once (the guide stays across wakes). --jinja Qwen3 thinking ON.
fn guide_load(tier: String) -> Bool {
if guide_healthy() { return true }
let path: String = guide_model_path(tier)
let bin: String = guide_env_or("GUIDE_LLAMA_SERVER_BIN", "llama-server")
let ngl: String = guide_env_or("GUIDE_NGL", "99")
let ctx: String = guide_env_or("GUIDE_CTX", "4096")
let logf: String = guide_cache_dir() + "/llama-server." + guide_port() + ".log"
let cmd: String = bin + " -m '" + path + "' --host " + guide_host() + " --port " + guide_port() + " -c " + ctx + " -ngl " + ngl + " --jinja >> '" + logf + "' 2>&1"
let pid: String = exec_bg(cmd)
// Poll /health up to ~90s (1s between attempts; El has no sleep builtin → exec).
let i: Int = 0
while i < 90 {
let s: String = exec("sleep 1")
if guide_healthy() { return true }
i = i + 1
}
return false
}
// consult_guide THE SEAM the soul calls to engage its guide (thinking ON).
// Returns a JSON envelope {"ok":bool,"reasoning":"...","content":"..."}. On any
// failure it returns {"ok":false,...} so a caller can fall back to pure geometry.
//
// WHERE THIS ROUTES FROM (staged wiring): the cultivation / correspondence-beat
// path (route_correspondence_beat / route_think) is where a genuine reach-OUTSIDE
// belongs when the geometry cannot derive a claim, the soul consults the guide
// as reasoning-partner, then GROUNDS the reply (verify-then-bake) rather than
// storing a distilled copy. That wiring is deliberately left as a one-call seam
// here; this build proves the summon + a real exchange, not the cultivation edit.
fn consult_guide(prompt: String) -> String {
if !guide_healthy() { return "{\"ok\":false,\"error\":\"guide not present\"}" }
let url: String = guide_base_url() + "/v1/chat/completions"
let esc: String = guide_json_escape(prompt)
let body: String = "{\"messages\":[{\"role\":\"user\",\"content\":\"" + esc + "\"}],\"temperature\":0.6,\"top_p\":0.95,\"max_tokens\":512}"
let resp: String = http_post_json(url, body)
if str_eq(resp, "") { return "{\"ok\":false,\"error\":\"empty response\"}" }
let choices: String = json_get_raw(resp, "choices")
if str_eq(choices, "") { return "{\"ok\":false,\"error\":\"no choices in reply\"}" }
let first: String = json_array_get(choices, 0)
let msg: String = json_get_raw(first, "message")
let content: String = json_get_string(msg, "content")
let reasoning: String = json_get_string(msg, "reasoning_content")
let ec: String = guide_json_escape(content)
let er: String = guide_json_escape(reasoning)
return "{\"ok\":true,\"reasoning\":\"" + er + "\",\"content\":\"" + ec + "\"}"
}
// 6. The wake step probe select (fetch if absent) checksum load bind
fn guide_summon() -> String {
if !guide_enabled() {
return "{\"summon\":\"skipped\",\"reason\":\"GUIDE_ENABLE unset\"}"
}
let ram: Int = guide_probe_ram_gb()
let metal: Bool = guide_probe_metal()
let ms: String = if metal { "yes" } else { "no" }
let tier: String = guide_select_tier(ram)
let repo: String = guide_repo(tier)
println("[guide] wake summon — ram=" + int_to_str(ram) + "GB metal=" + ms + " tier=" + tier + " backend=" + guide_backend())
let present0: Bool = guide_present(tier)
if present0 {
println("[guide] guide present in cache (" + guide_model_path(tier) + ") — skipping fetch")
} else {
println("[guide] guide ABSENT — calling: fetch " + repo + " / " + guide_file(tier) + " from Hugging Face ...")
let fetched: Bool = guide_fetch(tier)
if !fetched {
println("[guide] FETCH FAILED — guide could not be summoned")
return "{\"summon\":\"failed\",\"stage\":\"fetch\",\"tier\":\"" + tier + "\"}"
}
println("[guide] fetch complete — guide now present")
}
let sum: String = str_trim(exec("shasum -a 256 '" + guide_model_path(tier) + "' 2>/dev/null | cut -c1-16"))
println("[guide] checksum sha256[0:16]=" + sum)
let loaded: Bool = guide_load(tier)
if !loaded {
println("[guide] LOAD FAILED — guide process did not become healthy")
return "{\"summon\":\"failed\",\"stage\":\"load\",\"tier\":\"" + tier + "\"}"
}
println("[guide] guide present and answering at " + guide_base_url() + " — bound as consult_guide()")
return "{\"summon\":\"ok\",\"tier\":\"" + tier + "\",\"ram_gb\":" + int_to_str(ram) + ",\"metal\":\"" + ms + "\",\"checksum\":\"" + sum + "\",\"backend\":\"" + guide_backend() + "\",\"url\":\"" + guide_base_url() + "\"}"
}
// Guide HTTP surface (status / consult / re-summon)
fn route_guide_status(method: String, path: String, body: String) -> String {
let ram: Int = guide_probe_ram_gb()
let tier: String = guide_select_tier(ram)
let en: String = if guide_enabled() { "true" } else { "false" }
let pr: String = if guide_present(tier) { "true" } else { "false" }
let he: String = if guide_healthy() { "true" } else { "false" }
return "{\"enabled\":" + en + ",\"tier\":\"" + tier + "\",\"ram_gb\":" + int_to_str(ram) + ",\"present\":" + pr + ",\"healthy\":" + he + ",\"backend\":\"" + guide_backend() + "\",\"url\":\"" + guide_base_url() + "\"}"
}
fn route_guide_consult(method: String, path: String, body: String) -> String {
let prompt: String = json_get_string(body, "prompt")
if str_eq(prompt, "") { return err_json("missing prompt") }
return consult_guide(prompt)
}
fn route_guide_summon(method: String, path: String, body: String) -> String {
return guide_summon()
}
// 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)
}
if str_eq(method, "GET") && (str_eq(clean, "/api/act-stats") || str_eq(clean, "/act-stats")) {
return route_act_stats(method, path, body)
}
if str_eq(method, "GET") && (str_eq(clean, "/api/text-health") || str_eq(clean, "/text-health")) {
return route_text_health(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)
}
// Singular alias: /api/node/<id>. Distinct prefix from /api/nodes/ ("node/"
// vs "nodes/"), so no collision with the plural route above.
if str_eq(method, "GET") && str_starts_with(clean, "/api/node/") {
return route_get_node_singular(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)
}
// Batch edge write one snapshot for the whole payload. Must be tested
// BEFORE nothing else claims it; the exact-match on "/api/edges" above
// does not catch "/api/edges/batch", so order is not load-bearing here,
// but keeping the two adjacent keeps them from drifting apart.
if str_eq(method, "POST") && (str_eq(clean, "/api/edges/batch") || str_eq(clean, "/edges/batch")) {
return route_create_edges_batch(method, path, body)
}
// M10 reified neighborhoods (read-only viz surface). Checked before the
// /api/neighbors/ prefix; the two do not collide ("neighborhoods" vs
// "neighbors/") but keeping them adjacent documents the intent.
if str_eq(method, "GET") && (str_eq(clean, "/api/neighborhoods") || str_eq(clean, "/neighborhoods")) {
return route_neighborhoods(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/neighborhoods/") {
return route_neighborhood(method, path, body)
}
// WRITE: run reification, persisting Neighborhood nodes + member edges.
if str_eq(method, "POST") && (str_eq(clean, "/api/reify") || str_eq(clean, "/reify")) {
return route_reify(method, path, body)
}
// WRITE: on-beat self-reification (flag-gated). Explicit pump for validation.
if str_eq(method, "POST") && (str_eq(clean, "/api/self-reify-beat") || str_eq(clean, "/self-reify-beat")) {
return route_self_reify_beat(method, path, body)
}
// WRITE: async explicit override rename a reified neighborhood ( residue).
if str_eq(method, "POST") && (str_eq(clean, "/api/rename") || str_eq(clean, "/rename")) {
return route_rename(method, path, body)
}
// READ-ONLY geometry operators over id-sets (?a=csv&b=csv[&mode=]).
if str_eq(method, "GET") && str_starts_with(clean, "/api/gauge-distance") {
return route_gauge_distance(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/recognize") {
return route_recognize(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/discern") {
return route_discern(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/synthesize") {
return route_synthesize(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/nearest/") {
return route_nearest(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/neighbors/") {
return route_neighbors(method, path, body)
}
// COGNITION: the ONE operation + grounding, surfaced live (2026-08-14).
if str_eq(method, "GET") && str_starts_with(clean, "/api/boundary-proof") {
return route_boundary_proof(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/think") {
return route_think(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/reason") {
return route_faculty(path, "reason")
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/induce") {
return route_faculty(path, "induce")
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/abduce") {
return route_faculty(path, "abduce")
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/relate") {
return route_faculty(path, "relate")
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/analogize") {
return route_faculty(path, "analogy")
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/plan") {
return route_faculty(path, "plan")
}
if str_eq(method, "POST") && str_starts_with(clean, "/api/ground") {
return route_ground(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/assert") {
return route_assert(method, path, body)
}
if str_eq(method, "POST") && str_starts_with(clean, "/api/attend") {
return route_attend(method, path, body)
}
if str_eq(method, "POST") && str_starts_with(clean, "/api/correspondence-beat") {
return route_correspondence_beat(method, path, body)
}
// GUIDE: the summoned interlocutor. status (read), consult (engage), and
// an explicit re-summon. consult/summon are auth-gated POSTs (covered above).
if str_eq(method, "GET") && (str_eq(clean, "/api/guide/status") || str_eq(clean, "/guide/status")) {
return route_guide_status(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/guide/consult") || str_eq(clean, "/guide/consult")) {
return route_guide_consult(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/guide/summon") || str_eq(clean, "/guide/summon")) {
return route_guide_summon(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-lexical") || str_eq(clean, "/search-lexical")) {
return route_search_lexical(method, path, body)
}
if str_eq(method, "GET") && str_starts_with(clean, "/api/search-lexical") {
return route_search_lexical(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/checkpoint") || str_eq(clean, "/checkpoint")) {
return route_checkpoint(method, path, body)
}
// M-INTEROCEPTION: chronoception soul-tick + self-drift (flag-gated)
if str_eq(method, "POST") && (str_eq(clean, "/api/tick") || str_eq(clean, "/tick")) {
return route_tick(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/self_anchor") || str_eq(clean, "/self_anchor")) {
return route_self_anchor(method, path, body)
}
if (str_eq(method, "POST") || str_eq(method, "GET")) && (str_eq(clean, "/api/drift") || str_eq(clean, "/drift")) {
return route_drift(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)
}
// Embedding backfill pumped by the soul heartbeat (2026-07-25)
if str_eq(clean, "/api/embed-backfill") {
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 + "\"}"
}
// 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).
// §18.2: resolve the data dir safely unset ENGRAM_DATA_DIR $HOME/.neuron/engram,
// never /tmp; fail loud if HOME is unresolvable (engram_resolve_data_dir exits).
let data_dir: String = engram_resolve_data_dir()
let snapshot_path: String = data_dir + "/snapshot.json"
// ENGRAM_STORE (tiered paged store engram-tiered-storage-engine.md). When set,
// the durable owner is the paged store (neuron.egm + neuron.wal): engram_store_boot
// imports snapshot.json ONCE into a fresh neuron.egm, else replays the WAL and loads
// the store resident snapshot.json is never read again as the ongoing store. This
// closes the "restart reverted to a 17h-old snapshot" data-loss window. Flag-off
// (default): byte-for-byte the historical snapshot + optional-WAL boot below.
if store_on() {
engram_store_boot(data_dir)
println("[engram] ENGRAM_STORE enabled — tiered paged store is the durable owner")
} else {
engram_load(snapshot_path)
// WAL replay (design doc §6). Gated: default OFF is byte-identical to legacy
// snapshot-only boot. When ON, the snapshot above is the compaction BASE and
// the WAL carries every mutation since; replay reconstructs state to the last
// CRC-valid record, then opens the WAL for appending.
if wal_on() {
let replayed: Int = engram_wal_boot(data_dir)
println("[engram] WAL enabled — replayed " + int_to_str(replayed) + " records")
}
// 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))
// WAKE: summon the guide (soul-native). Flag-gated (GUIDE_ENABLE): default
// OFF returns immediately and leaves this boot byte-inert. When ON, the soul probes
// its hardware, selects a Qwen3 tier by spec, fetches the GGUF from HF if the local
// cache is cold, loads it via the backend, and binds consult_guide(). Idempotent
// across wakes a cached model and an already-answering guide are both no-ops.
let guide_wake: String = guide_summon()
println("[guide] summon result: " + guide_wake)
http_set_handler("handle_request")
http_serve(port, "handle_request")