// agentic_loop.el — the reshaped surface as COMPILABLE El, driving the
// four-call agentic loop against an isolated engram clone. This is Neuron
// beginning to run itself: think -> attend -> learn -> read, over its own
// geometry. Compile: elc --target=c agentic_loop.el ...  (see build_and_run.sh).
//
// Ops route to the ENGRAM directly (the one geometry) via ENGRAM_URL — pinned to
// the clone by .nsbx-env. Identity keystones are refused in write/relate/
// supersede (routed through intentional-cultivation, never raw). Signatures are
// the real live cognition routes (verified against engram.cognition-20260814).

fn engram_url() -> String {
    let u: String = env("ENGRAM_URL")
    if str_eq(u, "") { return "http://127.0.0.1:8900" }
    return u
}
fn engram_key() -> String {
    let k: String = env("ENGRAM_API_KEY")
    if str_eq(k, "") { return "sbx-dev-api-reshape" }
    return k
}
fn SELF_KEY() -> String { return "kn-efeb4a5b-5aff-4759-8a97-7233099be6ee" }
fn VALUES_KEY() -> String { return "kn-5b606390-a52d-4ca2-8e0e-eba141d13440" }

// self/values name -> keystone id; anything else passes through unchanged.
fn resolve_named(v: String) -> String {
    if str_eq(v, "self") { return SELF_KEY() }
    if str_eq(v, "neuron") { return SELF_KEY() }
    if str_eq(v, "values") { return VALUES_KEY() }
    if str_eq(v, "values_hub") { return VALUES_KEY() }
    return v
}
fn touches_identity(id: String) -> Bool {
    if str_eq(id, SELF_KEY()) { return true }
    if str_eq(id, VALUES_KEY()) { return true }
    return false
}
fn identity_typed(t: String) -> Bool {
    if str_eq(t, "self") { return true }
    if str_eq(t, "values") { return true }
    return false
}
fn type_to_node_type(t: String) -> String {
    if str_eq(t, "knowledge") { return "Knowledge" }
    if str_eq(t, "artifact") { return "Artifact" }
    if str_eq(t, "backlog") { return "WorkItem" }
    if str_eq(t, "process") { return "Process" }
    if str_eq(t, "state") { return "InternalStateEvent" }
    return "Memory"
}

// ── LAYER 1 — geometry ops ───────────────────────────────────────────────────

// read — THE VANTAGE-READ. Re-origin at a point + aperture -> a BOUNDED slice.
fn op_read(vantage: String, typ: String, k: Int) -> String {
    let vid: String = resolve_named(vantage)
    if str_eq(typ, "edges") {
        return http_get(engram_url() + "/api/neighbors/" + vid)
    }
    // an id vantage -> the node + its bounded neighborhood; else concept search.
    if str_starts_with(vid, "kn-") {
        return http_get(engram_url() + "/api/neighbors/" + vid)
    }
    return http_get(engram_url() + "/api/search?q=" + url_encode(vid) + "&limit=" + int_to_str(k))
}

// write — add a node; type selects node_type. Identity types refused.
fn op_write(content: String, typ: String, importance: Float) -> String {
    if str_eq(content, "") { return "{\"error\":\"write: content required\"}" }
    if identity_typed(typ) {
        return "{\"error\":\"write type=" + typ + " is write-protected -> intentional-cultivation\"}"
    }
    let body: String = "{\"_auth\":\"" + engram_key() + "\",\"content\":\"" + json_escape(content)
        + "\",\"node_type\":\"" + type_to_node_type(typ) + "\",\"tier\":\"Working\",\"importance\":"
        + float_to_str(importance) + "}"
    return http_post_json(engram_url() + "/api/nodes", body)
}

// relate — typed edge. Refused if either endpoint is an identity keystone.
fn op_relate(from_id: String, to_id: String, relationship: String) -> String {
    if str_eq(from_id, "") { return "{\"error\":\"relate: from required\"}" }
    if str_eq(to_id, "") { return "{\"error\":\"relate: to required\"}" }
    if touches_identity(from_id) { return "{\"error\":\"relate: identity keystone write-protected\"}" }
    if touches_identity(to_id) { return "{\"error\":\"relate: identity keystone write-protected\"}" }
    let rel: String = if str_eq(relationship, "") { "associates" } else { relationship }
    let body: String = "{\"_auth\":\"" + engram_key() + "\",\"from_id\":\"" + from_id
        + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + rel + "\",\"weight\":0.5}"
    return http_post_json(engram_url() + "/api/edges", body)
}

