|
|
|
@@ -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, "")
|
|
|
|
|
|
|
|
|
|
// Always try local snapshot first. If it has content (>50 nodes) it was
|
|
|
|
|
// previously seeded from HTTP Engram and is kept up-to-date by the awareness
|
|
|
|
|
// loop — use it. This preserves sessions and memories across restarts.
|
|
|
|
|
// HTTP Engram is only used for the very first boot (empty/absent snapshot).
|
|
|
|
|
engram_load(snapshot)
|
|
|
|
|
let local_node_count: Int = engram_node_count()
|
|
|
|
|
let snapshot_usable: Bool = local_node_count > 50
|
|
|
|
|
|
|
|
|
|
if using_http_engram && !snapshot_usable {
|
|
|
|
|
// First boot or empty/corrupt snapshot: seed from HTTP Engram.
|
|
|
|
|
println("[soul] engram -> HTTP " + engram_url_raw + " (no local snapshot, first boot)")
|
|
|
|
|
// THE ENGRAM IS THE CANONICAL STORE. The soul's resident graph is a working
|
|
|
|
|
// copy of it, never a rival source of truth.
|
|
|
|
|
//
|
|
|
|
|
// This used to be inverted: "always try local snapshot first... HTTP Engram is
|
|
|
|
|
// only used for the very first boot." The copy outranked the store. Everything
|
|
|
|
|
// that followed is a cost of that one inversion:
|
|
|
|
|
// - 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)
|
|
|
|
|
// - write-through exists solely to reconcile them, and had never once run
|
|
|
|
|
// - /api/graph/edges serialized 128 MB to answer a read, because the soul's
|
|
|
|
|
// 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 edges_json: String = http_get(engram_url_raw + "/api/edges")
|
|
|
|
|
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"
|
|
|
|
|
fs_write(tmp_path, snapshot_data)
|
|
|
|
|
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 {
|
|
|
|
|
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()
|
|
|
|
|