bef36a5e3a0d842c1e64adb5e99fc3accce3ad48
20 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bef36a5e3a |
feat(soul): Stage 1 structural audit as a real route — an annotated characterization, not a score (#91)
`runStructuralAudit` has been an advertised MCP tool with nothing behind it: the
dispatcher GET'd /session/begin and returned that unrelated session digest under
an audit tool's name. Meanwhile the failure the audit would have caught ran
silently for about three weeks — the soul reporting 103,089 nodes while the
engram, which OWNS persistence, held ~79,900, a crash discarding the difference,
and every boot reporting green throughout, because nothing in the system ever
compared the two sides.
WHAT THE PATENT SPECIFIES, AND HOW IT SHAPED THIS
CGI provisional, 05-detailed-description.md, "Stage 1: Structural audit 430".
Two clauses did the design work. First the four things the module evaluates:
the density and typed distribution of causal edges; value/execution-record
consistency; the richness and connectivity of the self-model; and wonder-
manifest authenticity. Second, and decisively: it "produces a coherence
assessment 432 — NOT A BINARY SCORE but an annotated characterization of the
graph's structural properties."
So every finding carries its numbers AND a plain-language note saying what
they mean and how they were obtained. There is no pass/fail and no composite
health figure, and `"score":null` is emitted explicitly so a reader cannot
mistake its absence for an omission.
WHAT IS IN STAGE 1 (four findings)
owner_runtime_divergence — the motivating case. Runtime counts vs the owner's
own GET /api/stats, the delta, and the trend against the previous audit, so
a second call answers "is the gap growing?" rather than restating it.
self_model_connectivity — the three identity pillars plus the self root:
present, content length, one-hop degree. This RETIRES the Claude-side vitals
identity block, which lived outside the system it was checking and went on
reporting green while the memory-philosophy pillar was absent from the live
graph. Asking the running soul is the designed mechanism; a shell probe was
the fourth patch on the same hole.
typed_edge_distribution — exact counts against the claim-10 vocabulary, plus
density, plus a separate count of LOWERCASE near-misses ("causes" vs
"Causes"): "the vocabulary is unused" and "the vocabulary is misspelled by
the write paths" are different defects with different fixes.
orphans_and_dangling_edges — the tool's own long-standing promise.
WHAT IS DEFERRED, AND WHY IT IS DATA RATHER THAN A COMMENT
Value/execution-record consistency and wonder-manifest authenticity ship as a
`deferred` array that MEASURES the populations they would need (Prediction and
WonderQuestion nodes) and reports those counts as the reason. Both are ~0 today
— WonderQuestion because of a known write/read node-type mismatch. Asserting
value coherence or a pull-weight correlation on an empty population would be a
fabricated result, which is worse than a stated gap.
MEASUREMENT HONESTY: EXACT WHERE CHEAP, SAMPLED WHERE NOT, ALWAYS LABELLED
Counts, edge typing and self-model connectivity are exact. Orphan and dangling
rates are sampled, because engram_find_node_index is a linear scan — an
exhaustive dangling check is O(nodes x edges), ~2.2e9 string compares at today's
scale. Samples are UNIFORM across the whole population (str_index_of_all gives
every edge offset in one pass, so any index is O(1); json_array_get would have
been O(n^2)), never head-of-list, and each figure ships with its own sampled /
population / exhaustive fields. ?edge_sample= and ?node_sample= at population
size run either check exhaustively. The real fix is an id index in the runtime.
ONE BUG THIS FOUND IN ITSELF, CAUGHT IN TEST
http_get does not return "" when the owner is unreachable — it returns a JSON
error object. Testing only for "" made a DEAD owner read as reachable with
node_count 0, so the audit reported 100% divergence and named it data loss.
Reachability is now proved by the presence of the node_count field, and the
owner's raw reply is attached. A confident wrong answer is exactly what this
route exists to stop.
Edge findings need relation labels and the runtime has no edge-enumeration
builtin, so they use the same scratch export GET /api/graph/edges already uses
(engram_save to TMPDIR, never the owner's canonical file — #117). That is a
large write on a large graph, so this is a manual route, not a timer; ?edges=0
skips it.
neuron-api.el:900-1273 handler + helpers
routes.el:567,752 GET and POST /api/neuron/audit/structural
mcp-wrapper/src/main.el:113,682 tool description + dispatch off /session/begin
dist/soul.c regenerated (1255 bodies)
Rung: E2E-VERIFIED. Soul built from this branch (gen-soul-amalgam + cc-brain,
921,192 bytes, 16 warnings, 0 errors), booted on throwaway ports 7893/7896/7897
with throwaway HOMEs against a stub owner on 7894. Three scenarios pass: owner
reachable (runtime 62 vs owner 42, delta 20 / 32.2%, trend flat on the second
call; 12/20 edges claim-10 typed, 3 lowercase near-misses; 50/62 orphans, 3/20
dangling — every figure matches the fixture by construction), owner unreachable
(reported as a finding with the raw reply, not a crash), and file mode (owner
"none", divergence undefined). Reached end-to-end through the MCP tool via a
locally built wrapper. verify-soul-contract.sh: GATE PASS, 27/27 routes +
immutability. No process left running; live :7770 and :8742 untouched (GET only).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
dd952c0e46 |
feat(soul): write-through to the persistence owner — memories survive restart (#117)
The soul obeys half of its own ownership rule. soul.el:571-573 says "when
ENGRAM_URL is set the HTTP Engram owns persistence — the soul must NEVER write
to the local snapshot", and it doesn't. But nothing was ever built to hand the
soul's writes TO that owner: sync is pull-only (/api/sync -> engram_load_merge),
so every node created inside the soul lived in process RAM and was shed on
restart. Measured live 2026-08-07: soul node_count=102184, engram 79197.
SCOPE CORRECTION vs the earlier internal spec: engram provisional claim 17's
"pull-then-push" is a PEER-ENGRAM to PEER-ENGRAM protocol (claims 15-18 say so
explicitly). The soul is a CALLER of the database API, not a peer. Claim 17 is
NOT authority for a soul<->engram contract and is no longer cited as such. The
design here follows from the ownership rule alone.
Mechanism: a new Accessor, persist.el, is the single boundary. Writes stage a
delta to a filesystem spool and are pushed to the owner via POST /api/load-merge
— NOT POST /api/nodes, which mints a new server-side id (breaking dedup and
edges) and drops label/tier/tags/importance/confidence (verified in a sandbox:
a tier "Canonical" probe came back "Working"). load-merge preserves the id and
every field, dedups nodes by id and edges by (from,to,relation) so retries are
no-ops, and calls persist_canonical() so THE OWNER writes its own file — the
ownership rule is honoured rather than worked around.
Spool-and-drain rather than push-per-write: measured ~0.38s per load-merge at
live scale (79k nodes/176MB), and a chat turn writes 5-7 nodes. The spool is on
disk, not in process state, because the soul serves each connection on its own
pthread and a shared buffer would lose entries to a read-modify-write race. That
also buys crash recovery: writes orphaned by kill -9 are drained on next boot.
Honesty: api_persisted (the gate all 10 MCP write handlers pass through) and
mem_store now assert AT THE OWNER instead of reading back the soul's own RAM.
With the owner down a write returns {"ok":false,"error":"write_not_persisted"}
and the delta is queued — where main returns {"ok":true} for a write that dies.
Coverage: 35 node sites + 9 edge sites routed through the boundary. Deliberately
excluded, with reasons in persist.el: 4 InternalStateEvent sites (Will's own
telemetry carve-out), the boot counter and the persona (both already have
bespoke owner-side write-backs), and soul.el's 54 genesis identity edges
(file-mode only). engram_strengthen and engram_forget are NOT propagated —
load-merge cannot update or delete, and hard-deleting at the owner would fail
verify-soul-contract.sh section B.
Also fixed here:
- routes.el GET /api/graph/edges engram_save()'d straight over the owner's
canonical snapshot.json — a read route, in a non-owner process, clobbering the
canonical on every call. Same defect class Will removed from the engram in el
dc39a61. Now exports to a scratch path. With this gone the soul writes nothing
at all in HTTP mode.
- persist.el must clear the runtime's _tl_fs_read_len hint after every fs_read.
In vendored runtime v1.0.0-20260501 that hint becomes the NEXT response's
Content-Length, so reading a spool file mid-request made an 86-byte reply go
out as 497 bytes with 411 bytes of adjacent heap trailing it. Caught and fixed
at our boundary; the runtime class was fixed upstream in el 43636ae, which is
not the pinned runtime here.
Rung: E2E-VERIFIED, discriminating. Same harness, same engram binary:
write-through: LEG 1 PRESENT at owner, LEG 2 SURVIVED kill -9 + restart
main: LEG 1 ABSENT at owner, LEG 2 LOST
verify-soul-contract.sh: GATE PASS on both builds (27/27 routes, immutability).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
8ba35a0d56 |
reconcile: merge Will's self-review WIP (456267a) into main
Union of all ship-critical soul fixes for the Mac beta: - Keeps main's honest receipts (#100/#101), immutability arc + #199 by-id gate (#83), Track B threat routing (#76), bounded beginSession (#103), CI hardening (#85/#86), elc typo hotfix (#77), neuron-dev-setup (#84). - Brings WIP's genesis-boot SIGSEGV fix (#150/#95), safety-contact 988 truncation fix (#96), bounded-persona floor (#93), and 10 self-review commits (importance flattening, curiosity DF gating, WM/heartbeat observability, boot-counter telemetry). - Folds the multi-word ranked-search fix: api_query_param now url_decode()s the extracted value so q=foo%20bar / foo+bar tokenize as two words. Conflicts (neuron-api.el payload-bound comments, mcp-wrapper tool_forget) resolved toward the correct end state: main's verified honest-receipt read-back is kept; WIP's improved forget description is kept. Generated dist/*.c taken from main and will be regenerated from this reconciled source in the following commit. |
||
|
|
9bbb4f2af8 |
Bound beginSession/compileCtx payloads to a compact digest
Port the payload-bounding fix (PR #102, commit
|
||
|
|
456267a771 |
self-review 2026-08-01: fix importance flattening in remember/evolve/cultivate paths
Four sites passed the Float local 'sal' through el_from_float() a second time. el_val_t is the bit-pattern of the double, so re-wrapping performs an int64->double VALUE conversion of the bits before re-bitcasting — garbage that fails engram_decode_score's range check and clamps to defaults. Net effect: importance="critical" stored 0.5/0.5 — importance levels were cosmetic on the MCP memory path. Verified fixed live: critical now stores salience/importance 0.95/0.95. Same bug fixed today in engram server.el route_create_node (foundation/el 7f03876). Literal wraps (el_from_float(0.9)) are safe — elc passes numeric literals raw. |
||
|
|
872120c757 |
Bound beginSession/compileCtx payloads to a compact digest
The session-init endpoints concatenated unbounded engram activate/scan
results as FULL node objects (content up to ~90KB per node), producing a
~900KB response. After the MCP wrapper re-escapes that into a stringified
text block the client dropped the socket ('connection closed unexpectedly')
on every beginSession call. Cap each list (8-10 activated, 10-20 recent)
and project every node to a light identity plus a bounded, UTF-8-safe
content snippet. Response drops from ~900KB to ~12KB; full content stays
available on demand via recall/fetch/inspectGraph.
|
||
|
|
b0f4d6c493 |
self-review 2026-07-30: auto_term stopword filter, real idle_ms, bounded beginSession
- awareness.el: curiosity auto_term was the raw first word of a WM label with no term-quality scoring — observed seeds included What, Colon, Prose, Context. Replaced the 7-word genre blocklist whack-a- mole with a delimited stopword membership test (function words + document-structure words); topical terms pass untouched. Verified live: seeds now ReasonEdit, Reasoning-model, Self-review. - routes.el + awareness.el: idle counter only reset on rare inbox synthesis-requests, so idle==pulse always (zero information). handle_request now stamps soul.last_activity_ts on every inbound HTTP request; heartbeat emits idle_ms = ms since last request (-1 until first request of a boot). - neuron-api.el: beginSession concatenated a depth-2 spread plus the unbounded self-hub neighbor dump — multi-MB response, doubled by wrapper re-escaping, socket died on every call. Now depth-1 and the hub dump dropped (identity loading has its own tool). Verified: beginSession returns instead of closing the socket. |
||
|
|
9e59c51f3c |
self-review 2026-07-23: title-derived Knowledge labels + Knowledge admitted to curiosity auto-term
Sentinel labels (knowledge:captured/evolved/canonical) made every capture anonymous in WM telemetry — 35 identical wm_top entries — and starved the curiosity auto-term seeder, which derives scan seeds from WM top-10 labels and had returned empty on every scan since boot 6 because WM became Knowledge-dominated while Knowledge was excluded from seeding. - capture/evolve/promote now pass title (or empty → engram_node_full's content[:60] derivation) instead of sentinels - auto_term_try_slot admits Knowledge slots; sentinel-shaped labels (colon, no space) are skipped so legacy nodes cannot seed 'knowledge' - verified: probe capture labeled 'Label derivation probe 2026-07-23' |
||
|
|
091cc1fc0e |
Fix issue #150: fresh-install genesis boot SIGSEGV in mem_save
A fresh-install (SOUL_CGI_ID=ntn-genesis) boot crashed with
"Segmentation fault: 11" right after the http server came up — a real
customer's very first boot. Backtrace:
strcmp(0x1) <- str_eq (el_runtime.c:219) <- mem_save <- awareness_run
Root cause: the el runtime's engram_save returns an Int (1 = ok, 0 =
failure), but mem_save did `str_eq(engram_save(path), "")`, treating the
return as a String. str_eq runs EL_CSTR on it, which is a raw cast:
EL_CSTR(1) = (char*)0x1. On a SUCCESSFUL save (return 1) strcmp then
dereferences 0x1 and segfaults. Genesis is the first path that both seeds
the brain AND saves it successfully on the very first awareness pass, so it
crashes there; non-genesis boots (contract gate, refusal test) don't hit a
successful early mem_save, which is why they passed. handle_api_consolidate
had the identical latent bug.
Fix: read engram_save's Int result and compare `== 0` instead of str_eq'ing
it — in mem_save (memory.el) and handle_api_consolidate (neuron-api.el).
Regression: pre-existing, NOT introduced by the immutability/floor rebuild.
The pre-immutability build (
|
||
|
|
6527988eb9 |
Make engram deletes/updates/forgets immutable on the launch branch
The ship-soul builds from this branch, which has the bounded-persona floor (#93) but never received the tombstone/supersede immutability fix (that went to main; hotfix diverged before it). So the launch soul failed verify-soul-contract IMMUTABILITY on the delete/update/forget routes — they hard-removed engram nodes via engram_forget/mem_forget. Apply the same fix, mirroring the knowledge routes' supersede pattern: - node/update -> create new node + "supersedes" edge to the original, KEEP the original (no engram_forget). - node/delete, memory/delete, memory/forget, cultivate forget, and the autonomous awareness forget -> TOMBSTONE via the canonical mem_tombstone (memory.el): keep the node + its edges, record a Tombstone marker, hide from default bounded list reads (?include_deleted recovers). Never engram_forget. The MCP forget tool now routes to the tombstoning delete instead of faking a delete. Internal GC that genuinely removes transient nodes (awareness inbox-trigger consume, consolidation dedup, session-summary replace, telemetry pruning) still calls engram_forget directly and is unchanged. Regenerated dist/soul.c (single-TU) + per-module dist/{memory,awareness, neuron-api}.c from THIS branch's sources under a 3GB physical-RSS watchdog (peak ~32MB), built against the release el_runtime (v1.0.0-20260501). The bounded-persona floor is preserved — verified in the emitted C and the linked binary (BOUNDED PERSONA / SOUL_PERSONA_NAME strings present). verify-soul-contract.sh: GATE PASS — PRESENCE all 27 routes, IMMUTABILITY 5/5 KEPT (memory-update, memory-delete, node-update, node-delete, memory-forget). |
||
|
|
40d800195a |
Tombstone the remaining forget paths (close the immutability arc)
Phase 1 tombstoned memory/delete + node/delete, but the generic forget
path was still destructive. This routes every forget through the same
tombstone semantics so nothing in the daemon can hard-delete an engram
node anymore.
Canonical helper: mem_tombstone (memory.el, imported first so every module
can call it) — keep the node + its edges, record a Tombstone marker, never
engram_forget. neuron-api's tombstone_node now delegates to it (single
source of truth).
Per-path before -> after:
- memory.el `mem_forget` hard delete (engram_forget) -> tombstone. This
alone fixes both callers: the /api/neuron/memory/forget route
(handle_api_forget) and the cultivate op=="forget".
- awareness.el autonomous `forget` action engram_forget -> mem_tombstone.
The soul can no longer autonomously hard-delete a memory.
- mcp-wrapper tool_forget was a FAKE no-op that returned {"ok","deleted"}
without deleting OR tombstoning -> now routes to the soul's tombstoning
/api/neuron/memory/delete; tool description fixed to say it
supersedes/tombstones (recoverable), not "Remove a node".
Left intentionally as hard deletes (internal GC / lifecycle, not user
memory, all call engram_forget directly): session-summary replace
(chat.el), mem_consolidate dedup (memory.el), session-start telemetry
pruning (soul.el), session lifecycle (sessions.el).
Regenerated both ship paths under a 3GB physical-RSS watchdog (peak ~32MB):
dist/soul.c (single-TU amalgamation, macOS/Linux) and the per-module
dist/{memory,awareness,neuron-api}.c (Windows/Linux build). Verified: no
forget handler calls engram_forget; a forget leaves the node present +
tombstone marker. Gate (neuron-ui verify-soul-contract.sh, new memory-forget
row): PRESENCE + IMMUTABILITY PASS.
|
||
|
|
d337fcb265 |
Make engram deletes/updates immutable (tombstone + supersede)
The soul was hard-deleting engram nodes: memory/delete and node/delete called engram_forget (frees the node and drops its incident edges), and node/update created a replacement then forgot the original with no link back. That violates the day-one rule that engram nodes are immutable — memory could be silently, irrecoverably destroyed via the API. Convert the three destructive handlers to Will's immutability semantics, mirroring the pattern memory/update and knowledge evolve/promote already use: - node/update -> create the new node, wire a "supersedes" edge new->old, KEEP the original. No engram_forget. (Was: create + forget old, no edge.) - memory/delete and node/delete -> TOMBSTONE: keep the node AND its edges, create a Tombstone marker node (content = target id, label "tombstone:<id>") wired with a "tombstones" edge. Never engram_forget. Default bounded list reads (handle_api_list_typed / the memory list) hide tombstoned nodes and the markers; ?include_deleted=1 returns them, and internal cognition + /api/graph/nodes still traverse them. memory/update was already correct and is unchanged. Full-graph hiding on /api/graph/nodes is deliberately NOT done at the el layer: json_array_get is O(index), so filtering that endpoint (called with limit up to 999999) would be O(n^2). That hide needs a runtime scan filter and is a separate follow-up; nodes there remain traversable, tagged status:deleted via the marker edge. Regenerated dist/soul.c from these sources (flat single-TU amalgamation, compiled under a 3GB physical-RSS watchdog, peak ~32MB). Verified with scripts/verify-soul-contract.sh in neuron-ui: PRESENCE passes (all 27 routes) and IMMUTABILITY passes (all four mutation routes KEPT; deletes produce a real tombstone marker and hide from the default list). |
||
|
|
51bea5507b |
prevent engram corruption: idempotent boot seeding, session-start event cap
Fix 1: mem_boot_count_inc prunes all existing soul:boot_count nodes before
inserting the new one — keeps exactly one boot counter node instead
of accumulating a new node per boot. Also fixes a latent ordering
bug where engram_search_json oldest-first results caused the counter
to read stale (low) values once >3 copies accumulated.
Fix 3: handle_api_node_delete comment clarified — the no-verify exception
is correct for deletes (not a write path); read-back-verify is for
writes only.
Fix 4: emit_session_start_event prunes old session-start InternalStateEvent
nodes after each boot, keeping the 10 most recent and forgetting
older ones. Prevents unbounded accumulation of ~120+ copies.
|
||
|
|
dcc0bf550a |
Add Ollama provider, portable memory, cultivation digest, refugee importer, GLM-OCR spike
- P0: unified soul binary with engram_node_full fix, read-back-verify, search fix - P0: move API keys from plaintext plists to macOS Keychain - P0: fix MCP backend URL (port 8742 → 7770) - P1.6: memory-export/import scripts (AES-256-CBC, versioned .neuronmem format) - P1.7: nightly cultivation digest with sharpness metric (launchd at 23:55) - P2.10: Ollama provider in agentic loop (SOUL_LLM_PROVIDER=ollama) - P3.12: refugee importer for ChatGPT/Screenpipe/generic formats - P3.13: GLM-OCR spike — SHIP IT (mlx-vlm, 1.59GB, photo-to-memory.sh) |
||
|
|
494d973a3b |
fix(reliability): engram-write — guard all fire-and-forget writes
Neuron Soul CI / build (pull_request) Has been cancelled
Every engram_node_full call that dropped its return value now binds it and emits a println on empty string. engram_save calls in consolidate, heartbeat, and dharma-room-turn are checked for failure. The two API handlers (log_state_event, tune_config) that skipped api_persisted() now match the read-back-after-write contract used everywhere else in neuron-api.el. Files changed: - chat.el: conv_history_persist, handle_dharma_room_turn, auto_persist - soul.el: emit_session_start_event, seed_persona_from_env HTTP check - memory.el: mem_save, mem_boot_count_inc - neuron-api.el: handle_api_log_state_event, handle_api_tune_config, handle_api_consolidate (engram_save + session summary write) - awareness.el: ise_post local-engram fallback path TODO comments added for non-atomic patterns (issues #12, #13) and the missing circuit breaker (#14) — these require new primitives. |
||
|
|
8b692e4666 |
fix/test: PR #21 review — guard, safety Bell, api write-back, temp paths
Neuron Soul CI / build (pull_request) Failing after 13m22s
fix(soul): add HTTP-engram guard to safe_to_seed — when ENGRAM_URL is set the HTTP Engram owns persistence; genesis must never save to local snapshot regardless of node counts (was: guard_disk forced to empty string, making the ratio check vacuously true and allowing init_soul_edges+engram_save). fix(soul): use multiplication form for ratio guard — node_count * 16000 < disk_len avoids floor-division truncation that underestimated boundary files (250KB / 16000 = 15.6, floors to 15; a 15-node graph wrongly passed old guard). fix(chat): add safety_augment_system to handle_chat_as_soul, handle_dharma_room_turn, and handle_dharma_room_turn_agentic — all three called the LLM without Hard Bell evaluation, leaving users in dharma rooms without crisis resource routing. fix(neuron-api): add api_persisted read-back to handle_api_define_process — was the only write handler that returned ok:true without verifying the node was actually written to engram. fix(routes): unique temp file path in connectd_post — replaces fixed /tmp/neuron-connectors-req.json with a timestamped path to prevent collision if concurrency is added or two soul instances share a machine. test: add tests/test_bell_safety.el — covers safety_detect_bell_level (none/soft/hard), safety_classify_hard_bell (abuse/self_harm routing), safety_normalize (smart-quote), safety_augment_system, and handle_safety_contact_post (validation + read-back). test: add tests/test_soul_guard.el — pure-function logic tests for the safe_to_seed predicate: 200KB boundary, 47MB/63-node clobber scenario, HTTP-engram mode, multiplication vs division truncation at 250KB. test: add tests/test_api_define_process.el — verifies the define_process write is read-back verified after the fix. |
||
|
|
6d8a992716 |
feat(soul): add safety module, expand connectors API, memory-recall bug notes
- safety.el/.elh: new safety module - neuron-api.el, routes.el, soul.el, chat.el: connectors API expansion - regenerated dist/ C artifacts - MEMORY_RECALL_BUG.md: investigation notes Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
05ca125ecc |
api: add /api/neuron/memory/delete and /api/neuron/memory/update for UI memory CRUD
Neuron Soul CI / build (pull_request) Failing after 4m48s
The UI needs full memory CRUD; the soul had create (handle_api_remember)
and the older /memory/forget + /memory/evolve, but no endpoints matching
the UI's delete/update contract.
POST /api/neuron/memory/delete {"id"}
Hard delete. engram_forget is a true delete primitive (removes the node
and all incident edges from the engram store), so no soft-delete
fallback is needed. Unlike /memory/forget, this checks the node exists
first - engram_forget silently no-ops on unknown ids, and a bad id must
return an error, not fake success. Protected identity/values nodes are
blocked, same as the other accumulation-path handlers.
POST /api/neuron/memory/update {"id","content"}
Evolve-style update. The engram runtime has no in-place node mutation
primitive (only node-create, strengthen, forget, connect), so update
creates a new Memory node and wires a supersedes edge to the prior one,
same pattern as handle_api_evolve_knowledge. Unlike /memory/evolve, id
is required and must reference an existing node; create+link delegates
to handle_api_evolve_memory. Returns {id, supersedes, ok}.
Both files syntax-checked with elc --target=c (exit 0, no stderr).
Compile-verified only - local builds cannot run the soul; needs Will's
build for runtime verification.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
6a27fd231e |
feat(neuron-api): add identity/values write protection
Block evolve_knowledge, evolve_memory, forget, and link_entities (to_id
direction) from modifying the 15 hardcoded identity and values node IDs.
Returns HTTP 403 with a hint to use the cultivation path instead.
Add POST /api/neuron/cultivate — the bypass endpoint for intentional
cultivation sessions. Accepts { "operation": "...", ...args } and performs
the same operations without the protection check.
Add handle_api_forget and handle_api_evolve_memory as new protected-by-
default handlers, routed at /api/neuron/memory/forget and
/api/neuron/memory/evolve respectively.
Tested: 10 verification cases — 403 on all blocked targets, 200 on
non-protected nodes and FROM-direction links, cultivate bypass confirmed.
|
||
|
|
ffadafb0bf |
soul: native cognitive API — port all MCP logic to soul daemon
neuron-api.el is a new first-class El module that implements all Neuron cognitive API handlers natively — no HTTP round-trips, no MCP wrapper, direct engram builtin calls. All capabilities that previously lived in the MCP wrapper adapter now live here in the soul. Handlers: begin_session, compile_ctx, remember, recall, search_knowledge, browse_knowledge, capture_knowledge, evolve_knowledge, promote_knowledge, browse_processes, define_process, log_state_event, list_state_events, inspect_config, tune_config, inspect_graph, link_entities, list_typed, consolidate. Routes wired in routes.el under /api/neuron/* (GET + POST). Also compiles all loop-1/loop-2 .el source changes into dist/*.c and rebuilds the binary. memory.elh and neuron-api.elh updated with new exports. |