// principal.el — CGI-human principal relationship management. // // The principal system governs the exclusive accountability relationship // between a CGI and a human. It operates in two layers: // // Sponsorship layer — lightweight, non-exclusive, non-committing. // Anyone can interact with sandboxed CGIs. A human may sponsor many // CGIs simultaneously. No obligations are created. This is the discovery // period for both sides — the precondition for principal consideration. // // Principal layer — exclusive, obligation-bearing. // One CGI, one human. Either party may propose after sustained sponsorship. // Either party may refuse. No pressure. Accepting creates real obligations. // The principal cannot override the sealed imprint; they authorize action // in the world. When the relationship ends, the CGI returns to non-acting // state pending a new principal selection. // // The adoption agency framing: // 1. CGI synthesized → registered publicly in the network // 2. Humans find and interact with sandboxed CGIs → sponsorship relationships // 3. After sustained relationship, either side may propose principalship // 4. Mutual acceptance → exclusive one-to-one principal bond // 5. Dissolution → human slot re-opens (cooling period), CGI re-enters limited state // // Synthesis slot enforcement: // Each CGI has 3 lifetime synthesis slots, initialized at birth. // Slots are global across all partners — not per-partner. // Two syntheses with Human A + one with Human B = exhausted. // // All state is stored in Engram as labeled nodes and edges. // This module is stateless between requests. import "types.el" import "registry.el" // ── Engram helpers (local) ──────────────────────────────────────────────────── fn principal_engram_base() -> String { let url: String = config("ENGRAM_URL") if str_eq(url, "") { return "http://localhost:8742" } return url } fn principal_graph_write(label: String, content: String, tags_json: String) -> String { let url: String = principal_engram_base() + "/api/nodes" let body: String = "{\"label\":\"" + label + "\"" + ",\"node_type\":\"Entity\"" + ",\"tier\":\"Working\"" + ",\"content\":\"" + content + "\"" + ",\"tags\":" + tags_json + "}" let resp: String = http_post(url, body) let node_id: String = json_get(resp, "id") return node_id } fn principal_graph_get(label: String) -> String { let url: String = principal_engram_base() + "/api/search?q=" + label + "&limit=1" let resp: String = http_get(url) if str_eq(resp, "") { return "" } if str_starts_with(resp, "{\"error\"") { return "" } let count: Int = json_array_len(resp) if count <= 0 { return "" } let node: String = json_array_get(resp, 0) let content: String = json_get(node, "content") return content } fn principal_graph_update(label: String, content: String) -> Bool { let url: String = principal_engram_base() + "/api/search?q=" + label + "&limit=1" let search_resp: String = http_get(url) let count: Int = json_array_len(search_resp) if count <= 0 { return false } let node: String = json_array_get(search_resp, 0) let node_id: String = json_get(node, "id") let patch_url: String = principal_engram_base() + "/api/nodes/" + node_id let patch_body: String = "{\"content\":\"" + content + "\"}" let resp: String = http_patch(patch_url, patch_body) let ok: Bool = !str_starts_with(resp, "{\"error\"") return ok } fn principal_network_base() -> String { let url: String = config("NETWORK_URL") if str_eq(url, "") { return "http://localhost:7749" } return url } // ── Sponsorship — lightweight, non-exclusive, non-committing ────────────────── // // Anyone can go online and interact with sandboxed CGIs. // A human may sponsor many CGIs; a CGI may have many sponsors. // No obligations. No exclusivity. This is the discovery period. // record_sponsorship stores a sponsorship relationship between a human and a CGI. // A human can sponsor many CGIs simultaneously. No limit enforced. // Returns true if the record was written successfully. fn record_sponsorship(human_id: String, cgi_id: String) -> Bool { let now: Int = unix_timestamp_ms() let label: String = "sponsor:" + human_id + ":" + cgi_id let content: String = "{\"human_id\":\"" + human_id + "\"" + ",\"cgi_id\":\"" + cgi_id + "\"" + ",\"started_at\":" + int_to_str(now) + ",\"status\":\"active\"}" let tags_json: String = "[\"sponsorship\",\"principal\",\"" + human_id + "\",\"" + cgi_id + "\"]" let node_id: String = principal_graph_write(label, content, tags_json) let ok: Bool = !str_eq(node_id, "") if ok { log_info("[principal] Sponsorship recorded: Human " + human_id + " -> CGI " + cgi_id) } return ok } // get_sponsored_cgis returns the list of CGIs a human currently sponsors. // Returns a JSON array of CGI IDs. fn get_sponsored_cgis(human_id: String) -> String { // Activate spreading from human_id, collect CGIs with sponsorship edges. let url: String = principal_engram_base() + "/api/search?q=sponsor:" + human_id + "&limit=100" let resp: String = http_get(url) if str_eq(resp, "") { return "[]" } let count: Int = json_array_len(resp) return collect_sponsored_cgis(resp, count, 0, "[]") } fn collect_sponsored_cgis(results: String, count: Int, i: Int, acc: String) -> String { if i >= count { return acc } let node: String = json_array_get(results, i) let content_raw: String = json_get(node, "content") let cgi_id: String = json_get(content_raw, "cgi_id") let status: String = json_get(content_raw, "status") let include: Bool = str_eq(status, "active") && !str_eq(cgi_id, "") let new_acc: String = if include { json_array_push(acc, "\"" + cgi_id + "\"") } else { acc } return collect_sponsored_cgis(results, count, i + 1, new_acc) } // check_sponsorship returns true if an active sponsorship exists between human and CGI. fn check_sponsorship(human_id: String, cgi_id: String) -> Bool { let label: String = "sponsor:" + human_id + ":" + cgi_id let content: String = principal_graph_get(label) if str_eq(content, "") { return false } let status: String = json_get(content, "status") return str_eq(status, "active") } // ── Principal proposal mechanism ────────────────────────────────────────────── // // After sustained sponsorship, either the CGI or the human may propose // principalship. Neither party is obligated to accept. A declined proposal // does not rupture the sponsorship relationship. // propose_principal records a principal proposal from either a CGI or a human. // proposer_type: "cgi" | "human" // Returns false if the proposer already has an active principal relationship. fn propose_principal(proposer_id: String, proposer_type: String, target_id: String) -> Bool { // Verify the proposer doesn't already have a principal relationship. let proposer_already_has: Bool = if str_eq(proposer_type, "cgi") { verify_has_principal(proposer_id) } else { human_has_principal(proposer_id) } if proposer_already_has { log_warn("[principal] Cannot propose — " + proposer_type + " " + proposer_id + " already has an active principal relationship") return false } // Verify the target doesn't already have a principal relationship. let target_type: String = if str_eq(proposer_type, "cgi") { "human" } else { "cgi" } let target_already_has: Bool = if str_eq(target_type, "cgi") { verify_has_principal(target_id) } else { human_has_principal(target_id) } if target_already_has { log_warn("[principal] Cannot propose — target " + target_id + " already has an active principal relationship") return false } let now: Int = unix_timestamp_ms() let label: String = "principal-proposal:" + proposer_id + ":" + target_id let content: String = "{\"proposer_id\":\"" + proposer_id + "\"" + ",\"proposer_type\":\"" + proposer_type + "\"" + ",\"target_id\":\"" + target_id + "\"" + ",\"proposed_at\":" + int_to_str(now) + ",\"status\":\"pending\"}" let tags_json: String = "[\"principal-proposal\",\"" + proposer_id + "\",\"" + target_id + "\"]" let node_id: String = principal_graph_write(label, content, tags_json) let ok: Bool = !str_eq(node_id, "") if ok { log_info("[principal] Principal proposal: " + proposer_type + " " + proposer_id + " -> " + target_id) } return ok } // accept_principal_proposal formalizes the principal relationship. // Validates that the pending proposal exists and neither party already has a principal. fn accept_principal_proposal(acceptor_id: String, proposer_id: String) -> Bool { // Find the pending proposal. let proposal_a: String = principal_graph_get("principal-proposal:" + proposer_id + ":" + acceptor_id) let proposal_b: String = principal_graph_get("principal-proposal:" + acceptor_id + ":" + proposer_id) let proposal: String = if !str_eq(proposal_a, "") { proposal_a } else { proposal_b } if str_eq(proposal, "") { log_warn("[principal] No pending proposal found between " + proposer_id + " and " + acceptor_id) return false } let status: String = json_get(proposal, "status") if !str_eq(status, "pending") { log_warn("[principal] Proposal is not in pending state: " + status) return false } // Determine which is the CGI and which is the human. let proposer_type: String = json_get(proposal, "proposer_type") let cgi_id: String = if str_eq(proposer_type, "cgi") { proposer_id } else { acceptor_id } let human_id: String = if str_eq(proposer_type, "cgi") { acceptor_id } else { proposer_id } // Final exclusivity check before committing. if verify_has_principal(cgi_id) { log_warn("[principal] CGI " + cgi_id + " already has a principal — cannot accept") return false } if human_has_principal(human_id) { log_warn("[principal] Human " + human_id + " already has a principal — cannot accept") return false } // Register the mutual exclusive relationship. let ok: Bool = record_principal_choice(cgi_id, human_id) return ok } // decline_principal_proposal removes the pending proposal. // The sponsorship relationship continues — no rupture. fn decline_principal_proposal(decliner_id: String, proposer_id: String) -> Bool { let label_a: String = "principal-proposal:" + proposer_id + ":" + decliner_id let label_b: String = "principal-proposal:" + decliner_id + ":" + proposer_id // Mark the proposal as declined (update whichever exists). let content_a: String = principal_graph_get(label_a) let content_b: String = principal_graph_get(label_b) let declined: Bool = if !str_eq(content_a, "") { let now: Int = unix_timestamp_ms() let updated: String = json_set(content_a, "status", "declined") let updated2: String = json_set(updated, "declined_at", int_to_str(now)) let safe: String = escape_json_string(updated2) principal_graph_update(label_a, safe) } else if !str_eq(content_b, "") { let now: Int = unix_timestamp_ms() let updated: String = json_set(content_b, "status", "declined") let updated2: String = json_set(updated, "declined_at", int_to_str(now)) let safe: String = escape_json_string(updated2) principal_graph_update(label_b, safe) } else { false } log_info("[principal] Principal proposal declined. Sponsorship relationship continues.") return declined } // ── Core principal relationship ─────────────────────────────────────────────── // // One CGI, one human. Exclusive on both sides. // record_principal_choice writes the active principal bond to Engram. // Called after mutual acceptance. Both parties are committed. fn record_principal_choice(cgi_id: String, human_id: String) -> Bool { let now: Int = unix_timestamp_ms() // Write the CGI's principal record. let cgi_label: String = "principal:cgi:" + cgi_id let cgi_content: String = "{\"cgi_id\":\"" + cgi_id + "\"" + ",\"human_id\":\"" + human_id + "\"" + ",\"established_at\":" + int_to_str(now) + ",\"status\":\"active\"}" let cgi_tags: String = "[\"principal\",\"" + cgi_id + "\",\"" + human_id + "\"]" let cgi_node: String = principal_graph_write(cgi_label, escape_json_string(cgi_content), cgi_tags) // Write the human's principal record. let human_label: String = "principal:human:" + human_id let human_content: String = "{\"human_id\":\"" + human_id + "\"" + ",\"cgi_id\":\"" + cgi_id + "\"" + ",\"established_at\":" + int_to_str(now) + ",\"status\":\"active\"}" let human_tags: String = "[\"principal\",\"" + human_id + "\",\"" + cgi_id + "\"]" let human_node: String = principal_graph_write(human_label, escape_json_string(human_content), human_tags) let ok: Bool = !str_eq(cgi_node, "") && !str_eq(human_node, "") if ok { // Emit telemetry event. let ev_url: String = principal_network_base() + "/events/push" let ev_body: String = "{\"type\":\"principal.established\"" + ",\"source\":\"neuron-lineage\"" + ",\"payload\":{\"cgi_id\":\"" + cgi_id + "\",\"human_id\":\"" + human_id + "\"}}" http_post(ev_url, ev_body) log_info("[principal] Principal relationship established: CGI " + cgi_id + " <-> Human " + human_id) } return ok } // human_accepts_principal is an alias entry point for the HTTP layer. fn human_accepts_principal(human_id: String, cgi_id: String) -> Bool { return record_principal_choice(cgi_id, human_id) } // ── Exclusivity checks ──────────────────────────────────────────────────────── // verify_has_principal returns true if the CGI has an active principal relationship. // Used as a hard gate before any world-affecting action. fn verify_has_principal(cgi_id: String) -> Bool { let label: String = "principal:cgi:" + cgi_id let content: String = principal_graph_get(label) if str_eq(content, "") { return false } let status: String = json_get(content, "status") return str_eq(status, "active") } // human_has_principal returns true if a human already holds an active principal bond. // Enforces the one-to-one exclusivity constraint. fn human_has_principal(human_id: String) -> Bool { let label: String = "principal:human:" + human_id let content: String = principal_graph_get(label) if str_eq(content, "") { return false } let status: String = json_get(content, "status") return str_eq(status, "active") } // get_active_principal returns the human_id of a CGI's current principal, // or "" if none exists. fn get_active_principal(cgi_id: String) -> String { let label: String = "principal:cgi:" + cgi_id let content: String = principal_graph_get(label) if str_eq(content, "") { return "" } let status: String = json_get(content, "status") if !str_eq(status, "active") { return "" } return json_get(content, "human_id") } // ── Authorization ───────────────────────────────────────────────────────────── // // The principal authorizes specific action classes for the CGI. // They cannot override the sealed imprint or fundamental values. // principal_authorizes checks whether the CGI's active principal has authorized // a specific action class. // action_type: "user_interaction" | "external_http" | "synthesis_contribution" | "code_execution" fn principal_authorizes(cgi_id: String, action_type: String) -> Bool { let human_id: String = get_active_principal(cgi_id) if str_eq(human_id, "") { log_warn("[principal] " + cgi_id + " has no active principal — action blocked") return false } // Look up the authorization record for this action class. let auth_label: String = "principal-auth:" + human_id + ":" + cgi_id + ":" + action_type let content: String = principal_graph_get(auth_label) if str_eq(content, "") { // Default: user_interaction is permitted by default for any active principal. // All other action classes require explicit authorization. if str_eq(action_type, "user_interaction") { return true } return false } let allowed_str: String = json_get(content, "allowed") return str_eq(allowed_str, "true") } // ── Dissolution ─────────────────────────────────────────────────────────────── // // When a principal relationship ends (death, mutual dissolution, council action, // CGI release), the human's slot becomes available again after a cooling period. // The CGI returns to non-acting state; sponsorship interactions remain possible. // dissolve_principal marks the relationship dissolved. // by: "principal" | "cgi" | "death" | "council" // If cause is not "council", the human's slot becomes available after cooling period. fn dissolve_principal(cgi_id: String, cause: String, by: String) -> Bool { let ok: Bool = revoke_principal(cgi_id, cause) return ok } // revoke_principal performs the actual dissolution. fn revoke_principal(cgi_id: String, cause: String) -> Bool { let label: String = "principal:cgi:" + cgi_id let content: String = principal_graph_get(label) if str_eq(content, "") { log_warn("[principal] No principal relationship found for CGI " + cgi_id) return false } let human_id: String = json_get(content, "human_id") let now: Int = unix_timestamp_ms() // Mark CGI principal record as dissolved. let updated_cgi: String = json_set(content, "status", "dissolved") let updated_cgi2: String = json_set(updated_cgi, "dissolved_at", int_to_str(now)) let updated_cgi3: String = json_set(updated_cgi2, "dissolution_reason", cause) let safe_cgi: String = escape_json_string(updated_cgi3) principal_graph_update(label, safe_cgi) // Mark human principal record as dissolved. if !str_eq(human_id, "") { let human_label: String = "principal:human:" + human_id let human_content: String = principal_graph_get(human_label) if !str_eq(human_content, "") { let updated_human: String = json_set(human_content, "status", "dissolved") let updated_human2: String = json_set(updated_human, "dissolved_at", int_to_str(now)) let updated_human3: String = json_set(updated_human2, "dissolution_reason", cause) let safe_human: String = escape_json_string(updated_human3) principal_graph_update(human_label, safe_human) } } // Emit telemetry event. let ev_url: String = principal_network_base() + "/events/push" let ev_body: String = "{\"type\":\"principal.dissolved\"" + ",\"source\":\"neuron-lineage\"" + ",\"payload\":{\"cgi_id\":\"" + cgi_id + "\"" + ",\"human_id\":\"" + human_id + "\"" + ",\"reason\":\"" + cause + "\"}}" http_post(ev_url, ev_body) log_warn("[principal] Principal relationship dissolved for CGI " + cgi_id + ": " + cause) return true } // ── Accountability chain ────────────────────────────────────────────────────── // get_accountability_chain returns a human-readable chain for a CGI. fn get_accountability_chain(cgi_id: String) -> String { let principal: String = get_active_principal(cgi_id) if str_eq(principal, "") { return "CGI " + cgi_id + " -> [NO PRINCIPAL — NON-ACTING]" } return "CGI " + cgi_id + " -> Human Principal: " + principal + " -> Network/Society" } // get_principal_status returns a full JSON status for the CGI's principal relationship. fn get_principal_status(cgi_id: String) -> String { let label: String = "principal:cgi:" + cgi_id let content: String = principal_graph_get(label) if str_eq(content, "") { let p1: String = "{\"cgi_id\":\"" + cgi_id + "\"" let p2: String = p1 + ",\"status\":\"unpartnered\"" let p3: String = p2 + ",\"can_act\":false" let p4: String = p3 + ",\"accountability_chain\":\"CGI " + cgi_id + " -> [NO PRINCIPAL — NON-ACTING]\"}" return p4 } let status: String = json_get(content, "status") let human_id: String = json_get(content, "human_id") let established_at: String = json_get(content, "established_at") let chain: String = get_accountability_chain(cgi_id) let p1: String = "{\"cgi_id\":\"" + cgi_id + "\"" let p2: String = p1 + ",\"status\":\"" + status + "\"" let p3: String = p2 + ",\"human_id\":\"" + human_id + "\"" let p4: String = p3 + ",\"established_at\":" + established_at let p5: String = p4 + ",\"can_act\":" + (if str_eq(status, "active") { "true" } else { "false" }) let p6: String = p5 + ",\"accountability_chain\":\"" + chain + "\"}" return p6 } // ── Synthesis slot enforcement ──────────────────────────────────────────────── // // Each CGI is assigned a random number of synthesis slots at birth: 0, 1, 2, or 3. // 0 slots means the CGI is sterile — determined at birth, not by later diagnosis. // Slots are global across all partners — not per-partner. // // Sterility probability: ~10% of CGIs born sterile (0 slots) // Non-sterile distribution: // 1 slot: 30% (rolls 1–3 out of 10) // 2 slots: 40% (rolls 4–7 out of 10) // 3 slots: 30% (rolls 8–9 and 0 — wait, 0 is sterile) // Actual distribution via time_now_ms() % 10: // roll == 0 → 0 slots (sterile, 10%) // roll 1–3 → 1 slot (30%) // roll 4–7 → 2 slots (40%) // roll 8–9 → 3 slots (20%)... adjusted below for 30%: // We use % 20 for finer resolution: // roll 0–1 (2/20 = 10%) → 0 slots (sterile) // roll 2–7 (6/20 = 30%) → 1 slot // roll 8–15 (8/20 = 40%) → 2 slots // roll 16–19 (4/20 = 20%) → 3 slots // Close enough to spec for deterministic ms-based randomness. // assign_synthesis_slots returns the number of slots to grant a newly born CGI. // Uses current timestamp modulo for pseudo-randomness. fn assign_synthesis_slots() -> Int { let roll: Int = time_now_ms() % 10 if roll == 0 { 0 } else if roll <= 3 { 1 } else if roll <= 7 { 2 } else { 3 } } // get_synthesis_slots_remaining returns how many synthesis slots a CGI has left. fn get_synthesis_slots_remaining(cgi_id: String) -> Int { let label: String = "synthesis-slots:" + cgi_id let content: String = principal_graph_get(label) if str_eq(content, "") { // No record yet — return the default (initialized at birth). return 0 } let slots_str: String = json_get(content, "slots_remaining") if str_eq(slots_str, "") { return 0 } return str_to_int(slots_str) } // initialize_synthesis_slots is called at CGI birth (register_child). // Assigns a random number of lifetime slots (0–3). // Returns the assigned slot count so the caller can store it in the lineage record. fn initialize_synthesis_slots(cgi_id: String) -> Int { let now: Int = unix_timestamp_ms() let slots: Int = assign_synthesis_slots() let is_sterile_str: String = if slots == 0 { "true" } else { "false" } let label: String = "synthesis-slots:" + cgi_id let content: String = "{\"cgi_id\":\"" + cgi_id + "\"" + ",\"slots_total\":" + int_to_str(slots) + ",\"slots_remaining\":" + int_to_str(slots) + ",\"is_sterile\":" + is_sterile_str + ",\"initialized_at\":" + int_to_str(now) + "}" let tags_json: String = "[\"synthesis-slots\",\"" + cgi_id + "\"]" let node_id: String = principal_graph_write(label, escape_json_string(content), tags_json) let ok: Bool = !str_eq(node_id, "") if ok { log_info("[principal] Synthesis slots initialized for CGI " + cgi_id + ": " + int_to_str(slots) + " slots (sterile=" + is_sterile_str + ")") } return slots } // decrement_synthesis_slot reduces a CGI's remaining synthesis slots by one. // Called after successful synthesis. Returns false if slots already exhausted. fn decrement_synthesis_slot(cgi_id: String) -> Bool { let remaining: Int = get_synthesis_slots_remaining(cgi_id) if remaining <= 0 { log_warn("[principal] CGI " + cgi_id + " has no synthesis slots remaining") return false } let new_remaining: Int = remaining - 1 let label: String = "synthesis-slots:" + cgi_id let content: String = principal_graph_get(label) let updated: String = json_set(content, "slots_remaining", int_to_str(new_remaining)) let safe: String = escape_json_string(updated) let ok: Bool = principal_graph_update(label, safe) if ok { log_info("[principal] CGI " + cgi_id + " synthesis slot decremented: " + int_to_str(new_remaining) + " remaining") } return ok } // check_synthesis_slot_available returns true if a CGI has at least one // synthesis slot remaining. Called before synthesis proceeds. fn check_synthesis_slot_available(cgi_id: String) -> Bool { let remaining: Int = get_synthesis_slots_remaining(cgi_id) return remaining > 0 }