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.
- 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.
- engram refresh URL now resolves env -> state -> localhost:8742, same
hardening ise_post got after the boot-4 blackout. Previously a corrupted/
empty soul_engram_url state key silently disabled sync forever while
heartbeats kept flowing — WM starves of Knowledge nodes with no outward
sign.
- heartbeat ISE: node_delta, edge_delta (growth vs stall vs flood is now
one field, not cross-ISE forensics), sync_age_ms from a new
soul.last_sync_ok_ts stamp (-1 = never; >> SOUL_REFRESH_MS = refresh
path broken). Verified live: pulse 1 sync_age_ms=-1, sync fired +1.6s,
age counts up between syncs.
- PR #60: inject operator home dir into system prompt (#30)
Adds OPERATOR IDENTITY section so the LLM correctly resolves
'my files/notes/desktop' to the actual running user's $HOME.
Prevents identity confusion between imprint author and operator.
- PR #61: plan-mode endpoint POST /api/chat {mode:'plan'} (#27)
Adds handle_chat_plan — returns {steps:[{id,title,detail}]} JSON.
Wired into all three /api/chat route handlers. Grounds the plan
via engram_compile (same as agentic path) for context awareness.
dist changes:
- soul.c: both PRs compiled in; build_system_prompt updated to
2-param signature (ctx, chat_mode); handle_chat_plan added
- chat.c/routes.c/chat.elh: individual module outputs updated
- elp-c-decls.h: remove stale 1-param build_system_prompt decl,
add handle_chat_plan declaration
- soul.elh.c: new soul header declarations file (from PR #60)
Compile verified: cc -O2 -DHAVE_CURL soul.c el_runtime.c -lcurl
Binary: 805K arm64, smoke test passes (port in use = expected).
neuron.c and routes.c were compiled against the old 1-arg soul interface.
chat.c already uses the 2-arg signature. The Windows cross-compile build
generates elp-c-decls.h from all dist/*.c files, causing a conflicting-types
error when both signatures appear. Recompile these modules against the
current soul API to eliminate the conflict.
Linked against dev runtime with is_knowledge fix that adds Knowledge
node type. Engram goal_bias now gives Knowledge nodes +0.3 boost on
technical queries, consistent with how Belief/DharmaSelf/Safety nodes
are already treated. Same el_runtime source as concurrent foundation/el
commit 16d62bd.
proactive_curiosity() now uses the top working-memory node's first label
word as a 4th activation seed alongside the 4 rotating fixed sets. This
breaks deterministic exploration that was reinforcing the same subgraph
every cycle and creates a self-referencing loop: curiosity radiates from
whatever is most salient right now, mirroring the brain's default-mode-
network resting-state dynamics. str_find_chars on " :([" extracts the
first meaningful word; sp > 3 guards against bracket-prefixed labels.
auto_term field added to curiosity_scan ISE for observability.
Ollama availability is a silent failure mode: when the embedding service
is down, semantic seed injection falls back to lexical-only activation with
no signal in the ISE stream. Add embed_ok field (0/1) to every heartbeat
by probing http://localhost:11434 — makes Ollama health visible without
a separate monitoring path.
state_get() returns "" for unset keys. Both soul.pulse and soul_boot_count
could be empty on first heartbeat cycle, producing invalid JSON like
{"event":"heartbeat","pulse":,"boot":,...}. Add defensive guards:
if str_eq(raw, "") { "0" } else { raw } for both fields.