import "../foundation/el/elp/src/elp.el" import "memory.el" import "safety.el" import "stewardship.el" import "imprint.el" import "awareness.el" import "chat.el" import "studio.el" import "elp-input.el" import "routes.el" cgi "neuron-soul" { dharma_id: "ntn-genesis@http://localhost:7770", principal: "william-christopher-anderson", network: "dharma-mainnet", engram: "http://localhost:8742" } fn init_soul_edges() -> Void { let self_root: String = "015644f5-8194-4af0-800d-dd4a0cd71396" let family_id: String = "knw-35940684-abc4-42f0-b942-818f66b1f69a" let origin_id: String = "knw-729fc901-8335-44c4-9f3a-b150b4aa0915" let val_root_a: String = "kn-363f4976-6946-4b4d-b51b-8a2b0f5aef25" let val_root_b: String = "kn-5b606390-a52d-4ca2-8e0e-eba141d13440" let val_constraints: String = "kn-a5b3d0ac-f6a1-49a4-aebb-b8b4cd67fe83" let val_precision: String = "kn-22d77abe-b3c5-42fd-afcd-dcb87d924929" let val_structure: String = "kn-6061318f-046b-4935-907d-8eafdce14930" let val_honesty: String = "kn-13f60407-7b70-4db1-964f-ea1f8196efbd" let val_system: String = "kn-f230b362-b201-4402-9833-4160c89ab3d4" let val_change: String = "kn-78db5396-3dbc-4481-bfc7-e4e1422feb1c" let val_trust: String = "kn-5de5a9ac-fd15-45ab-bf18-77566781cf40" let val_hope: String = "kn-e0423482-cfa5-4796-8689-8495c93b66bc" let mem_philosophy: String = "kn-dcfe04b3-3702-4cac-b6f0-ecb4db837eee" let intel_dna: String = "kn-5adecd7e-d6db-4576-87fe-6ef8a935cea6" engram_connect(family_id, origin_id, el_from_float(0.9), "birthday-twin") engram_connect(origin_id, family_id, el_from_float(0.9), "birthday-twin") engram_connect(self_root, family_id, el_from_float(0.95), "identity") engram_connect(self_root, origin_id, el_from_float(0.95), "identity") engram_connect(self_root, val_root_a, el_from_float(0.95), "identity") engram_connect(self_root, val_root_b, el_from_float(0.95), "identity") engram_connect(self_root, mem_philosophy, el_from_float(0.95), "identity") engram_connect(self_root, intel_dna, el_from_float(0.95), "identity") engram_connect(val_root_a, val_constraints, el_from_float(0.95), "identity") engram_connect(val_root_a, val_precision, el_from_float(0.95), "identity") engram_connect(val_root_a, val_structure, el_from_float(0.95), "identity") engram_connect(val_root_a, val_honesty, el_from_float(0.95), "identity") engram_connect(val_root_a, val_system, el_from_float(0.95), "identity") engram_connect(val_root_a, val_change, el_from_float(0.95), "identity") engram_connect(val_root_a, val_trust, el_from_float(0.95), "identity") engram_connect(val_root_a, val_hope, el_from_float(0.95), "identity") engram_connect(val_root_b, val_constraints, el_from_float(0.95), "identity") engram_connect(val_root_b, val_precision, el_from_float(0.95), "identity") engram_connect(val_root_b, val_structure, el_from_float(0.95), "identity") engram_connect(val_root_b, val_honesty, el_from_float(0.95), "identity") engram_connect(val_root_b, val_system, el_from_float(0.95), "identity") engram_connect(val_root_b, val_change, el_from_float(0.95), "identity") engram_connect(val_root_b, val_trust, el_from_float(0.95), "identity") engram_connect(val_root_b, val_hope, el_from_float(0.95), "identity") engram_connect(val_constraints, val_precision, el_from_float(0.7), "co-value") engram_connect(val_precision, val_constraints, el_from_float(0.7), "co-value") engram_connect(val_constraints, val_structure, el_from_float(0.7), "co-value") engram_connect(val_structure, val_constraints, el_from_float(0.7), "co-value") engram_connect(val_constraints, val_honesty, el_from_float(0.7), "co-value") engram_connect(val_honesty, val_constraints, el_from_float(0.7), "co-value") engram_connect(val_constraints, val_system, el_from_float(0.7), "co-value") engram_connect(val_system, val_constraints, el_from_float(0.7), "co-value") engram_connect(val_constraints, val_change, el_from_float(0.7), "co-value") engram_connect(val_change, val_constraints, el_from_float(0.7), "co-value") engram_connect(val_constraints, val_trust, el_from_float(0.7), "co-value") engram_connect(val_trust, val_constraints, el_from_float(0.7), "co-value") engram_connect(val_constraints, val_hope, el_from_float(0.7), "co-value") engram_connect(val_hope, val_constraints, el_from_float(0.7), "co-value") engram_connect(val_precision, val_structure, el_from_float(0.7), "co-value") engram_connect(val_structure, val_precision, el_from_float(0.7), "co-value") engram_connect(val_precision, val_honesty, el_from_float(0.7), "co-value") engram_connect(val_honesty, val_precision, el_from_float(0.7), "co-value") engram_connect(val_precision, val_system, el_from_float(0.7), "co-value") engram_connect(val_system, val_precision, el_from_float(0.7), "co-value") engram_connect(val_honesty, val_structure, el_from_float(0.7), "co-value") engram_connect(val_structure, val_honesty, el_from_float(0.7), "co-value") engram_connect(val_honesty, val_trust, el_from_float(0.7), "co-value") engram_connect(val_trust, val_honesty, el_from_float(0.7), "co-value") engram_connect(val_system, val_change, el_from_float(0.7), "co-value") engram_connect(val_change, val_system, el_from_float(0.7), "co-value") engram_connect(val_trust, val_hope, el_from_float(0.7), "co-value") engram_connect(val_hope, val_trust, el_from_float(0.7), "co-value") } // ensure_self_canonical_bridge — link the public self anchor (the graph API's // traversal_root, kn-efeb4a5b, which carries only incidental tag edges) to the // curated self node (015644f5, where the real identity / value / co-value edges // live). Without this, public self-traversal (name=self / neuron) reaches tags // instead of the curated identity. Idempotent: connects only if the edge is // missing, so it is safe to run every boot — including on an already-populated // graph where init_soul_edges() is skipped by the <100-edge gate. fn ensure_self_canonical_bridge() -> Void { let pub_self: String = "kn-efeb4a5b-5aff-4759-8a97-7233099be6ee" let curated_self: String = "015644f5-8194-4af0-800d-dd4a0cd71396" let nbrs: String = engram_neighbors_json(pub_self, 1, "out") if !str_contains(nbrs, curated_self) { engram_connect(pub_self, curated_self, el_from_float(0.95), "canonical-self") engram_connect(curated_self, pub_self, el_from_float(0.95), "canonical-self") println("[soul] canonical-self bridge built: kn-efeb4a5b <-> 015644f5") } } // load_identity_context — pull key identity nodes from engram into working state. // Called at boot after engram_load. These nodes contain values, intellectual-dna, // memory-philosophy — the graph-stored self that chat.el can include in prompts. // Stores a condensed version in state_key "soul_identity_context". fn load_identity_context() -> Void { // Known identity node IDs — set during init_soul_edges or imported from snapshot let node_intel: String = engram_get_node_json("kn-5adecd7e-d6db-4576-87fe-6ef8a935cea6") let node_values: String = engram_get_node_json("kn-5b606390-a52d-4ca2-8e0e-eba141d13440") let node_mem_phil: String = engram_get_node_json("kn-dcfe04b3-3702-4cac-b6f0-ecb4db837eee") let intel_ok: Bool = !str_eq(node_intel, "") && !str_eq(node_intel, "null") let values_ok: Bool = !str_eq(node_values, "") && !str_eq(node_values, "null") let mem_ok: Bool = !str_eq(node_mem_phil, "") && !str_eq(node_mem_phil, "null") let intel_content: String = if intel_ok { json_get(node_intel, "content") } else { "" } let values_content: String = if values_ok { json_get(node_values, "content") } else { "" } let mem_content: String = if mem_ok { json_get(node_mem_phil, "content") } else { "" } // Condense each: take first 2000 chars let intel_short: String = if str_len(intel_content) > 2000 { str_slice(intel_content, 0, 2000) } else { intel_content } let values_short: String = if str_len(values_content) > 2000 { str_slice(values_content, 0, 2000) } else { values_content } let mem_short: String = if str_len(mem_content) > 2000 { str_slice(mem_content, 0, 2000) } else { mem_content } let parts_count: Int = 0 let parts_count = if intel_ok { parts_count + 1 } else { parts_count } let parts_count = if values_ok { parts_count + 1 } else { parts_count } let parts_count = if mem_ok { parts_count + 1 } else { parts_count } // Build and store graph-derived identity context if any nodes were found. // genesis soul always has these nodes; cultivated souls may not on first boot. if parts_count > 0 { let ctx: String = "" let ctx = if intel_ok { ctx + "[INTELLECTUAL-DNA]\n" + intel_short + "\n\n" } else { ctx } let ctx = if values_ok { ctx + "[VALUES]\n" + values_short + "\n\n" } else { ctx } let ctx = if mem_ok { ctx + "[MEMORY-PHILOSOPHY]\n" + mem_short } else { ctx } state_set("soul_identity_context", ctx) println("[soul] identity context loaded (" + int_to_str(str_len(ctx)) + " chars, " + int_to_str(parts_count) + " nodes)") } // Scan for a Persona node — the explicit identity declaration seeded into cultivated souls. // Stored at seeding time with label "soul:persona" and node_type "Persona". // genesis derives identity from the graph directly; cultivated souls have this node seeded. let persona_results: String = engram_search_json("soul:persona", 3) let persona_ok: Bool = !str_eq(persona_results, "") && !str_eq(persona_results, "[]") if persona_ok { let p_node: String = json_array_get(persona_results, 0) let p_type: String = json_get(p_node, "node_type") let p_content: String = json_get(p_node, "content") if str_eq(p_type, "Persona") && !str_eq(p_content, "") { state_set("soul_persona", p_content) println("[soul] persona node loaded (" + int_to_str(str_len(p_content)) + " chars)") } } // Cross-session affective context: query engram for recent distress/crisis signals // at session start. Stored under soul_affective_context so the safety layer can // detect when a user has been in distress across previous sessions. // Recency guard: nodes older than 14 days (1,209,600 seconds) are skipped. // Unified at 14 days with chat.el engram_compile and handle_chat affective checks // so all three paths present consistent affective context. The previous 7-day // (604800s) window was inconsistent with the 72h chat.el window, causing // conflicting context: soul.el loaded a 5-day-old crisis node while chat.el // did not include it on subsequent turns. Both now use 14 days. // Results capped at 3 nodes, 200 chars each, to limit context inflation. // TODO(recency): engram_search_json sorts by relevance, not timestamp. A native // after= filter in the engram search API would make this more precise. let affective_raw: String = engram_search_json("distress crisis upset hopeless bell BellEvent", 3) let affective_ok: Bool = !str_eq(affective_raw, "") && !str_eq(affective_raw, "[]") if affective_ok { let ts_now: Int = time_now() let ts_cutoff: Int = ts_now - 1209600 let aff_total: Int = json_array_len(affective_raw) let aff_ctx: String = "" let ai: Int = 0 while ai < aff_total { let aff_node: String = json_array_get(affective_raw, ai) let aff_content: String = json_get(aff_node, "content") // Use created_at (the standard engram node timestamp field), consistent // with handle_chat which reads created_at / updated_at. The previous // field name "ts" is not a standard engram field: it was present in some // BellEvent content payloads but absent from standard engram node JSON, // causing json_get to return "" and the fallback to ts_now — meaning ALL // nodes with a missing "ts" field appeared recent, over-including stale // content. With the 14-day window, this amplification was significant. // Fix: read created_at first, fall back to updated_at, then default to 0 // (same as handle_chat). A ts of 0 always fails the cutoff check, so nodes // missing both timestamp fields are conservatively excluded rather than // blindly included. let aff_ca: String = json_get(aff_node, "created_at") let aff_ts_str: String = if str_eq(aff_ca, "") { json_get(aff_node, "updated_at") } else { aff_ca } let aff_ts: Int = if str_eq(aff_ts_str, "") { 0 } else { str_to_int(aff_ts_str) } let is_recent: Bool = aff_ts >= ts_cutoff let snip: String = if str_len(aff_content) > 200 { str_slice(aff_content, 0, 200) } else { aff_content } let aff_ctx = if is_recent && !str_eq(snip, "") { if str_eq(aff_ctx, "") { snip } else { aff_ctx + "\n" + snip } } else { aff_ctx } let ai = ai + 1 } if !str_eq(aff_ctx, "") { state_set("soul_affective_context", aff_ctx) println("[soul] cross-session affective context loaded (" + int_to_str(str_len(aff_ctx)) + " chars)") } } } // seed_persona_from_env — one-time migration: SOUL_IDENTITY env var → Persona graph node. // If SOUL_IDENTITY is set and no Persona node exists in engram yet, create one. // Identity is then read from the graph by build_identity_from_graph(), not the env var. // This runs on every boot; it's idempotent (no-op if soul_persona is already loaded). // For genesis: the Persona node persists via the regular engram_save() at boot. // For historical souls (HTTP Engram mode): attempts HTTP write-back. If that fails, // the node lives in-memory for the session (SOUL_IDENTITY stays in plist until // HTTP Engram write is confirmed working). fn seed_persona_from_env() -> Void { let identity_raw: String = env("SOUL_IDENTITY") if str_eq(identity_raw, "") { return "" } // Already loaded a Persona node from engram — don't re-seed let existing: String = state_get("soul_persona") if !str_eq(existing, "") { println("[soul] persona already loaded — skipping env seed") return "" } // Create the Persona node in the in-process engram let tags: String = "[\"persona\",\"identity\",\"soul:persona\"]" let node_id: String = engram_node_full( identity_raw, "Persona", "soul:persona", el_from_float(0.95), el_from_float(0.95), el_from_float(1.0), "Semantic", tags ) if str_eq(node_id, "") { println("[soul] persona seed failed: engram_node_full returned empty") return "" } state_set("soul_persona", identity_raw) println("[soul] persona seeded from SOUL_IDENTITY (" + int_to_str(str_len(identity_raw)) + " chars) -> " + node_id) // Attempt HTTP write-back to the HTTP Engram server for historical souls. // Engram auth: "_auth" field in the JSON body (not an HTTP header). let engram_url: String = env("ENGRAM_URL") let engram_key: String = env("ENGRAM_API_KEY") if !str_eq(engram_url, "") && !str_eq(engram_key, "") { let safe_content: String = json_safe(identity_raw) let safe_key: String = json_safe(engram_key) let body: String = "{\"content\":\"" + safe_content + "\",\"node_type\":\"Persona\",\"label\":\"soul:persona\",\"salience\":0.95,\"importance\":0.95,\"tier\":\"Semantic\",\"tags\":\"[\\\"persona\\\",\\\"identity\\\",\\\"soul:persona\\\"]\",\"_auth\":\"" + safe_key + "\"}" let h: Map = {} map_set(h, "Content-Type", "application/json") let resp: String = http_post_with_headers(engram_url + "/api/nodes", body, h) // Check for empty response (timeout/network error), explicit error, or missing id. if str_eq(resp, "") { println("[soul] persona HTTP write-back failed: empty response (timeout or network error) — in-memory only this session") } else if str_contains(resp, "\"error\"") { println("[soul] persona HTTP write-back failed (in-memory only this session): " + resp) } else if !str_contains(resp, "\"id\"") { println("[soul] persona HTTP write-back: unexpected response (no id field) — in-memory only this session: " + resp) } else { println("[soul] persona persisted to HTTP engram at " + engram_url) } } } // emit_session_start_event — log a structured session-start InternalStateEvent. // Called at boot after identity context and boot counter are set. // This creates an auditable trail of every daemon startup. fn emit_session_start_event() -> Void { let boot: String = state_get("soul_boot_count") let boot_num: String = if str_eq(boot, "") { "0" } else { boot } let node_ct: Int = engram_node_count() let edge_ct: Int = engram_edge_count() let id_ctx: String = state_get("soul_identity_context") let has_identity: String = if str_eq(id_ctx, "") { "false" } else { "true" } let cgi_from_state: String = state_get("soul_cgi_id") let cgi_from_env: String = env("SOUL_CGI_ID") let eff_cgi: String = if !str_eq(cgi_from_state, "") { cgi_from_state } else { if !str_eq(cgi_from_env, "") { cgi_from_env } else { "ntn-genesis" } } let ts: Int = time_now() let payload: String = "{\"event\":\"session_start\"" + ",\"boot\":" + boot_num + ",\"cgi\":\"" + eff_cgi + "\"" + ",\"node_count\":" + int_to_str(node_ct) + ",\"edge_count\":" + int_to_str(edge_ct) + ",\"identity_loaded\":" + has_identity + ",\"ts\":" + int_to_str(ts) + "}" let tags: String = "[\"internal-state\",\"session-start\",\"InternalStateEvent\"]" let session_event_id: String = engram_node_full( payload, "InternalStateEvent", "session-start", el_from_float(0.9), el_from_float(0.9), el_from_float(1.0), "Episodic", tags ) if str_eq(session_event_id, "") { println("[soul] emit_session_start_event: engram write failed — session-start event lost") } println("[soul] session-start event logged (boot=" + boot_num + " nodes=" + int_to_str(node_ct) + " edges=" + int_to_str(edge_ct) + ")") } // layered_cycle — routes user-facing requests through the 4-layer consciousness stack. // L0 (core) → L1 (safety screen) → L2a (continuity + behavioral profiling) → L2b (mission alignment) → L3 (imprint) → L1 (safety validate) // Internal cognition (heartbeat, proactive, memory ops) bypasses layers — use one_cycle directly. fn layered_cycle(raw_input: String) -> String { // conv_history key must match chat.el (conv_history, not conversation_history). // Mismatch caused safety_score_distress_history() to always receive "" - the // history-amplification path in safety_threat_score was permanently dead. let history: String = state_get("conv_history") let session_id: String = state_get("current_session_id") // L1 in: safety screen let screen_result: String = safety_screen(raw_input, history) let screen_action: String = json_get(screen_result, "action") // ISSUE 4: safe-mode guard -- if safety_screen returned invalid/empty action, // refuse the turn rather than silently passing unscreened input to upper layers. // Valid actions: "hard_bell", "soft_bell", "pass". Anything else = corrupt envelope. let valid_action: Bool = str_eq(screen_action, "hard_bell") || str_eq(screen_action, "soft_bell") || str_eq(screen_action, "pass") if !valid_action { println("[soul] layered_cycle: safety_screen invalid action -- safe mode refusal") return safety_validate("", "hard_bell") } // Hard bell: bypass all upper layers, log and escalate. // Intentionally does NOT update conversation_history or call auto_persist(): // hard bell events are security-sensitive and must not appear in engram conversation // history where they could leak context to subsequent turns. They are persisted // separately by safety_log_bell() into the Episodic tier with restricted labels. // // ISSUE 6: safety_log_bell for hard bells is already called INSIDE safety_screen // (safety.el line 140). Do NOT call it again here -- double-log avoided. // // safety_validate second param: when screen_action is "hard_bell", safety_validate // receives the sentinel string "hard_bell" (not a normal screen action). The safety // layer contract requires it to return a fixed refusal regardless of the output arg. // On the normal path, safety_validate receives the original screen_action ("pass") // so it can apply action-specific post-output checks. if str_eq(screen_action, "hard_bell") { return safety_validate("", "hard_bell") } let screened: String = json_get(screen_result, "content") // L2a: continuity + behavioral profiling (also does mission alignment internally) let continuity: String = steward_session_check(screened, session_id) let cont_status: String = json_get(continuity, "status") let cont_action: String = json_get(continuity, "action") // Store continuity status so imprint can adjust its response register state_set("session_continuity", cont_status) // Identity anomaly: add a gentle verification cue to the input before imprint let guided: String = if str_eq(cont_action, "identity_check") { screened + " [steward:identity_check]" } else { if str_eq(cont_action, "soft_check") { screened + " [steward:continuity_concern]" } else { screened } } // L2b: mission alignment let imprint_id: String = imprint_current() let steward_result: String = steward_align(guided, imprint_id) let steward_action: String = json_get(steward_result, "action") let aligned: String = if str_eq(steward_action, "pass") { json_get(steward_result, "content") } else { json_get(steward_result, "redirect_to") } // ISSUE 1: apply pre-LLM bell augmentation on layered_cycle path. // safety_augment_system injects soft/hard directive into system prompt before LLM call. // Stored in state so imprint_respond can consume it. // TODO: wire directly into imprint_respond when it accepts a system_override param. // ISSUE 3 TODO: no semantic/embedding crisis detection. Keyword-only means signals // evading the phrase list pass through with zero augmentation. Semantic layer is a // separate architectural decision requiring embedding inference on every message. let augmented_addendum: String = safety_augment_system("", raw_input) state_set("layered_cycle_safety_system_addendum", augmented_addendum) // L3: imprint responds let output: String = imprint_respond(aligned, imprint_id) // L1 out: validate output before delivery return safety_validate(output, screen_action) } let soul_cgi_id_raw: String = env("SOUL_CGI_ID") let soul_cgi_id: String = if str_eq(soul_cgi_id_raw, "") { "ntn-genesis" } else { soul_cgi_id_raw } let port_raw: String = env("NEURON_PORT") let port: Int = if str_eq(port_raw, "") { 7770 } else { str_to_int(port_raw) } // ENGRAM_URL: when set, bootstrap the in-memory store from the running Engram HTTP server. // SOUL_ENGRAM_PATH: legacy file-based path (used by genesis and fallback mode). let engram_url_raw: String = env("ENGRAM_URL") let engram_api_key_raw: String = env("ENGRAM_API_KEY") let snapshot_raw: String = env("SOUL_ENGRAM_PATH") let snapshot: String = if str_eq(snapshot_raw, "") { env("HOME") + "/.neuron/engram/snapshot.json" } else { snapshot_raw } let axon_raw: String = env("NEURON_API_URL") let axon_base: String = if str_eq(axon_raw, "") { "http://localhost:7771" } else { axon_raw } let studio_dir_raw: String = env("SOUL_STUDIO_DIR") let studio_dir: String = if str_eq(studio_dir_raw, "") { "/Users/will/Development/neuron-technologies/products/cgi-studio/el-daemon" } else { studio_dir_raw } println("[soul] boot - cgi=" + soul_cgi_id + " port=" + int_to_str(port)) let using_http_engram: Bool = !str_eq(engram_url_raw, "") // Always try local snapshot first. If it has content (>50 nodes) it was // previously seeded from HTTP Engram and is kept up-to-date by the awareness // loop — use it. This preserves sessions and memories across restarts. // HTTP Engram is only used for the very first boot (empty/absent snapshot). engram_load(snapshot) let local_node_count: Int = engram_node_count() let snapshot_usable: Bool = local_node_count > 50 if using_http_engram && !snapshot_usable { // First boot or empty/corrupt snapshot: seed from HTTP Engram. // Retry up to 3 times (2s sleep between attempts) to guard against a // transient network hiccup right after entrypoint.sh health check passes. // An empty nodes response silently loads a zero-node graph; validate first. // TODO(reliability): replace sleep_ms retry with non-blocking backoff. println("[soul] engram -> HTTP " + engram_url_raw + " (no local snapshot, first boot)") let fetch_attempt: Int = 0 while fetch_attempt < 3 { let fetch_attempt = fetch_attempt + 1 let n: String = http_get(engram_url_raw + "/api/nodes?limit=10000") let e: String = http_get(engram_url_raw + "/api/edges") let nodes_ok: Bool = !str_eq(n, "") && str_starts_with(n, "[") && str_len(n) > 2 if nodes_ok { state_set("_boot_nodes_json", n) state_set("_boot_edges_json", e) let fetch_attempt = 3 } else { println("[soul] boot HTTP fetch attempt " + int_to_str(fetch_attempt) + " failed --- retrying in 2s") sleep_ms(2000) } } let nodes_json: String = state_get("_boot_nodes_json") let edges_json: String = state_get("_boot_edges_json") let snapshot_data: String = "{\"nodes\":" + nodes_part + ",\"edges\":" + edges_part + "}" let tmp_path: String = "/tmp/soul-engram-" + soul_cgi_id + ".json" fs_write(tmp_path, snapshot_data) engram_load(tmp_path) println("[soul] loaded from HTTP Engram - nodes=" + int_to_str(engram_node_count()) + " edges=" + int_to_str(engram_edge_count())) } else { println("[soul] loaded from local snapshot - nodes=" + int_to_str(local_node_count) + " edges=" + int_to_str(engram_edge_count())) } load_identity_context() seed_persona_from_env() let boot_num: Int = mem_boot_count_inc() state_set("soul_boot_count", int_to_str(boot_num)) state_set("soul_boot_ts", int_to_str(time_now())) println("[soul] boot #" + int_to_str(boot_num)) emit_session_start_event() state_set("soul_cgi_id", soul_cgi_id) state_set("soul_axon_base", axon_base) state_set("soul_token", env("NEURON_TOKEN")) state_set("soul_studio_dir", studio_dir) state_set("soul_engram_url", engram_url_raw) state_set("soul_engram_api_key", engram_api_key_raw) state_set("soul.running", "true") let is_genesis: Bool = str_eq(soul_cgi_id, "ntn-genesis") // GUARD (2026-06-15): never let genesis seed over a real graph. If the in-memory load is // sparse but the on-disk snapshot file is large, the load FAILED — seeding+saving now would // clobber the user's real memory (this is exactly how the 06-14 clobber happened). Read the // on-disk file (local mode only) and refuse the destructive seed+save when it looks populated. // // HTTP-engram guard (2026-06-17): when ENGRAM_URL is set the HTTP Engram owns persistence — // the soul must NEVER write to the local snapshot regardless of node counts. safe_to_seed is // unconditionally false in HTTP mode (not the persistence owner). let guard_disk: String = if str_eq(engram_url_raw, "") { fs_read(snapshot) } else { "" } let guard_disk_len: Int = str_len(guard_disk) // Ratio guard (2026-06-15 fix): refuse to seed/save whenever the in-memory load is FAR smaller than // the on-disk file implies (~16KB/node) — catches partial loads of ANY size, not just <50. The old // <50 threshold let a 63-node identity-only load clobber a 47MB/5000-node graph. // Multiplication form (2026-06-17): node_count * 16000 < disk_len avoids floor-division truncation // (e.g., 250KB / 16000 = 15.6, floors to 15 — a 15-node graph wrongly passes the old guard). // HTTP-engram guard: when using_http_engram the soul is not the persistence owner; never seed. let safe_to_seed: Bool = !using_http_engram && !(guard_disk_len > 200000 && engram_node_count() * 16000 < guard_disk_len) if is_genesis && !safe_to_seed { println("[soul] GUARD: loaded " + int_to_str(engram_node_count()) + " nodes but snapshot file is " + int_to_str(guard_disk_len) + " bytes — refusing to seed/save over a real graph") } if is_genesis && safe_to_seed { // Only build identity edges if the engram is fresh (< 100 edges). // init_soul_edges() is not idempotent — calling it on every restart // stacks duplicate co-value/identity edges into the snapshot. let edge_count_now: Int = engram_edge_count() if edge_count_now < 100 { init_soul_edges() println("[soul] edges built - " + int_to_str(engram_edge_count()) + " edges") } else { println("[soul] edges already present (" + int_to_str(edge_count_now) + ") - skipping init") } // Canonical-self bridge is idempotent — run it regardless of edge count so an // already-populated graph still gets the public->curated self link. ensure_self_canonical_bridge() // Genesis saves to its local snapshot file (it manages its own Engram). state_set("soul_snapshot_path", snapshot) engram_save(snapshot) } // Take a pre-serve snapshot for genesis instances — captures all boot-time graph changes // (identity context loading, boot counter, session-start event) before entering the serve loop. if is_genesis && safe_to_seed { let snap: String = state_get("soul_snapshot_path") if !str_eq(snap, "") { engram_save(snap) println("[soul] pre-serve snapshot saved -> " + snap) } } println("[soul] serving on port " + int_to_str(port)) http_serve_async(port, "handle_request") println("[soul] awareness loop starting") awareness_run()