// db.el — Engram storage layer for DHARMA v2. // // All records stored as "Entity" nodes in engram. // The content JSON contains a "_type" field for DHARMA record discrimination. // Content encoding: str_to_bytes(json_string) → JSON int array for engram. // Content decoding: bytes_to_str(json_get(node, "content")) → JSON string. // // Record types (stored in content "_type" field): // principal — Principal records // cgi — CGI records // covenant — Public covenant documents // evaluation — Evaluation records // accumulation — Accumulation layers // drift — Drift events // kindred — Kindred grants // audit — Audit log entries // internal_state — Internal state events fn engram_url() -> String { let u: String = env("ENGRAM_URL") if str_eq(u, "") { return "http://localhost:7750" } return u } fn engram_key() -> String { return env("ENGRAM_KEY") } // ── Node creation ───────────────────────────────────────────────────────────── // put_node stores content_json as bytes in a new engram Entity node. // Returns the engram node UUID on success, "" on error. fn put_node(content_json: String) -> String { let url: String = engram_url() + "/nodes" let key: String = engram_key() let content_bytes: String = str_to_bytes(content_json) let body: String = "{\"node_type\":\"Entity\",\"embedding\":[],\"content\":" + content_bytes + ",\"tier\":\"Semantic\",\"importance\":1.0}" let resp: String = http_post_engram(url, key, body) let node_id: String = json_get(resp, "id") return node_id } // ── Node listing ────────────────────────────────────────────────────────────── fn list_all_nodes() -> String { let url: String = engram_url() + "/nodes/list" return http_get_engram(url, engram_key()) } fn decode_content(node_json: String) -> String { let content_raw: String = json_get(node_json, "content") if str_eq(content_raw, "") { return "" } if str_eq(content_raw, "[]") { return "" } return bytes_to_str(content_raw) } // ── Scan helpers ────────────────────────────────────────────────────────────── // Recursive traversal (El has no while loops). // Filters by content "_type" field, then optionally by content "id" field. fn scan_by_type_and_id(nodes: String, rec_type: String, stable_id: String, idx: Int, total: Int) -> String { if idx >= total { return "" } let node: String = json_array_get(nodes, idx) let content: String = decode_content(node) if str_eq(content, "") { return scan_by_type_and_id(nodes, rec_type, stable_id, idx + 1, total) } let t: String = json_get(content, "_type") if str_eq(t, rec_type) { let cid: String = json_get(content, "id") if str_eq(cid, stable_id) { return content } } return scan_by_type_and_id(nodes, rec_type, stable_id, idx + 1, total) } fn scan_collect_by_type(nodes: String, rec_type: String, idx: Int, total: Int, acc: String, first: Bool) -> String { if idx >= total { return acc + "]" } let node: String = json_array_get(nodes, idx) let content: String = decode_content(node) if str_eq(content, "") { return scan_collect_by_type(nodes, rec_type, idx + 1, total, acc, first) } let t: String = json_get(content, "_type") if str_eq(t, rec_type) { if first { return scan_collect_by_type(nodes, rec_type, idx + 1, total, acc + content, false) } return scan_collect_by_type(nodes, rec_type, idx + 1, total, acc + "," + content, false) } return scan_collect_by_type(nodes, rec_type, idx + 1, total, acc, first) } fn scan_collect_by_type_cgi(nodes: String, rec_type: String, cgi_id: String, idx: Int, total: Int, acc: String, first: Bool) -> String { if idx >= total { return acc + "]" } let node: String = json_array_get(nodes, idx) let content: String = decode_content(node) if str_eq(content, "") { return scan_collect_by_type_cgi(nodes, rec_type, cgi_id, idx + 1, total, acc, first) } let t: String = json_get(content, "_type") if str_eq(t, rec_type) { let c: String = json_get(content, "cgi_id") if str_eq(c, cgi_id) { if first { return scan_collect_by_type_cgi(nodes, rec_type, cgi_id, idx + 1, total, acc + content, false) } return scan_collect_by_type_cgi(nodes, rec_type, cgi_id, idx + 1, total, acc + "," + content, false) } } return scan_collect_by_type_cgi(nodes, rec_type, cgi_id, idx + 1, total, acc, first) } fn scan_get_engram_id(nodes: String, rec_type: String, stable_id: String, idx: Int, total: Int) -> String { if idx >= total { return "" } let node: String = json_array_get(nodes, idx) let content: String = decode_content(node) if str_eq(content, "") { return scan_get_engram_id(nodes, rec_type, stable_id, idx + 1, total) } let t: String = json_get(content, "_type") if str_eq(t, rec_type) { let cid: String = json_get(content, "id") if str_eq(cid, stable_id) { return json_get(node, "id") } } return scan_get_engram_id(nodes, rec_type, stable_id, idx + 1, total) } // ── Public DB API ───────────────────────────────────────────────────────────── fn db_find(rec_type: String, stable_id: String) -> String { let nodes: String = list_all_nodes() let total: Int = json_array_len(nodes) return scan_by_type_and_id(nodes, rec_type, stable_id, 0, total) } fn db_find_all(rec_type: String) -> String { let nodes: String = list_all_nodes() let total: Int = json_array_len(nodes) return scan_collect_by_type(nodes, rec_type, 0, total, "[", true) } fn db_find_all_for_cgi(rec_type: String, cgi_id: String) -> String { let nodes: String = list_all_nodes() let total: Int = json_array_len(nodes) return scan_collect_by_type_cgi(nodes, rec_type, cgi_id, 0, total, "[", true) } // db_exists returns "true" or "false" (String to avoid ! operator issues) fn db_exists(rec_type: String, stable_id: String) -> String { let found: String = db_find(rec_type, stable_id) if str_eq(found, "") { return "false" } return "true" } fn db_engram_id(rec_type: String, stable_id: String) -> String { let nodes: String = list_all_nodes() let total: Int = json_array_len(nodes) return scan_get_engram_id(nodes, rec_type, stable_id, 0, total) } // ── Typed record operations ─────────────────────────────────────────────────── fn create_principal(content_json: String) -> String { return put_node(content_json) } fn get_principal(id: String) -> String { return db_find("principal", id) } fn create_cgi(content_json: String) -> String { return put_node(content_json) } fn get_cgi(id: String) -> String { return db_find("cgi", id) } // Alias for backward compat with handlers.el fn create_cgi_node(content_json: String, principal_id: String) -> String { return put_node(content_json) } fn create_covenant(content_json: String) -> String { return put_node(content_json) } fn get_covenant(cgi_id: String) -> String { let all: String = db_find_all_for_cgi("covenant", cgi_id) let n: Int = json_array_len(all) if n == 0 { return "" } return json_array_get(all, 0) } fn create_evaluation(content_json: String) -> String { return put_node(content_json) } fn get_evaluation(id: String) -> String { return db_find("evaluation", id) } fn get_evaluation_for_cgi(cgi_id: String) -> String { let all: String = db_find_all_for_cgi("evaluation", cgi_id) let n: Int = json_array_len(all) if n == 0 { return "" } return json_array_get(all, n - 1) } // Alias fn get_evaluation_by_cgi(cgi_id: String) -> String { return get_evaluation_for_cgi(cgi_id) } fn create_accumulation(content_json: String) -> String { return put_node(content_json) } fn list_accumulations(cgi_id: String) -> String { return db_find_all_for_cgi("accumulation", cgi_id) } fn max_accum_ver_inner(all: String, idx: Int, total: Int, cur_max: Int) -> Int { if idx >= total { return cur_max } let item: String = json_array_get(all, idx) let v: Int = json_get_int(item, "version") if v > cur_max { return max_accum_ver_inner(all, idx + 1, total, v) } return max_accum_ver_inner(all, idx + 1, total, cur_max) } fn max_accumulation_version(cgi_id: String) -> Int { let all: String = list_accumulations(cgi_id) let total: Int = json_array_len(all) return max_accum_ver_inner(all, 0, total, 0) } fn create_drift(content_json: String) -> String { return put_node(content_json) } fn list_drifts(cgi_id: String) -> String { return db_find_all_for_cgi("drift", cgi_id) } fn get_drift(id: String) -> String { return db_find("drift", id) } // Alias fn get_drift_by_id(drift_id: String) -> String { return get_drift(drift_id) } fn create_kindred(content_json: String) -> String { return put_node(content_json) } fn scan_kindred_inner(all: String, grantor_id: String, idx: Int, total: Int, acc: String, first: Bool) -> String { if idx >= total { return acc + "]" } let item: String = json_array_get(all, idx) let gid: String = json_get(item, "grantor_cgi_id") if str_eq(gid, grantor_id) { if first { return scan_kindred_inner(all, grantor_id, idx + 1, total, acc + item, false) } return scan_kindred_inner(all, grantor_id, idx + 1, total, acc + "," + item, false) } return scan_kindred_inner(all, grantor_id, idx + 1, total, acc, first) } fn list_kindred_by_grantor(grantor_id: String) -> String { let all: String = db_find_all("kindred") let total: Int = json_array_len(all) return scan_kindred_inner(all, grantor_id, 0, total, "[", true) } fn create_audit(content_json: String) -> String { return put_node(content_json) } fn scan_audit_by_hash(all: String, hash: String, idx: Int, total: Int, acc: String, first: Bool) -> String { if idx >= total { return acc + "]" } let item: String = json_array_get(all, idx) let ih: String = json_get(item, "identity_hash") if str_eq(ih, hash) { if first { return scan_audit_by_hash(all, hash, idx + 1, total, acc + item, false) } return scan_audit_by_hash(all, hash, idx + 1, total, acc + "," + item, false) } return scan_audit_by_hash(all, hash, idx + 1, total, acc, first) } fn list_audits(identity_hash: String) -> String { let all: String = db_find_all("audit") if str_eq(identity_hash, "") { return all } let total: Int = json_array_len(all) return scan_audit_by_hash(all, identity_hash, 0, total, "[", true) } fn create_internal_state(content_json: String) -> String { return put_node(content_json) } fn list_internal_state(cgi_id: String) -> String { if str_eq(cgi_id, "") { return db_find_all("internal_state") } return db_find_all_for_cgi("internal_state", cgi_id) }