self-review 2026-07-24: boot counter — demote to telemetry weight, restore persistence via HTTP write-back
Three stale soul:boot_count copies (salience .9, importance .9, Canonical: +0.2 tier bias, 0.15 threshold) held the top WM slots for 23h — a boot counter outcompeting real context. Demoted to salience .55 / importance .2 / tier Working: plumbing, not memory. Persistence was also broken: in HTTP-engram mode the server owns state and nothing wrote the counter back — the log shows boot #5 on three consecutive boots. mem_boot_count_inc now mirrors the persona write-back: delete stale server copies (matched by content prefix — route_create_node sets label=content), create the replacement server-side. Working tier is in the boot seed (/api/nodes) but excluded from periodic /api/sync, so the count survives restarts without re-importing mid-session. Verified: restart incremented 1->2 with exactly one server-side counter node.
This commit is contained in:
+18
-1
@@ -236,7 +236,24 @@ fn auto_term_try_slot(slot_type: String, slot_lbl: String) -> Void {
|
|||||||
if !str_eq(slot_lbl, "") {
|
if !str_eq(slot_lbl, "") {
|
||||||
let sp: Int = str_find_chars(slot_lbl, " :([")
|
let sp: Int = str_find_chars(slot_lbl, " :([")
|
||||||
if sp > 3 {
|
if sp > 3 {
|
||||||
state_set("cseed_auto", str_slice(slot_lbl, 0, sp))
|
// GENRE-WORD BLOCKLIST (2026-07-23 self-review): world-ingestor
|
||||||
|
// titles open with classifier prefixes ("Method paper ...",
|
||||||
|
// "Theory paper ..."), so the first word is a genre tag, not a
|
||||||
|
// topic. Verified live: every scan after Knowledge admission
|
||||||
|
// seeded on 'Method'. Skip these; a lower-WM slot with a
|
||||||
|
// topical first word wins instead.
|
||||||
|
let term: String = str_slice(slot_lbl, 0, sp)
|
||||||
|
state_set("_ats_gw", "0")
|
||||||
|
if str_eq(term, "Method") { state_set("_ats_gw", "1") }
|
||||||
|
if str_eq(term, "Theory") { state_set("_ats_gw", "1") }
|
||||||
|
if str_eq(term, "Finding") { state_set("_ats_gw", "1") }
|
||||||
|
if str_eq(term, "Survey") { state_set("_ats_gw", "1") }
|
||||||
|
if str_eq(term, "Paper") { state_set("_ats_gw", "1") }
|
||||||
|
if str_eq(term, "Knowledge") { state_set("_ats_gw", "1") }
|
||||||
|
if str_eq(term, "Value") { state_set("_ats_gw", "1") }
|
||||||
|
if str_eq(state_get("_ats_gw"), "0") {
|
||||||
|
state_set("cseed_auto", term)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-1
@@ -188,7 +188,32 @@ el_val_t auto_term_try_slot(el_val_t slot_type, el_val_t slot_lbl) {
|
|||||||
if (!str_eq(slot_lbl, EL_STR(""))) {
|
if (!str_eq(slot_lbl, EL_STR(""))) {
|
||||||
el_val_t sp = str_find_chars(slot_lbl, EL_STR(" :(["));
|
el_val_t sp = str_find_chars(slot_lbl, EL_STR(" :(["));
|
||||||
if (sp > 3) {
|
if (sp > 3) {
|
||||||
state_set(EL_STR("cseed_auto"), str_slice(slot_lbl, 0, sp));
|
el_val_t term = str_slice(slot_lbl, 0, sp);
|
||||||
|
state_set(EL_STR("_ats_gw"), EL_STR("0"));
|
||||||
|
if (str_eq(term, EL_STR("Method"))) {
|
||||||
|
state_set(EL_STR("_ats_gw"), EL_STR("1"));
|
||||||
|
}
|
||||||
|
if (str_eq(term, EL_STR("Theory"))) {
|
||||||
|
state_set(EL_STR("_ats_gw"), EL_STR("1"));
|
||||||
|
}
|
||||||
|
if (str_eq(term, EL_STR("Finding"))) {
|
||||||
|
state_set(EL_STR("_ats_gw"), EL_STR("1"));
|
||||||
|
}
|
||||||
|
if (str_eq(term, EL_STR("Survey"))) {
|
||||||
|
state_set(EL_STR("_ats_gw"), EL_STR("1"));
|
||||||
|
}
|
||||||
|
if (str_eq(term, EL_STR("Paper"))) {
|
||||||
|
state_set(EL_STR("_ats_gw"), EL_STR("1"));
|
||||||
|
}
|
||||||
|
if (str_eq(term, EL_STR("Knowledge"))) {
|
||||||
|
state_set(EL_STR("_ats_gw"), EL_STR("1"));
|
||||||
|
}
|
||||||
|
if (str_eq(term, EL_STR("Value"))) {
|
||||||
|
state_set(EL_STR("_ats_gw"), EL_STR("1"));
|
||||||
|
}
|
||||||
|
if (str_eq(state_get(EL_STR("_ats_gw")), EL_STR("0"))) {
|
||||||
|
state_set(EL_STR("cseed_auto"), term);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-1
@@ -169,7 +169,7 @@ el_val_t mem_boot_count_inc(void) {
|
|||||||
}
|
}
|
||||||
el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next));
|
el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next));
|
||||||
el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]");
|
el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]");
|
||||||
el_val_t boot_node_id = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(0.9), el_from_float(0.9), el_from_float(1.0), EL_STR("Canonical"), tags);
|
el_val_t boot_node_id = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(0.55), el_from_float(0.2), el_from_float(1.0), EL_STR("Working"), tags);
|
||||||
if (str_eq(boot_node_id, EL_STR(""))) {
|
if (str_eq(boot_node_id, EL_STR(""))) {
|
||||||
println(el_str_concat(el_str_concat(EL_STR("[memory] mem_boot_count_inc: write rejected (empty id) \xe2\x80\x94 boot counter node lost (count="), int_to_str(next)), EL_STR(")")));
|
println(el_str_concat(el_str_concat(EL_STR("[memory] mem_boot_count_inc: write rejected (empty id) \xe2\x80\x94 boot counter node lost (count="), int_to_str(next)), EL_STR(")")));
|
||||||
return next;
|
return next;
|
||||||
@@ -178,6 +178,32 @@ el_val_t mem_boot_count_inc(void) {
|
|||||||
if (str_eq(boot_readback, EL_STR("")) || str_eq(boot_readback, EL_STR("{}"))) {
|
if (str_eq(boot_readback, EL_STR("")) || str_eq(boot_readback, EL_STR("{}"))) {
|
||||||
println(el_str_concat(el_str_concat(el_str_concat(EL_STR("[memory] mem_boot_count_inc: WRITE VERIFY FAILED id="), boot_node_id), EL_STR(" count=")), int_to_str(next)));
|
println(el_str_concat(el_str_concat(el_str_concat(EL_STR("[memory] mem_boot_count_inc: WRITE VERIFY FAILED id="), boot_node_id), EL_STR(" count=")), int_to_str(next)));
|
||||||
}
|
}
|
||||||
|
el_val_t wb_url = env(EL_STR("ENGRAM_URL"));
|
||||||
|
el_val_t wb_key = env(EL_STR("ENGRAM_API_KEY"));
|
||||||
|
if (!str_eq(wb_url, EL_STR("")) && !str_eq(wb_key, EL_STR(""))) {
|
||||||
|
el_val_t auth_body = el_str_concat(el_str_concat(EL_STR("{\"_auth\":\""), json_safe(wb_key)), EL_STR("\"}"));
|
||||||
|
el_val_t srv_old = http_get(el_str_concat(wb_url, EL_STR("/api/search?q=soul:boot_count&limit=20")));
|
||||||
|
if (!str_eq(srv_old, EL_STR("")) && !str_eq(srv_old, EL_STR("[]"))) {
|
||||||
|
el_val_t srv_len = json_array_len(srv_old);
|
||||||
|
el_val_t si = 0;
|
||||||
|
while (si < srv_len) {
|
||||||
|
el_val_t srv_node = json_array_get(srv_old, si);
|
||||||
|
el_val_t srv_content = json_get(srv_node, EL_STR("content"));
|
||||||
|
if (str_starts_with(srv_content, EL_STR("soul:boot_count:"))) {
|
||||||
|
el_val_t srv_id = json_get(srv_node, EL_STR("id"));
|
||||||
|
if (!str_eq(srv_id, EL_STR(""))) {
|
||||||
|
http_delete_json(el_str_concat(el_str_concat(wb_url, EL_STR("/api/nodes/")), srv_id), auth_body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
si = (si + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
el_val_t wb_body = el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"content\":\""), content), EL_STR("\",\"node_type\":\"Memory\",\"label\":\"soul:boot_count\",\"salience\":0.55,\"importance\":0.2,\"tier\":\"Working\",\"tags\":\"[\\\"soul-meta\\\",\\\"boot-counter\\\"]\",\"_auth\":\"")), json_safe(wb_key)), EL_STR("\"}"));
|
||||||
|
el_val_t wb_resp = http_post_json(el_str_concat(wb_url, EL_STR("/api/nodes")), wb_body);
|
||||||
|
if (str_contains(wb_resp, EL_STR("\"error\""))) {
|
||||||
|
println(el_str_concat(EL_STR("[memory] mem_boot_count_inc: HTTP write-back failed (count in-memory only): "), wb_resp));
|
||||||
|
}
|
||||||
|
}
|
||||||
return next;
|
return next;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,10 +188,20 @@ fn mem_boot_count_inc() -> Int {
|
|||||||
}
|
}
|
||||||
let content: String = "soul:boot_count:" + int_to_str(next)
|
let content: String = "soul:boot_count:" + int_to_str(next)
|
||||||
let tags: String = "[\"soul-meta\",\"boot-counter\"]"
|
let tags: String = "[\"soul-meta\",\"boot-counter\"]"
|
||||||
|
// TELEMETRY DEMOTION (2026-07-24 self-review): this counter was written at
|
||||||
|
// salience 0.9 / importance 0.9 / tier Canonical — Canonical gets +0.2
|
||||||
|
// goal bias and the 0.15 promotion threshold, so three stale copies of a
|
||||||
|
// BOOT COUNTER held the top working-memory slots (wm 0.31+) for 23h,
|
||||||
|
// crowding out real context. It is plumbing, not memory. Working tier:
|
||||||
|
// 0.40 threshold, no tier bias, and the /api/sync route excludes
|
||||||
|
// Working-tier nodes — so the counter also stops leaking to the engram
|
||||||
|
// server graph, which is where the duplicate copies accumulated (the
|
||||||
|
// prune below only reaches the soul's local graph). Persistence across
|
||||||
|
// restarts comes from the soul's own snapshot (mem_save), not from sync.
|
||||||
let boot_node_id: String = engram_node_full(
|
let boot_node_id: String = engram_node_full(
|
||||||
content, "Memory", "soul:boot_count",
|
content, "Memory", "soul:boot_count",
|
||||||
el_from_float(0.9), el_from_float(0.9), el_from_float(1.0),
|
el_from_float(0.55), el_from_float(0.2), el_from_float(1.0),
|
||||||
"Canonical", tags
|
"Working", tags
|
||||||
)
|
)
|
||||||
if str_eq(boot_node_id, "") {
|
if str_eq(boot_node_id, "") {
|
||||||
println("[memory] mem_boot_count_inc: write rejected (empty id) — boot counter node lost (count=" + int_to_str(next) + ")")
|
println("[memory] mem_boot_count_inc: write rejected (empty id) — boot counter node lost (count=" + int_to_str(next) + ")")
|
||||||
@@ -201,6 +211,46 @@ fn mem_boot_count_inc() -> Int {
|
|||||||
if str_eq(boot_readback, "") || str_eq(boot_readback, "{}") {
|
if str_eq(boot_readback, "") || str_eq(boot_readback, "{}") {
|
||||||
println("[memory] mem_boot_count_inc: WRITE VERIFY FAILED id=" + boot_node_id + " count=" + int_to_str(next))
|
println("[memory] mem_boot_count_inc: WRITE VERIFY FAILED id=" + boot_node_id + " count=" + int_to_str(next))
|
||||||
}
|
}
|
||||||
|
// HTTP WRITE-BACK (2026-07-24 self-review): in HTTP-engram mode the server
|
||||||
|
// owns persistence and the soul's in-process graph dies with the process —
|
||||||
|
// the local create above is invisible to the next boot. The counter only
|
||||||
|
// ever "persisted" via a long-gone push path, which is why the log shows
|
||||||
|
// boot #5 on three consecutive boots. Mirror the persona write-back
|
||||||
|
// pattern: delete stale server copies (dupes were the 23h WM-pollution
|
||||||
|
// bug), then create the demoted replacement server-side. Boot seeding
|
||||||
|
// reads /api/nodes, which includes Working-tier nodes, so the count
|
||||||
|
// survives restarts; the periodic /api/sync excludes Working tier, so it
|
||||||
|
// never re-imports mid-session. Fail-soft: on any HTTP error the counter
|
||||||
|
// is in-memory-only this session, same as before.
|
||||||
|
let wb_url: String = env("ENGRAM_URL")
|
||||||
|
let wb_key: String = env("ENGRAM_API_KEY")
|
||||||
|
if !str_eq(wb_url, "") && !str_eq(wb_key, "") {
|
||||||
|
let auth_body: String = "{\"_auth\":\"" + json_safe(wb_key) + "\"}"
|
||||||
|
let srv_old: String = http_get(wb_url + "/api/search?q=soul:boot_count&limit=20")
|
||||||
|
if !str_eq(srv_old, "") && !str_eq(srv_old, "[]") {
|
||||||
|
let srv_len: Int = json_array_len(srv_old)
|
||||||
|
let si: Int = 0
|
||||||
|
while si < srv_len {
|
||||||
|
let srv_node: String = json_array_get(srv_old, si)
|
||||||
|
// Match by CONTENT prefix, not label: route_create_node sets
|
||||||
|
// label = content, so server-side counter nodes carry labels
|
||||||
|
// like "soul:boot_count:6". (2026-07-24)
|
||||||
|
let srv_content: String = json_get(srv_node, "content")
|
||||||
|
if str_starts_with(srv_content, "soul:boot_count:") {
|
||||||
|
let srv_id: String = json_get(srv_node, "id")
|
||||||
|
if !str_eq(srv_id, "") {
|
||||||
|
http_delete_json(wb_url + "/api/nodes/" + srv_id, auth_body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let si = si + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let wb_body: String = "{\"content\":\"" + content + "\",\"node_type\":\"Memory\",\"label\":\"soul:boot_count\",\"salience\":0.55,\"importance\":0.2,\"tier\":\"Working\",\"tags\":\"[\\\"soul-meta\\\",\\\"boot-counter\\\"]\",\"_auth\":\"" + json_safe(wb_key) + "\"}"
|
||||||
|
let wb_resp: String = http_post_json(wb_url + "/api/nodes", wb_body)
|
||||||
|
if str_contains(wb_resp, "\"error\"") {
|
||||||
|
println("[memory] mem_boot_count_inc: HTTP write-back failed (count in-memory only): " + wb_resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
return next
|
return next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user