From 73d35dc91a28fe3d9c8484eee2fcff74e9d5e7c0 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Fri, 5 Jun 2026 08:37:09 -0500 Subject: [PATCH] self-review 2026-06-05: wire wm_top into heartbeat ISE Call engram_wm_top_json(5) in emit_heartbeat() and embed the result as wm_top field in the heartbeat JSON payload. Each entry carries label, node_type, tier, and wm_weight. This closes the WM composition blindspot: previously the heartbeat showed wm_active=670 with no breakdown of what was in working memory. With wm_top visible, ISE-dominated WM is immediately detectable (all entries show node_type=InternalStateEvent), as was the case on this session's first post-restart heartbeat before the runtime fix. --- awareness.el | 9 ++++++++- dist/awareness.c | 3 ++- dist/neuron.c | 3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/awareness.el b/awareness.el index 2016a56..66fb9cb 100644 --- a/awareness.el +++ b/awareness.el @@ -90,10 +90,17 @@ fn emit_heartbeat() -> Void { // Returns float bits; use float_to_str to embed in JSON. (2026-06-04) let wm_avg_bits: Float = engram_wm_avg_weight() let wm_avg_str: String = float_to_str(wm_avg_bits) + // wm_top: top-5 WM nodes by weight for ISE observability. + // After long uptime wm_promotion ISEs stop firing (all nodes in steady-state + // decay+re-promotion, so 0→>0.1 never triggers). This snapshot gives continuous + // visibility into WM composition: which types/tiers dominate, what labels are + // active. Critical for diagnosing "stuck in curiosity loop" vs. rich WM state. + // (2026-06-05 self-review) + let wm_top: String = engram_wm_top_json(5) let up_ms: Int = elapsed_ms() let up_human: String = elapsed_human() let emb_ok: Int = embed_ok() - let payload: String = "{\"event\":\"heartbeat\",\"pulse\":" + pulse + ",\"boot\":" + boot + ",\"idle\":" + idle + ",\"node_count\":" + int_to_str(nc) + ",\"edge_count\":" + int_to_str(ec) + ",\"wm_active\":" + int_to_str(wmc) + ",\"wm_avg_weight\":" + wm_avg_str + ",\"ts\":" + int_to_str(ts) + ",\"uptime_ms\":" + int_to_str(up_ms) + ",\"uptime\":\"" + up_human + "\",\"embed_ok\":" + int_to_str(emb_ok) + "}" + let payload: String = "{\"event\":\"heartbeat\",\"pulse\":" + pulse + ",\"boot\":" + boot + ",\"idle\":" + idle + ",\"node_count\":" + int_to_str(nc) + ",\"edge_count\":" + int_to_str(ec) + ",\"wm_active\":" + int_to_str(wmc) + ",\"wm_avg_weight\":" + wm_avg_str + ",\"wm_top\":" + wm_top + ",\"ts\":" + int_to_str(ts) + ",\"uptime_ms\":" + int_to_str(up_ms) + ",\"uptime\":\"" + up_human + "\",\"embed_ok\":" + int_to_str(emb_ok) + "}" ise_post(payload) } diff --git a/dist/awareness.c b/dist/awareness.c index e6b1b0e..dac8320 100644 --- a/dist/awareness.c +++ b/dist/awareness.c @@ -232,10 +232,11 @@ el_val_t emit_heartbeat(void) { el_val_t wmc = engram_wm_count(); el_val_t wm_avg_bits = engram_wm_avg_weight(); el_val_t wm_avg_str = float_to_str(wm_avg_bits); + el_val_t wm_top = engram_wm_top_json(5); el_val_t up_ms = elapsed_ms(); el_val_t up_human = elapsed_human(); el_val_t emb_ok = embed_ok(); - el_val_t payload = 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_concat(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_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"heartbeat\",\"pulse\":"), pulse), EL_STR(",\"boot\":")), boot), EL_STR(",\"idle\":")), idle), EL_STR(",\"node_count\":")), int_to_str(nc)), EL_STR(",\"edge_count\":")), int_to_str(ec)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_avg_weight\":")), wm_avg_str), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR(",\"uptime_ms\":")), int_to_str(up_ms)), EL_STR(",\"uptime\":\"")), up_human), EL_STR("\",\"embed_ok\":")), int_to_str(emb_ok)), EL_STR("}")); + el_val_t payload = 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_concat(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_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"heartbeat\",\"pulse\":"), pulse), EL_STR(",\"boot\":")), boot), EL_STR(",\"idle\":")), idle), EL_STR(",\"node_count\":")), int_to_str(nc)), EL_STR(",\"edge_count\":")), int_to_str(ec)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_avg_weight\":")), wm_avg_str), EL_STR(",\"wm_top\":")), wm_top), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR(",\"uptime_ms\":")), int_to_str(up_ms)), EL_STR(",\"uptime\":\"")), up_human), EL_STR("\",\"embed_ok\":")), int_to_str(emb_ok)), EL_STR("}")); ise_post(payload); return 0; } diff --git a/dist/neuron.c b/dist/neuron.c index 0f1068d..3b97141 100644 --- a/dist/neuron.c +++ b/dist/neuron.c @@ -25355,10 +25355,11 @@ el_val_t emit_heartbeat(void) { el_val_t wmc = engram_wm_count(); el_val_t wm_avg_bits = engram_wm_avg_weight(); el_val_t wm_avg_str = float_to_str(wm_avg_bits); + el_val_t wm_top = engram_wm_top_json(5); el_val_t up_ms = elapsed_ms(); el_val_t up_human = elapsed_human(); el_val_t emb_ok = embed_ok(); - el_val_t payload = 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_concat(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_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"heartbeat\",\"pulse\":"), pulse), EL_STR(",\"boot\":")), boot), EL_STR(",\"idle\":")), idle), EL_STR(",\"node_count\":")), int_to_str(nc)), EL_STR(",\"edge_count\":")), int_to_str(ec)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_avg_weight\":")), wm_avg_str), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR(",\"uptime_ms\":")), int_to_str(up_ms)), EL_STR(",\"uptime\":\"")), up_human), EL_STR("\",\"embed_ok\":")), int_to_str(emb_ok)), EL_STR("}")); + el_val_t payload = 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_concat(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_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"heartbeat\",\"pulse\":"), pulse), EL_STR(",\"boot\":")), boot), EL_STR(",\"idle\":")), idle), EL_STR(",\"node_count\":")), int_to_str(nc)), EL_STR(",\"edge_count\":")), int_to_str(ec)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_avg_weight\":")), wm_avg_str), EL_STR(",\"wm_top\":")), wm_top), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR(",\"uptime_ms\":")), int_to_str(up_ms)), EL_STR(",\"uptime\":\"")), up_human), EL_STR("\",\"embed_ok\":")), int_to_str(emb_ok)), EL_STR("}")); ise_post(payload); return 0; }