Merge pull request 'soul: the engram is the canonical store, not a fallback' (#162) from fix/engram-is-canonical into main
Neuron Soul CI / build (push) Failing after 12m31s
Neuron Soul CI / deploy (push) Failing after 14m31s

This commit was merged in pull request #162.
This commit is contained in:
2026-08-16 02:16:56 +00:00
+43 -13
View File
@@ -584,17 +584,35 @@ println("[soul] boot - cgi=" + soul_cgi_id + " port=" + int_to_str(port))
let using_http_engram: Bool = !str_eq(engram_url_raw, "") let using_http_engram: Bool = !str_eq(engram_url_raw, "")
// Always try local snapshot first. If it has content (>50 nodes) it was // THE ENGRAM IS THE CANONICAL STORE. The soul's resident graph is a working
// previously seeded from HTTP Engram and is kept up-to-date by the awareness // copy of it, never a rival source of truth.
// loop use it. This preserves sessions and memories across restarts. //
// HTTP Engram is only used for the very first boot (empty/absent snapshot). // This used to be inverted: "always try local snapshot first... HTTP Engram is
engram_load(snapshot) // only used for the very first boot." The copy outranked the store. Everything
let local_node_count: Int = engram_node_count() // that followed is a cost of that one inversion:
let snapshot_usable: Bool = local_node_count > 50 // - the two graphs drifted (13,479 nodes/74,563 edges in the soul vs
// 13,425/37,658 in the engram nearly 2x the edges, silently)
if using_http_engram && !snapshot_usable { // - write-through exists solely to reconcile them, and had never once run
// First boot or empty/corrupt snapshot: seed from HTTP Engram. // - /api/graph/edges serialized 128 MB to answer a read, because the soul's
println("[soul] engram -> HTTP " + engram_url_raw + " (no local snapshot, first boot)") // copy was not the engram's
// - a read route overwrote the engram's canonical snapshot.json with the
// soul's divergent copy
// - three copies of the same memory: neuron.egm, snapshot.json, soul RAM
// None of those are features. They are all reconciliation debt.
//
// The engram itself already reached this conclusion for its own boot path:
// "the durable owner is the paged store (neuron.egm + neuron.wal) ...
// snapshot.json is never read again as the ongoing store. This closes the
// 'restart reverted to a 17h-old snapshot' data-loss window." The soul kept
// booting the legacy way the engram had already abandoned, and inherited
// exactly the data-loss window that comment describes.
//
// So in HTTP-engram mode the soul seeds from the engram, EVERY boot, and never
// consults or writes a local snapshot. The local file is not read even when
// present a stale copy that outranks the store is the bug, not a fallback.
// (File mode, no ENGRAM_URL, is unchanged: there the soul IS the owner.)
if using_http_engram {
println("[soul] engram -> HTTP " + engram_url_raw + " (canonical store; local snapshot ignored)")
let nodes_json: String = http_get(engram_url_raw + "/api/nodes?limit=10000") let nodes_json: String = http_get(engram_url_raw + "/api/nodes?limit=10000")
let edges_json: String = http_get(engram_url_raw + "/api/edges") let edges_json: String = http_get(engram_url_raw + "/api/edges")
let nodes_part: String = if str_eq(nodes_json, "") { "[]" } else { nodes_json } let nodes_part: String = if str_eq(nodes_json, "") { "[]" } else { nodes_json }
@@ -603,9 +621,21 @@ if using_http_engram && !snapshot_usable {
let tmp_path: String = "/tmp/soul-engram-" + soul_cgi_id + ".json" let tmp_path: String = "/tmp/soul-engram-" + soul_cgi_id + ".json"
fs_write(tmp_path, snapshot_data) fs_write(tmp_path, snapshot_data)
engram_load(tmp_path) engram_load(tmp_path)
println("[soul] loaded from HTTP Engram - nodes=" + int_to_str(engram_node_count()) + " edges=" + int_to_str(engram_edge_count())) let seeded: Int = engram_node_count()
if seeded < 50 {
// Refuse to run blind. An empty seed in HTTP mode means the canonical
// store was unreachable or empty; continuing would let the soul rebuild
// a divergent graph from nothing, which is how the copies split before.
println("[soul] FATAL: engram at " + engram_url_raw + " returned " + int_to_str(seeded)
+ " nodes. The canonical store is unreachable or empty; refusing to boot on a"
+ " local copy. Fix the engram, then restart.")
exit_program(1)
}
println("[soul] loaded from engram - nodes=" + int_to_str(seeded) + " edges=" + int_to_str(engram_edge_count()))
} else { } else {
println("[soul] loaded from local snapshot - nodes=" + int_to_str(local_node_count) + " edges=" + int_to_str(engram_edge_count())) engram_load(snapshot)
println("[soul] file mode (no ENGRAM_URL) - soul owns the store - nodes="
+ int_to_str(engram_node_count()) + " edges=" + int_to_str(engram_edge_count()))
} }
load_identity_context() load_identity_context()