e5c80359a8
New hard invariant (Will): only the orchestrator mutates global engram state; workers are read-only against the full engram + write only their own local geometry. This is an AUTHORITY gate (capability), not a health gate — a worker is STRUCTURALLY UNABLE to mutate global engram state regardless of engram health. - containment.el: scope tokens now carry a caps set. Orchestrator token holds engram:write + dharma:emit (@manager-only, the VBD rule that only the manager mutates global state); worker token holds ONLY engram:read. Rule 4: containment_check_engram_write / _dharma_emit reject any caller lacking the capability — same scope-token mechanism as the live Rule-2 denial. - swarm.el: swarm_engram_write is the ONLY engram write path, gated by Rule 4; a worker token is denied before any HTTP is issued (no mutation). The curated merge (commit=1) is the sole writer: the orchestrator commits approved geometry via its write-capable token. Workers' full-engram READ stays intact. - reshape_surface.el: compose op_write (json_escape_string) for the commit path. - harness: Rule-4 suite proven — worker engram-write DENIED by capability, no node created, violation journalled; orchestrator passes the gate as sole writer. 24/24 green on the :8901 clone with real cognition. Authority gate holds independent of daemon write-health (proven with daemon both alive and, earlier, crashed). Prod :8742 untouched.
104 lines
4.7 KiB
EmacsLisp
104 lines
4.7 KiB
EmacsLisp
// reshape_surface.el — the api-reshape agent's PROVEN decorated primitives,
|
|
// composed into the swarm build to bind real cognition.
|
|
//
|
|
// PROVENANCE: these fns are the reshape's surface at wt/api-reshape @ d4f401d
|
|
// ("reshape: decorator-as-seam — port @route codegen, prove decorate->serve,
|
|
// rewrite surface as decorated El"), verified live against
|
|
// engram.cognition-20260814. Copied verbatim (read/cognition ops only) so the
|
|
// swarm binds the REAL primitives, not a reimplementation. The write ops
|
|
// (op_write/op_relate/op_supersede/op_ground) are intentionally NOT composed
|
|
// here — they exercise the persist_node write path that needs the gate-1
|
|
// write-healthy clone; the swarm's proven run is read-cognition (think/read).
|
|
//
|
|
// Ops route to the ENGRAM over ENGRAM_URL — pinned by THIS worktree's .nsbx-env
|
|
// to the :8901 swarm clone (never the reshape agent's :8900). Separate clones,
|
|
// no collision.
|
|
|
|
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
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
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))
|
|
}
|
|
|
|
// 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. (POST — needs a write-healthy clone.)
|
|
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)
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
// write — add a node (POST /api/nodes). Identity types refused. This is a
|
|
// global-engram MUTATION — @manager-only (Rule 4); never called on a worker path.
|
|
// (Reshape's op_write, with json_escape -> the available json_escape_string.)
|
|
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_string(content)
|
|
+ "\",\"node_type\":\"" + type_to_node_type(typ) + "\",\"tier\":\"Working\",\"importance\":"
|
|
+ float_to_str(importance) + "}"
|
|
return http_post_json(engram_url() + "/api/nodes", body)
|
|
}
|
|
|
|
// learn — the reflexive correspondence-beat: calibrate the steering-prior.
|
|
// (POST — needs a write-healthy clone.)
|
|
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)
|
|
}
|