// supersede — immutable: tombstone (DELETE keeps original) or evolve (new + edge).
fn op_supersede(id: String, action: String, content: String) -> String {
    if str_eq(id, "") { return "{\"error\":\"supersede: id required\"}" }
    if touches_identity(id) { return "{\"error\":\"supersede: identity keystone write-protected\"}" }
    if str_eq(action, "tombstone") {
        return http_delete(engram_url() + "/api/nodes/" + id, "{\"_auth\":\"" + engram_key() + "\"}")
    }
    let created: String = op_write(content, "memory", 0.5)
    let new_id: String = json_get_string(created, "id")
    if str_eq(new_id, "") { return created }
    let e: String = op_relate(new_id, id, "supersedes")
    return "{\"new_id\":\"" + new_id + "\",\"supersedes\":\"" + id + "\",\"edge\":" + e + "}"
}

// ── LAYER 2 — primitive agentic tools (grounded in the live cog-arch) ─────────

// think — THE ONE OPERATION. anchor (node ids) steered by faculty -> gradient.
fn op_think(seeds: String, faculty: String) -> String {
    let s: String = resolve_named(seeds)
    let f: String = if str_eq(faculty, "") { "reason" } else { faculty }
    return http_get(engram_url() + "/api/think?seeds=" + url_encode(s) + "&faculty=" + f)
}
// attend — aim attention at a region.
fn op_attend(node: String, observer: String) -> String {
    let n: String = resolve_named(node)
    let o: String = if str_eq(observer, "") { SELF_KEY() } else { resolve_named(observer) }
    let body: String = "{\"_auth\":\"" + engram_key() + "\",\"node\":\"" + n
        + "\",\"observer\":\"" + o + "\",\"salience\":\"0.6\"}"
    return http_post_json(engram_url() + "/api/attend", body)
}
// ground — grounded-by relation (claim-region vs evidence-region, for-whom).
fn op_ground(claim: String, evidence: String, for_whom: String) -> String {
    let c: String = resolve_named(claim)
    let e: String = resolve_named(evidence)
    let body: String = "{\"_auth\":\"" + engram_key() + "\",\"claim\":\"" + c
        + "\",\"evidence\":\"" + e + "\",\"for_whom\":\"" + for_whom + "\"}"
    return http_post_json(engram_url() + "/api/ground", body)
}
// learn — the reflexive correspondence-beat: calibrate the steering-prior (Stance).
fn op_learn(seeds: String, faculty: String) -> String {
    let s: String = resolve_named(seeds)
    let f: String = if str_eq(faculty, "") { "induce" } else { faculty }
    let body: String = "{\"_auth\":\"" + engram_key() + "\",\"seeds\":\"" + s
        + "\",\"faculty\":\"" + f + "\",\"keystone\":\"false\"}"
    return http_post_json(engram_url() + "/api/correspondence-beat", body)
}

fn head160(s: String) -> String { return s }

// ── THE AGENTIC LOOP — Neuron running itself over its own geometry ───────────
fn main() -> Int {
    println("== reshaped surface: Neuron running itself over its own geometry ==")
    println("engram (clone): " + engram_url())

    // 1) THINK — reason/plan from the self, steered by the 'plan' faculty.
    let g: String = op_think("self", "plan")
    println("")
    println("1. think({seeds:self, faculty:plan}) -> gradient:")
    println("   " + g)

    // 2) ATTEND — aim attention at the values region (a real node-id region).
    let a: String = op_attend("values", "self")
    println("")
    println("2. attend({node:values, observer:self}) -> attention aimed:")
    println("   " + a)

    // 3) LEARN — reflexive correspondence-beat: calibrate the prior on that region.
    let l: String = op_learn("values", "induce")
    println("")
    println("3. learn({seeds:values, faculty:induce}) -> Stance calibrated:")
    println("   " + l)

    // 4) READ — bounded vantage-read from the self (aperture k=6, no dump).
    let r: String = op_read("self", "edges", 6)
    println("")
    println("4. read({vantage:self, type:edges, k:6}) -> BOUNDED self-slice:")
    println("   bytes=" + int_to_str(str_len(r)))

    // Identity guard proof — a write/relate touching a keystone is refused.
    println("")
    println("guard: write(type=values) -> " + op_write("attempt", "values", 0.5))
    println("guard: relate(to=self keystone) -> " + op_relate("some-node", SELF_KEY(), "associates"))

    println("")
    println("== loop complete: think -> attend -> learn -> read, all over the live geometry ==")
    return 0
}
