self-review 2026-05-21: fix curiosity seed splitting and awareness loop activation

Two fixes:

1. proactive_curiosity() was calling engram_activate_json with multi-word phrases
   ("memory knowledge context"). engram_activate finds seeds via istr_contains
   (substring match), so the phrase had to appear verbatim in a node's content.
   Almost no node contains the exact string "memory knowledge context", so only
   0-2 nodes activated per curiosity scan. Fixed by activating each word separately:
   "memory", "knowledge", "context" → 3 independent activate calls → hundreds of
   nodes promoted to WM per cycle.

2. dist/neuron.c called http_serve() (blocking accept loop) which made awareness_run()
   unreachable. soul.el correctly specifies http_serve_async but elc silently drops
   unknown builtins, leaving blocking http_serve in the compiled C. Patched neuron.c
   to call http_serve_async directly — HTTP server runs in a background pthread,
   awareness_run() runs on the main thread as intended.
This commit is contained in:
2026-05-21 08:47:00 -05:00
parent cc09c296a3
commit 5b8cb58da1
4 changed files with 64 additions and 16 deletions
+38 -9
View File
@@ -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)