diff --git a/awareness.el b/awareness.el index 5b2a02c..c2d0a6c 100644 --- a/awareness.el +++ b/awareness.el @@ -527,9 +527,27 @@ fn awareness_run() -> Void { let scan_ms: Int = beat_ms / 2 while true { + // Arena-scope each tick: awareness_run() is a background loop, not an + // HTTP request, so nothing ever called el_request_start/el_request_end + // for this thread. Per the runtime's own convention (el_runtime.c), + // any thread that never enters a request/arena scope is treated as a + // one-shot CLI program whose allocations are intentionally permanent — + // so every el_strdup/el_strbuf/jb_finish string built during perceive(), + // emit_heartbeat(), and proactive_curiosity() (JSON payloads, search + // results, string concatenation via +) leaked forever, once per tick. + // el_arena_push()/el_arena_pop() are the same builtins the EL compiler + // itself uses to scope allocations per function/statement (see + // codegen.el's fn_arena_mark / stmt_mark usage) — mirroring that here + // reclaims everything allocated in one tick as soon as the tick ends. + // Safe: state_set/state_get persist through a separate global table + // (el_strdup_persist, outside the arena) — state_get's return value is + // only an arena-tracked *copy* of the persisted value, scoped to this + // tick's use, which is exactly what should be reclaimed here. + let tick_mark: Any = el_arena_push() let running: String = state_get("soul.running") if str_eq(running, "false") { println("[awareness] exiting") + el_arena_pop(tick_mark) return "" } let did_work: Bool = one_cycle() @@ -593,6 +611,7 @@ fn awareness_run() -> Void { } sleep_ms(tick_ms) + el_arena_pop(tick_mark) } } diff --git a/awareness.elh b/awareness.elh index eb000d1..58cc269 100644 --- a/awareness.elh +++ b/awareness.elh @@ -7,6 +7,7 @@ extern fn elapsed_ms() -> Int extern fn elapsed_human() -> String extern fn embed_ok() -> Int extern fn emit_heartbeat() -> Void +extern fn auto_term_try_slot(slot_type: String, slot_lbl: String) -> Void extern fn proactive_curiosity() -> Bool extern fn pulse_count() -> Int extern fn pulse_inc() -> Int diff --git a/chat.elh b/chat.elh index 083a968..cfaa53a 100644 --- a/chat.elh +++ b/chat.elh @@ -17,7 +17,9 @@ extern fn id_in_seen(node_id: String, seen: String) -> Bool extern fn add_to_seen(seen: String, node_id: String) -> String extern fn engram_extract_ids(nodes_json: String) -> String extern fn engram_compile(intent: String) -> String +extern fn distill_transcript(transcript: String) -> String extern fn json_safe(s: String) -> String +extern fn current_engine_note(model: String) -> String extern fn build_system_prompt(ctx: String, chat_mode: Bool) -> String extern fn hist_append(hist: String, role: String, content: String) -> String extern fn hist_trim(hist: String) -> String @@ -30,6 +32,10 @@ extern fn handle_chat(body: String) -> String extern fn handle_see(body: String) -> String extern fn studio_tools_json() -> String extern fn agentic_api_key() -> String +extern fn llm_base_url() -> String +extern fn llm_wire_format() -> String +extern fn json_escape(s: String) -> String +extern fn openai_chat_complete(model: String, base_url: String, api_key: String, safe_sys: String, messages_json: String) -> String extern fn agentic_tools_literal() -> String extern fn agentic_tools_with_web() -> String extern fn connector_tools_json() -> String diff --git a/dist/soul.c b/dist/soul.c index 2db31cc..0d67f3d 100644 --- a/dist/soul.c +++ b/dist/soul.c @@ -26214,9 +26214,17 @@ el_val_t awareness_run(void) { el_val_t beat_ms = ({ el_val_t _if_result_103 = 0; if (str_eq(beat_ms_raw, EL_STR(""))) { _if_result_103 = (60000); } else { _if_result_103 = (str_to_int(beat_ms_raw)); } _if_result_103; }); el_val_t scan_ms = (beat_ms / 2); while (1) { + /* Arena-scope each tick — see awareness.el's el_arena_push/el_arena_pop + * around this loop body for the rationale (hand-patched translation of + * that source change; el_runtime.c has no existing generated-code + * precedent for these two builtins, only the compiler's own internal + * usage — mirrors this function's standard zero-arg/one-arg native call + * codegen pattern, e.g. state_get()/ise_post() below). */ + el_val_t tick_mark = el_arena_push(); el_val_t running = state_get(EL_STR("soul.running")); if (str_eq(running, EL_STR("false"))) { println(EL_STR("[awareness] exiting")); + el_arena_pop(tick_mark); return EL_STR(""); } el_val_t did_work = one_cycle(); @@ -26264,6 +26272,7 @@ el_val_t awareness_run(void) { state_set(EL_STR("soul.last_refresh_ts"), int_to_str(now_ts)); } sleep_ms(tick_ms); + el_arena_pop(tick_mark); } return 0; } diff --git a/elp-input.elh b/elp-input.elh index 96422fa..8c1531f 100644 --- a/elp-input.elh +++ b/elp-input.elh @@ -1,4 +1,4 @@ -// auto-generated by elc --emit-header - do not edit +// auto-generated by elc --emit-header — do not edit extern fn elp_extract_topic(msg: String) -> String extern fn elp_detect_predicate(msg: String) -> String extern fn elp_parse(msg: String) -> String diff --git a/memory.elh b/memory.elh index 4f665a2..607cdf7 100644 --- a/memory.elh +++ b/memory.elh @@ -1,4 +1,4 @@ -// auto-generated by elc --emit-header - do not edit +// auto-generated by elc --emit-header — do not edit extern fn tier_working() -> String extern fn tier_episodic() -> String extern fn tier_canonical() -> String diff --git a/sessions.elh b/sessions.elh index 3c2d136..8bd8d0c 100644 --- a/sessions.elh +++ b/sessions.elh @@ -8,6 +8,7 @@ extern fn session_list() -> String extern fn session_get(session_id: String) -> String extern fn session_delete(session_id: String) -> String extern fn session_update_patch(session_id: String, body: String) -> String +extern fn session_search_entry(node: String) -> String extern fn session_search(query: String) -> String extern fn session_hist_load(session_id: String) -> String extern fn session_hist_save(session_id: String, hist: String) -> Void diff --git a/stewardship.elh b/stewardship.elh index 4198268..9caf947 100644 --- a/stewardship.elh +++ b/stewardship.elh @@ -1,15 +1,11 @@ -// stewardship.elh — Layer 2 public surface // auto-generated by elc --emit-header — do not edit +extern fn steward_log_event(kind: String, detail: String) -> Void extern fn steward_get_mission() -> String extern fn steward_align(input: String, imprint_id: String) -> String extern fn steward_validate_imprint(imprint_id: String, tool_name: String) -> String extern fn steward_cgi_check(action: String) -> String -// steward_log_event is an internal helper exported here because El has no access modifiers. -// External callers have no business invoking this directly — use steward_align, -// steward_validate_imprint, or steward_cgi_check, which call it at the correct points. -extern fn steward_log_event(kind: String, detail: String) -> Void -// Behavioral profiling and continuity detection (Layer 2 — session fingerprinting). extern fn steward_fingerprint_session(input: String, session_id: String) -> String +extern fn extract_dim(content: String, key: String) -> String extern fn steward_build_baseline() -> String extern fn steward_check_continuity(current_fingerprint: String, session_id: String) -> String extern fn steward_session_check(input: String, session_id: String) -> String diff --git a/studio.elh b/studio.elh index fdea29a..a0e17d3 100644 --- a/studio.elh +++ b/studio.elh @@ -1,4 +1,4 @@ -// auto-generated by elc --emit-header - do not edit +// auto-generated by elc --emit-header — do not edit extern fn auth_headers(tok: String) -> Map extern fn axon_get(path: String) -> String extern fn axon_post(path: String, body: String) -> String