feat(soul): add safety module, expand connectors API, memory-recall bug notes

- safety.el/.elh: new safety module
- neuron-api.el, routes.el, soul.el, chat.el: connectors API expansion
- regenerated dist/ C artifacts
- MEMORY_RECALL_BUG.md: investigation notes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tim Lingo
2026-06-15 11:10:33 -05:00
committed by Will Anderson
parent 2797909633
commit 6d8a992716
13 changed files with 381 additions and 15 deletions
Generated Vendored
+2 -1
View File
@@ -1,4 +1,4 @@
// auto-generated by elc --emit-header do not edit
// auto-generated by elc --emit-header - do not edit
extern fn chat_default_model() -> String
extern fn gemini_api_key() -> String
extern fn xai_api_key() -> String
@@ -19,6 +19,7 @@ extern fn studio_tools_json() -> String
extern fn agentic_api_key() -> String
extern fn call_neuron_mcp(tool_name: String, args_json: String) -> String
extern fn agentic_tools_literal() -> String
extern fn agentic_tools_with_web() -> String
extern fn dispatch_tool(tool_name: String, tool_input: String) -> String
extern fn handle_chat_agentic(body: String) -> String
extern fn handle_chat_as_soul(body: String) -> String
Generated Vendored
+36 -2
View File
@@ -1042,12 +1042,36 @@ el_val_t call_neuron_mcp(el_val_t tool_name, el_val_t args_json);
el_val_t agentic_tools_literal(void);
el_val_t agentic_tools_with_web(void);
el_val_t dispatch_tool(el_val_t tool_name, el_val_t tool_input);
el_val_t json_array_append(el_val_t arr, el_val_t item);
el_val_t append_tool_log(el_val_t log, el_val_t name);
el_val_t exec_tool_block(el_val_t block);
el_val_t agentic_blob(el_val_t model, el_val_t system, el_val_t tools_json, el_val_t messages, el_val_t origin, el_val_t approval, el_val_t iteration, el_val_t tools_log, el_val_t content, el_val_t queue, el_val_t results, el_val_t next);
el_val_t extract_all_text(el_val_t s);
el_val_t strip_citations(el_val_t s);
el_val_t agentic_api_turn(el_val_t model, el_val_t safe_sys, el_val_t tools_json, el_val_t messages);
el_val_t agentic_engine(el_val_t session_id, el_val_t blob);
el_val_t handle_chat_agentic(el_val_t body);
el_val_t handle_session_approve(el_val_t session_id, el_val_t body);
el_val_t handle_chat_as_soul(el_val_t body);
el_val_t handle_dharma_room_turn(el_val_t body);
el_val_t handle_dharma_room_turn_agentic(el_val_t body);
el_val_t auto_persist(el_val_t req, el_val_t resp);
el_val_t strengthen_chat_nodes(el_val_t activation_nodes);
el_val_t safety_self_harm_phrases(void);
el_val_t safety_abuse_phrases(void);
el_val_t safety_general_hard_phrases(void);
el_val_t safety_soft_phrases(void);
el_val_t safety_normalize(el_val_t message);
el_val_t safety_any_match(el_val_t text, el_val_t phrases_json);
el_val_t safety_count_match(el_val_t text, el_val_t phrases_json);
el_val_t safety_detect_bell_level(el_val_t message);
el_val_t safety_classify_hard_bell(el_val_t message);
el_val_t safety_soft_directive(void);
el_val_t safety_hard_directive(el_val_t hard_type);
el_val_t safety_augment_system(el_val_t system, el_val_t user_msg);
el_val_t safety_contact_path(void);
el_val_t handle_safety_contact_get(void);
el_val_t handle_safety_contact_post(el_val_t body);
el_val_t auth_headers(el_val_t tok);
el_val_t axon_get(el_val_t path);
el_val_t axon_post(el_val_t path, el_val_t body);
@@ -1110,6 +1134,7 @@ el_val_t session_update_meta_timestamp(el_val_t session_id);
el_val_t session_auto_title(el_val_t session_id, el_val_t first_message);
el_val_t handle_session_approve(el_val_t session_id, el_val_t body);
el_val_t strip_query(el_val_t path);
el_val_t flag_true(el_val_t body, el_val_t key);
el_val_t err_404(el_val_t path);
el_val_t err_405(el_val_t method, el_val_t path);
el_val_t route_health(void);
@@ -1144,6 +1169,9 @@ el_val_t local_node_count;
el_val_t snapshot_usable;
el_val_t boot_num;
el_val_t is_genesis;
el_val_t guard_disk;
el_val_t guard_disk_len;
el_val_t safe_to_seed;
el_val_t lang_profile(el_val_t code, el_val_t word_order, el_val_t morph_type, el_val_t has_case, el_val_t has_gender, el_val_t script_dir, el_val_t agreement, el_val_t null_subject) {
el_val_t r = native_list_empty();
@@ -28915,7 +28943,13 @@ 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"));
if (is_genesis) {
guard_disk = ({ el_val_t _if_result_25 = 0; if (str_eq(engram_url_raw, EL_STR(""))) { _if_result_25 = (fs_read(snapshot)); } else { _if_result_25 = (EL_STR("")); } _if_result_25; });
guard_disk_len = str_len(guard_disk);
safe_to_seed = !((engram_node_count() < 50) && (guard_disk_len > 200000));
if (is_genesis && !safe_to_seed) {
println(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("[soul] GUARD: loaded "), int_to_str(engram_node_count())), EL_STR(" nodes but snapshot file is ")), int_to_str(guard_disk_len)), EL_STR(" bytes \xe2\x80\x94 refusing to seed/save over a real graph")));
}
if (is_genesis && safe_to_seed) {
el_val_t edge_count_now = engram_edge_count();
if (edge_count_now < 100) {
init_soul_edges();
@@ -28926,7 +28960,7 @@ int main(int _argc, char** _argv) {
state_set(EL_STR("soul_snapshot_path"), snapshot);
engram_save(snapshot);
}
if (is_genesis) {
if (is_genesis && safe_to_seed) {
el_val_t snap = state_get(EL_STR("soul_snapshot_path"));
if (!str_eq(snap, EL_STR(""))) {
engram_save(snap);