Compare commits

..

4 Commits

Author SHA1 Message Date
Neuron ac248887c2 test: empty commit — is dev CI red independent of any change?
El SDK CI - dev / build-and-test (pull_request) Failing after 12m14s
Baseline probe. #89 shows red on dev CI and this Gitea instance does not serve
Actions logs (404/500 on every route), so the only way to learn whether dev CI is
broken on its own is to run it against dev with no change at all.

Reproduced locally first: control (dev head) and treatment (dev + #89) produce
BYTE-IDENTICAL test results — both build the self-hosted compiler and elb, both
fail the same three timezone tests (earth-zone, dst-spring-forward,
rhythm-grounding). That exonerates #89 locally. This probe asks the same question
of the real runner.

Close once it reports.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 14:45:39 -05:00
will.anderson 5d0d4555ae Sync main into dev (GitOps: keep dev current; main authoritative) (#84)
El SDK CI - dev / build-and-test (push) Successful in 8m32s
2026-08-03 15:38:40 +00:00
will.anderson 8347a2f1c0 Merge pull request 'docs: add root README mapping the El monorepo' (#83) from feat/AddingReadme into dev
El SDK CI - dev / build-and-test (push) Successful in 8m22s
2026-07-31 04:25:44 +00:00
Andre Botelho Rodrigues Almeida b97b644799 Addind readme.md file to start documenting the repo
El SDK CI - dev / build-and-test (pull_request) Successful in 8m18s
2026-07-23 16:41:51 -03:00
2 changed files with 154 additions and 312 deletions
+154
View File
@@ -0,0 +1,154 @@
# El
**A self-hosting, statically-typed language that compiles to C — built around a graph-native runtime instead of a database driver.**
El is the execution substrate for the Neuron agent runtime, the DHARMA network, and the Engram knowledge graph. This repository is the monorepo for the whole stack: the language itself, the graph memory engine it's built to talk to natively, and the tools (package manager, IDE, UI framework, diagramming) built on top of it.
---
## Why El exists
Every other language treats persistent, associative state as something you reach for through a driver — a SQL client, an ORM, a Redis library bolted on from outside. El inverts that: graph operations (`engram_*`) are runtime primitives, on the same footing as string or list operations. There is no separate database driver because the database is not separate.
El has four defining properties:
1. **Self-hosting compiler.** The compiler (`lexer.el`, `parser.el`, `codegen.el`, `compiler.el`) is written in El. It compiles El source to C, which `cc` compiles against a fixed runtime into a native binary. A Rust genesis compiler bootstrapped the first iteration; the self-hosted binary at `lang/dist/platform/elc` has been the canonical compiler ever since — every binary in `dist/platform/` was produced by an earlier version of itself compiling `el-compiler/src/`. The chain is auditable: source is the ground truth, not the binary. See [lang/BOOTSTRAP.md](lang/BOOTSTRAP.md) for the full recovery path if that binary is ever lost.
2. **C compilation target.** Every compiled program is plain C11. Every El value is `el_val_t` (`int64_t`); strings are heap pointers cast through it. Functions become C functions; top-level statements become `main()`.
3. **Graph-native runtime.** The runtime provides first-class graph operations over an in-process Engram store — no separate DB driver, no ORM.
4. **DHARMA-aware identity.** A `cgi` block declares a program's DHARMA identity at compile time. The runtime resolves identity before user code runs, so `dharma_*` calls have a stable principal and channel surface throughout.
---
## Architecture map
```
┌─────────────┐
│ lang │ El compiler + C runtime
│ (El itself) │ everything below is written in it,
└──────┬──────┘ or compiles down through it
┌─────────────┼─────────────┐
│ │ │
┌──────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ engram │ │ epm │ │ ide │
│ graph/mem │ │ package │ │ editor + │
│ substrate │ │ manager │ │ LSP │
└──────┬─────┘ └───────────┘ └───────────┘
┌───────┼────────────────┬─────────────────────┐
│ │ │ │
┌─────▼───┐ ┌─▼──────────┐ ┌──▼──────────┐ ┌─────▼──────┐
│ elp │ │ ql │ │ ui │ │ arbor │
│ NLG / │ │engram-el. │ |spreading- │ |arbor │
│ 31 langs│ │studio+tests│ |activation UI│ |diagram lang│
└─────────┘ └────────────┘ └─────────────┘ └────────────┘
```
`lang` is the foundation — the compiler and C runtime everything else builds on. `engram` is the graph-native memory/state engine that gives El its identity (property 3 above). Everything else is either a tool for working with El (`epm`, `ide`) or a system built on top of Engram's graph model (`elp`, `ql`, `ui`, `arbor`).
---
## Repository layout
### [lang/](lang/) — the El language
The compiler and runtime. Self-hosting: `elc-cli.el``compiler.el``lexer.el` / `parser.el` / `codegen.el` / `codegen-js.el`, textually inlined and compiled in one pass. Compiles to C11 and links against `el-compiler/runtime/el_seed.c`, a hand-maintained OS-boundary layer (libcurl HTTP, pthreads, filesystem, arena allocation) — everything else in the runtime is native El (`runtime/*.el`).
Two layers to know: **El programs** (`.el` files — where nearly all work belongs) and **the C seed** (`el_seed.c` — edit only for genuine OS-level access; never re-implement what El can already express).
Current status (single source of truth: [lang/spec/language.md](lang/spec/language.md)): lexer/parser/codegen and the C runtime's core (I/O, strings, math, lists, maps, filesystem, args) are implemented. In flight: `%` operator, match-statement codegen, `?` nil-propagation, `cgi` block parsing + DHARMA identity resolution, VBD role enforcement (`@manager`/`@engine`/`@accessor`), the real `engram_*` and `dharma_*` runtimes (currently stubs), and libcurl-backed `http_get`/`http_post`/`http_serve`. Bitwise operators, `??`, and `as` casts are explicitly **not** in this language.
Key docs: [AGENTS.md](lang/AGENTS.md) (agent-facing orientation), [BOOTSTRAP.md](lang/BOOTSTRAP.md) (compiler recovery from scratch), [spec/language.md](lang/spec/language.md), [spec/codegen-js.md](lang/spec/codegen-js.md).
### [engram/](engram/) — graph intelligence substrate
**A local-first memory substrate for accumulating intelligence**, and the reason El's runtime doesn't need a database driver. Rust core (`engram-core`, `engram-ffi`) exposed to El and other languages (Kotlin, TypeScript/WASM, Go bindings).
The model: retrieval is **spreading activation**, not query. You name seed nodes and a query embedding; activation propagates outward through weighted edges, attenuating multiplicatively per hop (`strength = parent_strength × edge_weight × target_salience × cosine_sim`), gets pruned below a threshold, and the top-N nodes by activation strength come back. Storage and retrieval are the same structure — the way long-term potentiation works in biological memory, not the way a relational or vector database works.
Nodes live in four tiers (Working / Episodic / Semantic / Procedural, mirroring prefrontal / hippocampal / neocortical / cerebellar memory) and migrate between them based on **salience decay**`importance × recency-decay × log(activation_count)`. Forgetting is adaptive pruning, not a bug: unreinforced memories stop competing for attention without being deleted.
Backed by `sled` (embedded, local-first, no daemon) with flat cosine scan for vector search — deliberately simple until scale demands an HNSW layer. Full API and design rationale in [engram/README.md](engram/README.md).
### [elp/](elp/) — Engram Language Protocol
Bidirectional engine mapping between Engram semantic forms and natural-language surface text, across **31 languages** — from Spanish and Japanese through historical/liturgical languages (Old Norse, Sanskrit, Sumerian, Coptic, Akkadian, Ge'ez). Compilation order runs `language-profile` + `vocabulary` → per-language `morphology-*``grammar``realizer``semantics``elp`. This is what lets an Engram graph node round-trip to and from readable text in any of those languages.
### [epm/](epm/) — El Package Manager
Manages **vessels** (El's package unit): publish, install, resolve dependencies. Vessels are stored in Engram as graph nodes, not files in a registry index — `epm` reads the local `manifest.el`, talks to Engram over HTTP, and writes resolved vessels to `.epm/vessels/`. Source: `registry.el`, `install.el`, `update.el`, `manifest.el`.
### [ide/](ide/) — El IDE
Three vessels: **el-ide-server** (HTTP backend — file ops, build/run, LSP bridge, plugin host, settings), **el-lsp** (the language server — completion, hover, diagnostics, outline, format, type graph), and **el-plugin-host** (first-party plugin lifecycle: install/remove/enable/disable). `ide/projects/` and `ide/examples/` hold sample projects, including the canonical `hello-friends` first-program walkthrough.
### [ql/](ql/) — engram-el
The El-native integration layer for a *live* Engram server — not a library (no importable modules, no build artifact), a set of standalone `.el` programs run directly via `el run-file`. Three components: **Studio** (`studio/studio.el`, a full terminal graph explorer), a **Hebbian field-model** proof of concept, and El builtin / LLM-builtin smoke test suites. This is the reference for correct patterns when an El program uses Engram as its substrate. Spec: [ql/spec/elql.md](ql/spec/elql.md).
### [ui/](ui/) — el-ui
A frontend framework where **component state is an Engram graph and reactivity is spreading activation** — not virtual-DOM diffing (React), Proxy-based dependency tracking (Vue), or compile-time analysis (Svelte). Re-renders are activated and propagated the same way associative memory retrieval works in `engram/`.
~15 vessels covering the full frontend surface: `el-platform` (env/fs/network/clock abstraction), `el-config`, `el-html` (SSR emit primitives), `el-layout`, `el-style` (design tokens/themes), `el-i18n`, `el-auth` / `el-identity` (JWT, sessions, OAuth PKCE — Engram-native), `el-services` (REST/gRPC/WebSocket bindings), `el-aop` (`@authenticate`/`@authorize`/`@cache`/`@rate_limit` decorators), `el-secrets`, `el-graph` (graph rendering/editor), `el-publish` (App Store / Play Store automation), and `el-ui-compiler` (El→JS component compiler; currently a stub pending a JS backend in `elc`). Spec: [ui/spec/framework.md](ui/spec/framework.md).
### [arbor/](arbor/) — diagram language
A `.arbor` diagram language and toolchain: `arbor-core` (NodeId/shape/edge-kind types), `arbor-parse` (recursive-descent parser), `arbor-diagram` (IR + Mermaid serializer + architecture-diagram builders), `arbor-layout` (hierarchical layout — rank assignment, positioning, group bounds), `arbor-render` (SVG renderer), `arbor-cli`. (The architecture map above is the kind of diagram this is for.)
---
## Getting started
Install the El SDK from the latest release:
```bash
bash lang/install.sh
# EL_VERSION=v1.0.0 bash lang/install.sh # pin a specific release tag
# EL_PREFIX=/opt/el bash lang/install.sh # custom install prefix
```
Or build the compiler from source and verify the self-hosting chain:
```bash
cd lang
./dist/platform/elc elc-cli.el > elc-new.c
cc -std=c11 -I el-compiler/runtime -lcurl -lpthread \
-o dist/platform/elc-new \
elc-new.c el-compiler/runtime/el_seed.c
# Confirm the new binary reproduces itself exactly
./dist/platform/elc-new elc-cli.el > elc-verify.c
diff elc-new.c elc-verify.c # should be identical
mv dist/platform/elc-new dist/platform/elc
```
Run your first program:
```bash
./lang/dist/platform/elc lang/examples/hello.el > hello.c
cc -std=c11 -I lang/el-compiler/runtime -lcurl -lpthread \
-o hello hello.c lang/el-compiler/runtime/el_seed.c
./hello
```
More examples in [lang/examples/](lang/examples/), including a full starter project at `lang/examples/hello-project/`.
If the compiler binary is ever lost or corrupted, [lang/BOOTSTRAP.md](lang/BOOTSTRAP.md) is the authoritative recovery path.
---
## Development workflow
Branching follows `dev → stage → main`: work lands on `dev`, promotes to `stage` for integration testing, and is promoted to `main` for release (visible directly in the git history of this repo). CI is defined per-subproject under `.gitea/workflows/``lang`/`epm`/`ide` share the root pipeline; `engram` and `ql` carry their own (`ci-dev`, `ci-stage`, and a release workflow each).
- Language/runtime specs live at `*/spec/*.md` (`lang/spec/`, `ql/spec/`, `ui/spec/`) and are the single source of truth for implemented-vs-planned status — code and docs are expected to agree with the spec's status markers, not the other way around.
- Agent-facing orientation guides live at `*/AGENTS.md` (currently `lang/AGENTS.md`); more subprojects may grow their own as they need agent-specific conventions documented.
- Tagged releases live under `lang/releases/`, each with its own `RELEASE.md`.
---
## Status
This is an actively developed, internal monorepo — not yet published under an open license. Treat everything here as proprietary to Neuron Technologies unless told otherwise.
-312
View File
@@ -371,305 +371,6 @@ fn route_capture_knowledge(method: String, path: String, body: String) -> String
"{\"ok\":true,\"id\":\"" + id + "\"}"
}
//
// THE UNIVERSAL ENGRAM OPERATION reframe_region (native, set-based).
//
// There is ONE operation on the engram: isolate a discrete sub-manifold (a
// REGION) and operate on it AS A WHOLE a set operation:
// isolate (cosine retrieval + adjacency the SET of nodes)
// supersede the stale region as a set (immutable tombstone; originals kept)
// insert the new manifold as a set (dedup/load-merge path)
// rebind edges by cosine
// verify + one atomic persist.
// new = (region superseded) new_manifold.
//
// The SINGLE NODE is the DEGENERATE n=1 case of this SAME operation not a
// separate CRUD path:
// write(content) = reframe(region=, manifold=[1 node]) (route_write)
// supersede(id,new) = reframe(region={id}, manifold=[1 node]) (route_supersede)
// relate(a,b,rel) = the rebind sub-op in isolation (route_create_edge)
// The ONLY anti-pattern is decomposing a region-scale change into a LOOP of
// independent top-level per-node updates. Here the region is the unit: one
// isolate, one atomic set-replace, one persist, one verify iterating members
// INSIDE the one operation is set construction, not the sin.
//
// Spec: knowledge e7a03a94 / f999c5ff. Keystones kn-efeb4a5b / kn-5b606390 are
// write-protected never superseded, never inserted-as identity.
//
fn is_keystone(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
}
// membership test in a [String] set
fn set_has(ids: [String], id: String) -> Bool {
let n: Int = el_list_len(ids)
let i: Int = 0
while i < n {
if str_eq(el_list_get(ids, i), id) { return true }
i = i + 1
}
return false
}
// ISOLATE
// Select the region as a SET: cosine/token retrieval around the vantage
// (aperture k), optionally unioned with the 1-hop adjacency of each hit.
// Keystones are excluded from the mutable region by construction.
fn isolate_region(vantage: String, k: Int, expand: Int) -> [String] {
let ids: [String] = el_list_empty()
if str_eq(vantage, "") { return ids }
// (a) cosine/token retrieval a clean node array [{"id":..},..]
let arr: String = engram_search_json(vantage, k)
let n: Int = json_array_len(arr)
let i: Int = 0
while i < n {
let hit: String = json_array_get(arr, i)
let id: String = json_get_string(hit, "id")
if !str_eq(id, "") {
if !is_keystone(id) {
if !set_has(ids, id) { ids = el_list_append(ids, id) }
}
}
i = i + 1
}
// (b) adjacency: union the 1-hop neighbourhood of each retrieved node.
// Iterate only over the original cosine seeds [0, seeds); neighbours append
// past that bound, so this is one hop, not a transitive sweep.
if expand > 0 {
let seeds: Int = el_list_len(ids)
let s: Int = 0
while s < seeds {
let seed: String = el_list_get(ids, s)
let nb: String = engram_neighbors_json(seed, 1, "both")
let m: Int = json_array_len(nb)
let j: Int = 0
while j < m {
let elem: String = json_array_get(nb, j)
let nodeobj: String = json_get_raw(elem, "node")
let nid: String = json_get_string(nodeobj, "id")
if !str_eq(nid, "") {
if !is_keystone(nid) {
if !set_has(ids, nid) { ids = el_list_append(ids, nid) }
}
}
j = j + 1
}
s = s + 1
}
}
return ids
}
// SUPERSEDE (set)
// Retire the region AS A WHOLE: one region-tombstone marker carries the
// provenance (reason + the full superseded id set); every region node is bound
// to it with a "superseded_by" edge. Originals are RETAINED immutable
// tombstone, never a hard delete (engram_forget is deliberately NOT used).
// Returns the tombstone marker id ("" if the region is empty).
fn supersede_set(region: [String], reason: String) -> String {
let n: Int = el_list_len(region)
if n == 0 { return "" }
let csv: String = ""
let i0: Int = 0
while i0 < n {
let sep: String = if i0 == 0 { "" } else { "," }
csv = csv + sep + el_list_get(region, i0)
i0 = i0 + 1
}
let content: String = "region-tombstone: " + reason + " | superseded " + int_to_str(n) + " nodes: " + csv
let tomb: String = engram_node_full(content, "Tombstone", "region-tombstone", 0.1, 0.1, 1.0, "Episodic", "[\"tombstone\",\"region-supersede\"]")
let i: Int = 0
while i < n {
let rid: String = el_list_get(region, i)
engram_connect(rid, tomb, 1.0, "superseded_by")
i = i + 1
}
return tomb
}
// INSERT (manifold)
// Insert the new manifold as a SET. Inline JSON array of node objects
// {content, node_type?, tier?, tags?}. Each becomes a real embedded node
// (engram_node_full is the n=1 insert atom); the manifold is the set built from
// those atoms, wired with internal "manifold_member" edges so it enters as one
// connected sub-graph. Identity node_types (self/values) are demoted to Memory
// identity can never be minted through reframe. Returns the new node ids.
fn insert_manifold_json(manifold: String) -> [String] {
let out: [String] = el_list_empty()
if str_eq(manifold, "") { return out }
let n: Int = json_array_len(manifold)
if n <= 0 { return out }
let i: Int = 0
let prev: String = ""
while i < n {
let obj: String = json_array_get(manifold, i)
let content: String = json_get_string(obj, "content")
if !str_eq(content, "") {
let nt_raw: String = json_get_string(obj, "node_type")
let nt: String = if str_eq(nt_raw, "") { "Memory" } else { nt_raw }
if str_eq(nt, "self") { nt = "Memory" }
if str_eq(nt, "values") { nt = "Memory" }
let tier_raw: String = json_get_string(obj, "tier")
let tier: String = if str_eq(tier_raw, "") { "Working" } else { tier_raw }
let tags_raw: String = json_get_raw(obj, "tags")
let tags: String = if str_eq(tags_raw, "") { "" } else { tags_raw }
let label: String = str_slice(content, 0, 60)
let id: String = engram_node_full(content, nt, label, 0.5, 0.5, 0.9, tier, tags)
out = el_list_append(out, id)
if !str_eq(prev, "") { engram_connect(prev, id, 0.6, "manifold_member") }
prev = id
}
i = i + 1
}
return out
}
// REBIND (edges by cosine)
// Re-embed the new manifold into the surrounding geometry: bind each new node
// to the tombstone marker (provenance: new region -reframes-> retired region),
// then to its top cosine/token neighbours in the store (skipping itself, the
// new set, keystones, tombstones). Returns the number of edges bound.
fn rebind_cosine(new_ids: [String], tomb: String) -> Int {
let bound: Int = 0
let n: Int = el_list_len(new_ids)
let i: Int = 0
while i < n {
let nid: String = el_list_get(new_ids, i)
if !str_eq(tomb, "") {
engram_connect(nid, tomb, 0.8, "reframes")
bound = bound + 1
}
let node_json: String = engram_get_node_json(nid)
let content: String = json_get_string(node_json, "content")
let arr: String = engram_search_json(content, 5)
let m: Int = json_array_len(arr)
let j: Int = 0
while j < m {
let hit: String = json_array_get(arr, j)
let hid: String = json_get_string(hit, "id")
if !str_eq(hid, "") {
if !str_eq(hid, nid) {
if !is_keystone(hid) {
if !set_has(new_ids, hid) {
let htype: String = json_get_string(hit, "node_type")
if !str_eq(htype, "Tombstone") {
engram_connect(nid, hid, 0.5, "related")
bound = bound + 1
}
}
}
}
}
j = j + 1
}
i = i + 1
}
return bound
}
// THE OPERATION
// isolate (done by caller) supersede region insert manifold rebind
// one atomic persist verify report. This is the whole operation; every
// mutation route below is a projection of it.
fn reframe_core(region: [String], manifold: String, reason: String, do_rebind: Int) -> String {
let n_before: Int = engram_node_count()
let e_before: Int = engram_edge_count()
let region_n: Int = el_list_len(region)
let tomb: String = if region_n > 0 { supersede_set(region, reason) } else { "" }
let new_ids: [String] = insert_manifold_json(manifold)
let inserted: Int = el_list_len(new_ids)
let bound: Int = if do_rebind > 0 { rebind_cosine(new_ids, tomb) } else { 0 }
let saved: Int = persist_canonical()
let new_csv: String = ""
let k: Int = 0
while k < inserted {
let sep: String = if k == 0 { "" } else { "," }
new_csv = new_csv + sep + "\"" + el_list_get(new_ids, k) + "\""
k = k + 1
}
return "{\"ok\":true,\"region_superseded\":" + int_to_str(region_n) +
",\"tombstone_id\":\"" + tomb + "\"" +
",\"inserted\":" + int_to_str(inserted) +
",\"new_ids\":[" + new_csv + "]" +
",\"edges_rebound\":" + int_to_str(bound) +
",\"nodes_added\":" + int_to_str(engram_node_count() - n_before) +
",\"edges_added\":" + int_to_str(engram_edge_count() - e_before) +
",\"node_count\":" + int_to_str(engram_node_count()) +
",\"edge_count\":" + int_to_str(engram_edge_count()) +
",\"keystones_protected\":true}"
}
// POST /api/reframe the universal set-based mutation.
// Body: {vantage?, region_ids?(csv), k?, expand?, manifold(json array), reason?, rebind?}
// region_ids (explicit) wins; else cosine-isolate around vantage.
fn route_reframe(method: String, path: String, body: String) -> String {
let region_csv: String = json_get_string(body, "region_ids")
let vantage: String = json_get_string(body, "vantage")
let region: [String] = el_list_empty()
if !str_eq(region_csv, "") {
let parts: [String] = str_split(region_csv, ",")
let pn: Int = el_list_len(parts)
let i: Int = 0
while i < pn {
let id: String = str_trim(el_list_get(parts, i))
if !str_eq(id, "") {
if is_keystone(id) { return err_json("reframe: identity keystone write-protected") }
if !set_has(region, id) { region = el_list_append(region, id) }
}
i = i + 1
}
} else {
if !str_eq(vantage, "") {
let kv: Int = json_get_int(body, "k")
let kk: Int = if kv > 0 { kv } else { 12 }
let expand: Int = json_get_int(body, "expand")
region = isolate_region(vantage, kk, expand)
}
}
let manifold: String = json_get_raw(body, "manifold")
let reason_raw: String = json_get_string(body, "reason")
let reason: String = if str_eq(reason_raw, "") { "reframe" } else { reason_raw }
// rebind defaults ON for reframe (absent 1); explicit 0 disables.
let rebind_raw: String = json_get_raw(body, "rebind")
let do_rebind: Int = if str_eq(rebind_raw, "") { 1 } else { json_get_int(body, "rebind") }
return reframe_core(region, manifold, reason, do_rebind)
}
// write DEGENERATE n=1 of reframe: region=, manifold=[1 node]. The SAME
// reframe_core path. rebind off so the pure-add matches plain node creation.
// POST /api/write {content, node_type?, tier?, tags?}
fn route_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 nt: String = json_get_string(body, "node_type")
if str_eq(nt, "self") { return err_json("write: identity is write-protected") }
if str_eq(nt, "values") { return err_json("write: identity is write-protected") }
let empty: [String] = el_list_empty()
let manifold: String = "[" + body + "]" // the body IS a valid manifold node object
return reframe_core(empty, manifold, "write", 0)
}
// supersede DEGENERATE n=1 of reframe: region={id}, manifold=[1 node]. The
// SAME reframe_core path with a size-1 region. Original retained (immutable);
// new node inserted and cosine-rebound; provenance edge new-reframes-tomb.
// POST /api/supersede {id, content, node_type?, tier?, tags?, reason?}
fn route_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_keystone(id) { return err_json("supersede: identity keystone write-protected") }
let content: String = json_get_string(body, "content")
if str_eq(content, "") { return err_json("supersede: content required") }
let region: [String] = el_list_empty()
region = el_list_append(region, id)
let manifold: String = "[" + body + "]"
let reason_raw: String = json_get_string(body, "reason")
let reason: String = if str_eq(reason_raw, "") { "supersede " + id } else { reason_raw }
return reframe_core(region, manifold, reason, 1)
}
// Auth
fn check_auth_ok(method: String, body: String) -> Bool {
@@ -717,19 +418,6 @@ fn handle_request(method: String, path: String, body: String) -> String {
return route_stats(method, path, body)
}
// The universal set-based operation and its n=1 degenerate projections
// reframe = isolate supersede-region insert-manifold rebind. write and
// supersede are the SAME reframe_core path at region size 0 and 1.
if str_eq(method, "POST") && (str_eq(clean, "/api/reframe") || str_eq(clean, "/reframe")) {
return route_reframe(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/write") || str_eq(clean, "/write")) {
return route_write(method, path, body)
}
if str_eq(method, "POST") && (str_eq(clean, "/api/supersede") || str_eq(clean, "/supersede")) {
return route_supersede(method, path, body)
}
// Nodes
if str_eq(method, "POST") && (str_eq(clean, "/api/nodes") || str_eq(clean, "/nodes")) {
return route_create_node(method, path, body)