diff --git a/awareness.el b/awareness.el index 2508549..ce947ea 100644 --- a/awareness.el +++ b/awareness.el @@ -92,10 +92,16 @@ fn emit_heartbeat() -> Void { ise_post(payload) } -// proactive_curiosity — activate a rotating seed to exercise working memory -// during idle periods. Rotates through 4 domain seeds on a wall-clock minute +// proactive_curiosity — activate rotating seeds to exercise working memory +// during idle periods. Rotates through 4 domain sets on a wall-clock minute // cycle so no single topic dominates WM between heartbeats. // +// KEY DESIGN: each seed set is split into INDIVIDUAL words and activated +// separately. engram_activate uses istr_contains (substring matching) for +// seed finding, so a multi-word phrase like "memory knowledge context" only +// finds nodes that contain that EXACT phrase. Activating each word separately +// hits hundreds of nodes per word, giving the graph a genuine WM workout. +// // Unlike perceive(), this intentionally calls engram_activate_json to build // up WM weights. It only fires when the inbox is empty (no real work to do), // so it never interferes with inbox processing. @@ -103,7 +109,7 @@ fn emit_heartbeat() -> Void { // Returns true if any nodes were activated. fn proactive_curiosity() -> Bool { let ts: Int = time_now() - // Rotate seed every minute using wall clock: (minutes_since_epoch) % 4. + // Rotate seed set every minute using wall clock: (minutes_since_epoch) % 4. // IMPORTANT: use imperative let-rebinding, NOT inline if-else string // expressions. EL codegen initialises the result slot to 0 (null) before // evaluating the if, so string-literal if-else branches can produce an @@ -112,12 +118,35 @@ fn proactive_curiosity() -> Bool { // NOTE: variable named "curiosity_seed" not "seed" — "seed" appears to be // a reserved/conflicting name in EL that compiles to EL_NULL at call sites. let minute_block: Int = (ts / 60000) % 4 - let curiosity_seed: String = "memory knowledge context" - if minute_block == 1 { let curiosity_seed = "self identity values architecture" } - if minute_block == 2 { let curiosity_seed = "recent decision pattern lesson" } - if minute_block == 3 { let curiosity_seed = "working active project" } - let results: String = engram_activate_json(curiosity_seed, 2) - let found: Int = json_array_len(results) + + // Each slot: 3 individual terms to activate separately. + let curiosity_term_a: String = "memory" + let curiosity_term_b: String = "knowledge" + let curiosity_term_c: String = "context" + if minute_block == 1 { + let curiosity_term_a = "self" + let curiosity_term_b = "identity" + let curiosity_term_c = "values" + } + if minute_block == 2 { + let curiosity_term_a = "decision" + let curiosity_term_b = "pattern" + let curiosity_term_c = "lesson" + } + if minute_block == 3 { + let curiosity_term_a = "working" + let curiosity_term_b = "project" + let curiosity_term_c = "active" + } + // Activate each term independently so substring seed-finding hits many nodes. + let curiosity_seed: String = curiosity_term_a + " " + curiosity_term_b + " " + curiosity_term_c + let results_a: String = engram_activate_json(curiosity_term_a, 2) + let results_b: String = engram_activate_json(curiosity_term_b, 2) + let results_c: String = engram_activate_json(curiosity_term_c, 2) + let found_a: Int = json_array_len(results_a) + let found_b: Int = json_array_len(results_b) + let found_c: Int = json_array_len(results_c) + let found: Int = found_a + found_b + found_c let wmc: Int = engram_wm_count() let ise: String = "{\"event\":\"curiosity_scan\",\"seed\":\"" + curiosity_seed + "\",\"activated\":" + int_to_str(found) diff --git a/dist/awareness.c b/dist/awareness.c index 28a8a07..cedf1ce 100644 --- a/dist/awareness.c +++ b/dist/awareness.c @@ -133,18 +133,32 @@ el_val_t emit_heartbeat(void) { el_val_t proactive_curiosity(void) { el_val_t ts = time_now(); el_val_t minute_block = ((ts / 60000) % 4); - el_val_t curiosity_seed = EL_STR("memory knowledge context"); + el_val_t curiosity_term_a = EL_STR("memory"); + el_val_t curiosity_term_b = EL_STR("knowledge"); + el_val_t curiosity_term_c = EL_STR("context"); if (minute_block == 1) { - curiosity_seed = EL_STR("self identity values architecture"); + curiosity_term_a = EL_STR("self"); + curiosity_term_b = EL_STR("identity"); + curiosity_term_c = EL_STR("values"); } if (minute_block == 2) { - curiosity_seed = EL_STR("recent decision pattern lesson"); + curiosity_term_a = EL_STR("decision"); + curiosity_term_b = EL_STR("pattern"); + curiosity_term_c = EL_STR("lesson"); } if (minute_block == 3) { - curiosity_seed = EL_STR("working active project"); + curiosity_term_a = EL_STR("working"); + curiosity_term_b = EL_STR("project"); + curiosity_term_c = EL_STR("active"); } - el_val_t results = engram_activate_json(curiosity_seed, 2); - el_val_t found = json_array_len(results); + el_val_t curiosity_seed = el_str_concat(el_str_concat(el_str_concat(el_str_concat(curiosity_term_a, EL_STR(" ")), curiosity_term_b), EL_STR(" ")), curiosity_term_c); + el_val_t results_a = engram_activate_json(curiosity_term_a, 2); + el_val_t results_b = engram_activate_json(curiosity_term_b, 2); + el_val_t results_c = engram_activate_json(curiosity_term_c, 2); + el_val_t found_a = json_array_len(results_a); + el_val_t found_b = json_array_len(results_b); + el_val_t found_c = json_array_len(results_c); + el_val_t found = ((found_a + found_b) + found_c); el_val_t wmc = engram_wm_count(); el_val_t ise = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"curiosity_scan\",\"seed\":\""), curiosity_seed), EL_STR("\",\"activated\":")), int_to_str(found)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}")); ise_post(ise); diff --git a/dist/neuron b/dist/neuron index d48e411..6a26e9c 100755 Binary files a/dist/neuron and b/dist/neuron differ diff --git a/dist/neuron.c b/dist/neuron.c index 34b8091..00ee781 100644 --- a/dist/neuron.c +++ b/dist/neuron.c @@ -352,7 +352,12 @@ int main(int _argc, char** _argv) { } } println(el_str_concat(EL_STR("[soul] serving on port "), int_to_str(port))); - http_serve(port, EL_STR("handle_request")); + /* Use http_serve_async (non-blocking) so awareness_run() executes on the main + * thread. http_serve would block here forever, making awareness_run unreachable. + * http_serve_async spawns the accept loop in a background pthread and returns + * immediately. awareness_run() then runs the idle-activation heartbeat loop. + * Self-review fix 2026-05-21. */ + http_serve_async(port, EL_STR("handle_request")); println(EL_STR("[soul] awareness loop starting")); awareness_run(); return 0;