From 2018036bce00377664dc64da4a6dffbfac6f7df7 Mon Sep 17 00:00:00 2001 From: Neuron Date: Sun, 9 Aug 2026 12:18:16 -0500 Subject: [PATCH] =?UTF-8?q?fix(soul):=20restore=20the=20soul=5Fidentity=20?= =?UTF-8?q?producer=20=E2=80=94=20the=20chat=20system=20prompt=20has=20bee?= =?UTF-8?q?n=20empty=20for=20three=20months=20(#137)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five sites in chat.el read state_get("soul_identity") and splice the result into the system prompt, beside the voice, security and capability rules: chat.el:737, 1745, 2620, 3425, 3480 Nothing has written that key since b163fa6. The producer was added 2026-05-02 in 601e0fe and deleted by the awareness refactor days later. Every chat turn since has built its system prompt with an EMPTY identity section, and nothing reported it. Found by the #132 state-key gate, which treats a read with no producer as a build error rather than a silence. That is the entire argument for that gate. RESTORED VERBATIM, NOT IMPROVED. soul_identity is an env-configurable persona LINE. It is not soul_identity_context — the graph-derived [INTELLECTUAL-DNA]/[VALUES]/[MEMORY-PHILOSOPHY] block written at soul.el:184. Repointing the five reads at that block would have substituted different content and called it a repair. Whether the chat prompt should ALSO carry the graph-derived block is a real question and a separate one; it is not smuggled in here. Verified by the gate that found it: dead reads 6 -> 1, and it now reports the chat.el baseline entry as STALE — 'entries that no longer match anything; delete them'. The remaining one is studio.el's soul_principal, untouched by this change. Rung: BUILT, gate-verified, boots. NOT end-to-end chat-verified — proving the prompt now carries the line needs a live provider call, which I have not run. Refs #137, #132 Co-Authored-By: Claude Opus 5 (1M context) --- dist/soul.c | 11 ++++++++--- dist/soul.c.stamp | 6 +++--- soul.el | 21 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/dist/soul.c b/dist/soul.c index 2b11fcc..b3d28bd 100644 --- a/dist/soul.c +++ b/dist/soul.c @@ -1274,6 +1274,8 @@ el_val_t axon_raw; el_val_t axon_base; el_val_t studio_dir_raw; el_val_t studio_dir; +el_val_t identity_raw; +el_val_t soul_identity; el_val_t using_http_engram; el_val_t local_node_count; el_val_t snapshot_usable; @@ -31948,6 +31950,9 @@ int main(int _argc, char** _argv) { axon_base = ({ el_val_t _if_result_824 = 0; if (str_eq(axon_raw, EL_STR(""))) { _if_result_824 = (EL_STR("http://localhost:7771")); } else { _if_result_824 = (axon_raw); } _if_result_824; }); studio_dir_raw = env(EL_STR("SOUL_STUDIO_DIR")); studio_dir = ({ el_val_t _if_result_825 = 0; if (str_eq(studio_dir_raw, EL_STR(""))) { _if_result_825 = (el_str_concat(env(EL_STR("HOME")), EL_STR("/Development/neuron-technologies/products/cgi-studio/el-daemon"))); } else { _if_result_825 = (studio_dir_raw); } _if_result_825; }); + identity_raw = env(EL_STR("SOUL_IDENTITY")); + soul_identity = ({ el_val_t _if_result_826 = 0; if (str_eq(identity_raw, EL_STR(""))) { _if_result_826 = (el_str_concat(el_str_concat(EL_STR("You are "), soul_cgi_id), EL_STR(", a CGI."))); } else { _if_result_826 = (identity_raw); } _if_result_826; }); + state_set(EL_STR("soul_identity"), soul_identity); println(el_str_concat(el_str_concat(el_str_concat(EL_STR("[soul] boot - cgi="), soul_cgi_id), EL_STR(" port=")), int_to_str(port))); using_http_engram = !str_eq(engram_url_raw, EL_STR("")); engram_load(snapshot); @@ -31957,8 +31962,8 @@ int main(int _argc, char** _argv) { println(el_str_concat(el_str_concat(EL_STR("[soul] engram -> HTTP "), engram_url_raw), EL_STR(" (no local snapshot, first boot)"))); el_val_t nodes_json = http_get(el_str_concat(engram_url_raw, EL_STR("/api/nodes?limit=10000"))); el_val_t edges_json = http_get(el_str_concat(engram_url_raw, EL_STR("/api/edges"))); - el_val_t nodes_part = ({ el_val_t _if_result_826 = 0; if (str_eq(nodes_json, EL_STR(""))) { _if_result_826 = (EL_STR("[]")); } else { _if_result_826 = (nodes_json); } _if_result_826; }); - el_val_t edges_part = ({ el_val_t _if_result_827 = 0; if (str_eq(edges_json, EL_STR(""))) { _if_result_827 = (EL_STR("[]")); } else { _if_result_827 = (edges_json); } _if_result_827; }); + el_val_t nodes_part = ({ el_val_t _if_result_827 = 0; if (str_eq(nodes_json, EL_STR(""))) { _if_result_827 = (EL_STR("[]")); } else { _if_result_827 = (nodes_json); } _if_result_827; }); + el_val_t edges_part = ({ el_val_t _if_result_828 = 0; if (str_eq(edges_json, EL_STR(""))) { _if_result_828 = (EL_STR("[]")); } else { _if_result_828 = (edges_json); } _if_result_828; }); el_val_t snapshot_data = el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"nodes\":"), nodes_part), EL_STR(",\"edges\":")), edges_part), EL_STR("}")); el_val_t tmp_path = el_str_concat(el_str_concat(EL_STR("/tmp/soul-engram-"), soul_cgi_id), EL_STR(".json")); fs_write(tmp_path, snapshot_data); @@ -31982,7 +31987,7 @@ int main(int _argc, char** _argv) { state_set(EL_STR("soul_engram_api_key"), engram_api_key_raw); state_set(EL_STR("soul.running"), EL_STR("true")); is_genesis = str_eq(soul_cgi_id, EL_STR("ntn-genesis")); - guard_disk = ({ el_val_t _if_result_828 = 0; if (str_eq(engram_url_raw, EL_STR(""))) { _if_result_828 = (fs_read(snapshot)); } else { _if_result_828 = (EL_STR("")); } _if_result_828; }); + guard_disk = ({ el_val_t _if_result_829 = 0; if (str_eq(engram_url_raw, EL_STR(""))) { _if_result_829 = (fs_read(snapshot)); } else { _if_result_829 = (EL_STR("")); } _if_result_829; }); guard_disk_len = str_len(guard_disk); safe_to_seed = (!using_http_engram && !((guard_disk_len > 200000) && ((engram_node_count() * 16000) < guard_disk_len))); if (is_genesis && !safe_to_seed) { diff --git a/dist/soul.c.stamp b/dist/soul.c.stamp index 90c0264..d2c7292 100644 --- a/dist/soul.c.stamp +++ b/dist/soul.c.stamp @@ -1,7 +1,7 @@ # soul.c.stamp — fingerprint of the .el sources dist/soul.c was generated from. # Written by tools/soulc-stamp.sh --write. Do not hand-edit. -# generated_amalgam_sha256 63e30030bee5e87fa082a84cda5c1226896f49da6076101fcd6b9530ea7caf49 -# generated_amalgam_bytes 1204442 +# generated_amalgam_sha256 ee09798ad93ddd047136577cf324483e5956984d60d06596d34662f315ee0df4 +# generated_amalgam_bytes 1204845 f8597e10546654bce3fbbe40461b2da59d0e06dbf1b038d1d362d24f949e3911 awareness.el b6f3d14ca0c26017a2d617399a6d3754dabb0905e4d5f52eb75d25c4ad18d3c5 chat.el 42288c212cbf72fb1e8ecbd4d9900e4e9ee1cfa475b7974295c7637f1bf2939f elp-input.el @@ -13,6 +13,6 @@ fba8ffdb9ba72bca5b09ca1c93a520edc52f3f4d8aec2c7585fe9b17e06420b2 manifest.el a6d69f3fc55233d9d3300160fd46a1551f2064bcd0fb84e2c9e432f636a72476 routes.el c28e36952ec56525963a0bdf29455ab097d3b0c5653d19c25fbb005e1069a1f7 safety.el fd3ab91d0ae0ea26639e21bef2f8f94054dc4b02eae68b19e3fe689d2769aad4 sessions.el -0f1cf43904a98a5a646cce5a07e0e96162ced662692fbc13357d9b67d9a8ac3d soul.el +5613b60d74d5d7768f46da5ac435a5dd99d38c27f0f7013c89fa27e98dc8a21c soul.el 30337940905171a9645b0929f0a412ce6b3dccb1246495070c553bca0bbae6cd stewardship.el e105dc5990e6adbf39db9dc0462cd8bcf6e6c3dfd03709059227ecfad2bbab29 studio.el diff --git a/soul.el b/soul.el index 7e46d00..1f1cdc7 100644 --- a/soul.el +++ b/soul.el @@ -559,6 +559,27 @@ let axon_base: String = if str_eq(axon_raw, "") { "http://localhost:7771" } else let studio_dir_raw: String = env("SOUL_STUDIO_DIR") let studio_dir: String = if str_eq(studio_dir_raw, "") { env("HOME") + "/Development/neuron-technologies/products/cgi-studio/el-daemon" } else { studio_dir_raw } +// RESTORED 2026-08-09 — this producer was added 2026-05-02 in 601e0fe and deleted +// by the awareness refactor b163fa6 a few days later. Nothing has written +// soul_identity since, while FIVE sites in chat.el kept reading it: +// chat.el:737, 1745, 2620, 3425, 3480 — each doing state_get("soul_identity") +// and splicing the result into the system prompt beside the voice, security and +// capability rules. They have been splicing an EMPTY STRING for roughly three +// months. The identity section of every chat turn was blank and nothing said so. +// +// Found by the #132 state-key gate, which reports a read with no producer as a +// build error rather than a silence — the whole reason that gate exists. +// +// Restored verbatim rather than improved: this key is an env-configurable persona +// LINE, which is NOT the same thing as soul_identity_context (the graph-derived +// [INTELLECTUAL-DNA]/[VALUES]/[MEMORY-PHILOSOPHY] block written at soul.el:184). +// Pointing these five reads at that block instead would have substituted different +// content and called it a fix. Whether the chat system prompt should ALSO carry the +// graph-derived block is a real question, and a separate one. +let identity_raw: String = env("SOUL_IDENTITY") +let soul_identity: String = if str_eq(identity_raw, "") { "You are " + soul_cgi_id + ", a CGI." } else { identity_raw } +state_set("soul_identity", soul_identity) + println("[soul] boot - cgi=" + soul_cgi_id + " port=" + int_to_str(port)) let using_http_engram: Bool = !str_eq(engram_url_raw, "")