d4f401de1c
Ground-truth the three seams (route/telemetry+interoception/bus) with file:line evidence. Port the tested @route codegen+parser from feat/el-route-decorators into the worktree elc (decoration synthesizes el_route_dispatch — no hand-written 90-branch handle_request). Rebuild elc self-host; prove decorate->serve end-to-end (route_proof.el on :8951). Rewrite surface.el as El-native decorated components: @route + @accessor/@manager, in-process engram_* builtins (not http_get), @manager ops emit on the real dharma_* bus (same transport as wt/swarm-ccr). Identity keystones refused in write/relate/supersede. Gate-1 clone recipe (WAL-aside cold-boot + ENGRAM_WAL=on) proves the FULL op set live on the clone. Boundary auto-emit (telemetry/interoception/bus) staged as a reviewable cg_fn diff (SEAM_STAGED.md) — needs the cognition-engram rebuild to verify link. Live :8742 untouched; no push, no cutover.
165 lines
8.9 KiB
EmacsLisp
165 lines
8.9 KiB
EmacsLisp
// surface.el — the RESHAPED Neuron surface as EL-NATIVE DECORATED COMPONENTS.
|
|
//
|
|
// Design: artifact 0e828907 + design-brief 2b8078cf §5. THE DECORATION IS THE API.
|
|
// Each op is one function decorated with (a) its @route — codegen synthesizes the
|
|
// HTTP dispatcher (el_route_dispatch), no hand-written 90-branch handle_request —
|
|
// and (b) its VBD role — @accessor (engram I/O) or @manager (agentic orchestration
|
|
// + sole DHARMA emitter). Handlers call the engram IN-PROCESS via engram_* builtins
|
|
// (NOT http_get: the old MCP-wrapper http idiom existed only because it was a
|
|
// separate process; compiled into the engram, the geometry is a direct call).
|
|
//
|
|
// This file is designed to be INCLUDED IN the engram server (engram/src/server.el)
|
|
// so the engram_* builtins + server helpers (query_param, json_get_string,
|
|
// extract_id, err_json, engram_node_full, persist_node, ...) link in-process.
|
|
//
|
|
// Handler contract (from the @route codegen): uniform (method, path, body)->String.
|
|
//
|
|
// Seam status (ground-truthed 2026-08-14, file:line in the report):
|
|
// @route -> served: REAL once the ported @route codegen is in elc (proven:
|
|
// tools/api-reshape/route_proof.el serves decorated handlers on :8951).
|
|
// @manager dharma_emit -> bus: REAL today (explicit call; @manager may emit).
|
|
// STAGED codegen change makes it AUTOMATIC at the boundary (report §diff),
|
|
// sharing the one dharma_* transport the swarm (wt/swarm-ccr) uses.
|
|
// @accessor telemetry (strengthen/afferent/chronoception): fires inside the
|
|
// engram builtins today; STAGED to also fire at the decorated boundary.
|
|
|
|
// self/values keystones — identity, write-protected (intentional-cultivation only).
|
|
fn is_identity_id(id: String) -> Bool {
|
|
if str_eq(id, "kn-efeb4a5b-5aff-4759-8a97-7233099be6ee") { return true }
|
|
if str_eq(id, "kn-5b606390-a52d-4ca2-8e0e-eba141d13440") { return true }
|
|
return false
|
|
}
|
|
fn type_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 (@accessor: engram I/O, in-process) ────────────────
|
|
|
|
// read — THE VANTAGE-READ. re-origin + aperture -> BOUNDED slice. type=edges reads
|
|
// the neighborhood; a concept vantage reads salience-ranked geometry (limit=aperture).
|
|
@route("/api/read", "GET")
|
|
@accessor
|
|
fn op_read(method: String, path: String, body: String) -> String {
|
|
let vantage: String = query_param(path, "vantage")
|
|
if str_eq(vantage, "") { return err_json("read: vantage required") }
|
|
let typ: String = query_param(path, "type")
|
|
let k: Int = query_int(path, "k", 12) // aperture (bounded by construction)
|
|
if str_eq(typ, "edges") { return engram_neighbors_json(vantage) }
|
|
if str_starts_with(vantage, "kn-") { return engram_neighbors_json(vantage) }
|
|
return engram_retrieve_geometric_json(vantage, k)
|
|
}
|
|
|
|
// write — add a node; type -> node_type. Identity types refused.
|
|
@route("/api/write", "POST")
|
|
@accessor
|
|
fn op_write(method: String, path: String, body: String) -> String {
|
|
let content: String = json_get_string(body, "content")
|
|
if str_eq(content, "") { return err_json("write: content required") }
|
|
let typ: String = json_get_string(body, "type")
|
|
if str_eq(typ, "self") { return err_json("write: identity is write-protected -> intentional-cultivation") }
|
|
if str_eq(typ, "values") { return err_json("write: identity is write-protected -> intentional-cultivation") }
|
|
let tags: String = json_get_string(body, "tags")
|
|
let imp: Float = json_get_float(body, "importance")
|
|
let id: String = engram_node_full(content, type_node_type(typ), content, 0.5, imp, 1.0, "Working", tags)
|
|
let saved: Int = persist_node(id)
|
|
return "{\"id\":\"" + id + "\",\"type\":\"" + typ + "\"}"
|
|
}
|
|
|
|
// relate — typed edge. Refused if either endpoint is an identity keystone.
|
|
@route("/api/relate", "POST")
|
|
@accessor
|
|
fn op_relate(method: String, path: String, body: String) -> String {
|
|
let from_id: String = json_get_string(body, "from")
|
|
let to_id: String = json_get_string(body, "to")
|
|
if str_eq(from_id, "") { return err_json("relate: from required") }
|
|
if str_eq(to_id, "") { return err_json("relate: to required") }
|
|
if is_identity_id(from_id) { return err_json("relate: identity keystone write-protected") }
|
|
if is_identity_id(to_id) { return err_json("relate: identity keystone write-protected") }
|
|
let rel_raw: String = json_get_string(body, "relationship")
|
|
let rel: String = if str_eq(rel_raw, "") { "associates" } else { rel_raw }
|
|
let ec0: Int = engram_edge_count()
|
|
engram_connect(from_id, to_id, 0.5, rel)
|
|
let saved: Int = persist_edges_since(ec0)
|
|
return "{\"ok\":true,\"from\":\"" + from_id + "\",\"to\":\"" + to_id + "\",\"relationship\":\"" + rel + "\"}"
|
|
}
|
|
|
|
// supersede — IMMUTABLE. tombstone (marker + edge, original kept) | evolve (new + edge).
|
|
@route("/api/supersede", "POST")
|
|
@accessor
|
|
fn op_supersede(method: String, path: String, body: String) -> String {
|
|
let id: String = json_get_string(body, "id")
|
|
if str_eq(id, "") { return err_json("supersede: id required") }
|
|
if is_identity_id(id) { return err_json("supersede: identity keystone write-protected") }
|
|
let action: String = json_get_string(body, "action")
|
|
if str_eq(action, "tombstone") {
|
|
let tomb: String = engram_node_full("tombstone:" + id, "Tombstone", "tombstone:" + id, 0.1, 0.1, 1.0, "Episodic", "[\"tombstone\"]")
|
|
engram_connect(tomb, id, 1.0, "tombstones") // original node retained (immutable)
|
|
let s: Int = persist_node(tomb)
|
|
return "{\"ok\":true,\"tombstoned\":\"" + id + "\",\"tombstone_id\":\"" + tomb + "\"}"
|
|
}
|
|
let content: String = json_get_string(body, "content")
|
|
if str_eq(content, "") { return err_json("supersede(evolve): content required") }
|
|
let new_id: String = engram_node_full(content, "Memory", content, 0.5, 0.5, 1.0, "Working", "")
|
|
let sv: Int = persist_node(new_id)
|
|
engram_connect(new_id, id, 1.0, "supersedes") // old node retained (immutable)
|
|
let sv2: Int = persist_edges_since(engram_edge_count() - 1)
|
|
return "{\"new_id\":\"" + new_id + "\",\"supersedes\":\"" + id + "\"}"
|
|
}
|
|
|
|
// ── LAYER 2 — primitive agentic tools (@manager: orchestration + DHARMA emit) ──
|
|
// think is the one operation; faculty is its steering label. Each @manager op
|
|
// emits on the dharma_* bus (the same transport the swarm peers use). When the
|
|
// staged boundary-injection lands, these explicit emits become automatic.
|
|
|
|
@route("/api/think", "GET")
|
|
@manager
|
|
fn op_think(method: String, path: String, body: String) -> String {
|
|
let seeds: String = query_param(path, "seeds") // CSV node-ids (the anchor)
|
|
if str_eq(seeds, "") { return err_json("think: seeds (node-id anchor) required") }
|
|
let f_raw: String = query_param(path, "faculty")
|
|
let f: String = if str_eq(f_raw, "") { "reason" } else { f_raw }
|
|
dharma_emit("neuron.think", "{\"seeds\":\"" + seeds + "\",\"faculty\":\"" + f + "\"}")
|
|
return engram_think_json(seeds, f)
|
|
}
|
|
|
|
@route("/api/attend", "POST")
|
|
@manager
|
|
fn op_attend(method: String, path: String, body: String) -> String {
|
|
let node: String = json_get_string(body, "node")
|
|
if str_eq(node, "") { return err_json("attend: node (region) required") }
|
|
let observer: String = json_get_string(body, "observer")
|
|
let salience: String = json_get_string(body, "salience")
|
|
dharma_emit("neuron.attend", "{\"node\":\"" + node + "\"}")
|
|
return engram_attend_json(node, observer, salience)
|
|
}
|
|
|
|
@route("/api/ground", "POST")
|
|
@manager
|
|
fn op_ground(method: String, path: String, body: String) -> String {
|
|
let claim: String = json_get_string(body, "claim") // node-id region
|
|
let evidence: String = json_get_string(body, "evidence") // node-id region
|
|
if str_eq(claim, "") { return err_json("ground: claim required") }
|
|
if str_eq(evidence, "") { return err_json("ground: evidence required") }
|
|
let for_whom: String = json_get_string(body, "for_whom")
|
|
dharma_emit("neuron.ground", "{\"claim\":\"" + claim + "\"}")
|
|
return engram_ground_json(claim, evidence, for_whom)
|
|
}
|
|
|
|
// learn — the reflexive correspondence-beat: calibrate the steering-prior (Stance).
|
|
@route("/api/learn", "POST")
|
|
@manager
|
|
fn op_learn(method: String, path: String, body: String) -> String {
|
|
let seeds: String = json_get_string(body, "seeds")
|
|
if str_eq(seeds, "") { return err_json("learn: seeds required") }
|
|
let f_raw: String = json_get_string(body, "faculty")
|
|
let f: String = if str_eq(f_raw, "") { "induce" } else { f_raw }
|
|
let keystone: String = json_get_string(body, "keystone")
|
|
dharma_emit("neuron.learn", "{\"seeds\":\"" + seeds + "\",\"faculty\":\"" + f + "\"}")
|
|
return engram_correspondence_beat_json(seeds, f, keystone)
|
|
}
|