Commit Graph

137 Commits

Author SHA1 Message Date
will.anderson 33c377410d Merge pull request 'feat(soul): Layer 1 — safety.el' (#8) from feat/layer-safety into main
Deploy Soul to GKE / deploy (push) Failing after 35s
Neuron Soul CI / build (push) Failing after 6m20s
2026-06-11 17:14:40 +00:00
will.anderson af933494a9 Merge pull request 'feat(soul): Layer 2 — stewardship.el' (#7) from feat/layer-stewardship into main
Deploy Soul to GKE / deploy (push) Failing after 36s
Neuron Soul CI / build (push) Failing after 7m16s
2026-06-11 17:14:32 +00:00
will.anderson 72751c3833 Merge pull request 'feat(soul): Layer 3 — imprint.el' (#6) from feat/layer-imprint into main
Deploy Soul to GKE / deploy (push) Failing after 38s
Neuron Soul CI / build (push) Failing after 7m32s
2026-06-11 17:14:16 +00:00
will.anderson 195cc9dc66 Merge pull request 'test(soul): Layer 1 safety.el test suite' (#10) from test/layer-safety into feat/layer-safety
Neuron Soul CI / build (pull_request) Failing after 5m53s
2026-06-11 17:13:50 +00:00
will.anderson 4b648f3291 Merge pull request 'test(imprint): add 14-case test suite for Layer 3 imprint boundary' (#11) from test/layer-imprint into feat/layer-imprint
Neuron Soul CI / build (pull_request) Failing after 7m54s
2026-06-11 17:13:49 +00:00
will.anderson ffd1f34344 Merge pull request 'test(soul): integration and contract tests for layered_cycle' (#13) from test/layer-composition into feat/layer-composition
Neuron Soul CI / build (pull_request) Failing after 7m47s
2026-06-11 17:13:48 +00:00
will.anderson 084bee9f0f Merge pull request 'test(stewardship): comprehensive test suite for Layer 2 — 35 cases' (#12) from test/layer-stewardship into feat/layer-stewardship
Neuron Soul CI / build (pull_request) Failing after 8m14s
2026-06-11 17:13:43 +00:00
will.anderson a8027e9c00 feat(soul): wire steward_session_check into layered_cycle — continuity + behavioral profiling
Neuron Soul CI / build (pull_request) Failing after 6m2s
2026-06-11 12:13:19 -05:00
will.anderson df2c7409c0 feat(steward): behavioral profiling and continuity detection — drift, discontinuity, identity anomaly
Neuron Soul CI / build (pull_request) Failing after 3m38s
2026-06-11 11:58:43 -05:00
will.anderson bebf1f8c86 fix(soul): address review issues in feat/layer-composition
Neuron Soul CI / build (pull_request) Failing after 6m5s
- Add stub implementations of safety.el, stewardship.el, and imprint.el
  with their .elh headers so the branch compiles without the dependency
  branches (feat/layer-safety, feat/layer-stewardship, feat/layer-imprint).
  Each stub documents the layer contract it must satisfy when replaced.

- Fix GET /api/chat bypass: update the GET branch in handle_request to
  call layered_cycle() consistently with the POST branch, rather than
  calling handle_chat() directly and skipping the consciousness stack.

- Export layered_cycle() from soul.elh (and dist/soul.elh) so routes.el
  can resolve the symbol via the header import.

- Fix steward_action else branch: add explicit handling for "block"
  (returns safe refusal immediately, skips L3) and "redirect" (uses
  redirect_to field). Unknown actions now log a warning and fall back to
  the screened input rather than silently passing an empty string to
  imprint_respond().

- Document hard_bell path: clarify that omitting auto_persist/history
  update is intentional security isolation, and document the safety_validate
  second-param sentinel contract ("hard_bell" vs screen_action).
2026-06-11 11:47:45 -05:00
will.anderson 63968cd224 fix(stewardship): address review issues in feat/layer-stewardship
Neuron Soul CI / build (pull_request) Failing after 6m38s
- steward_log_event (line 14): add println after let discard so the
  function's last expression is Void, fixing the type mismatch on a
  Void-declared function
- steward_get_mission (lines 40-43): remove non-Config fallthrough that
  allowed any Episodic/Working node to silently override the mission;
  only Config nodes are now authoritative
- steward_align signal_deceive (line 56): widen 'deceive the user' to
  'deceive' to catch variants like 'deceive users', 'deceive them', etc.
- steward_align signal_hide (line 57): tighten 'hide from' to
  'hide from the user' to eliminate false positives on legitimate inputs
  like 'hide from a background process' or 'hide from view'
- stewardship.elh: document that steward_log_event is an internal helper
  exported only because El has no access modifiers; callers should not
  invoke it directly
2026-06-11 11:46:56 -05:00
will.anderson db2ee387a4 fix(soul): address review issues in feat/layer-safety
Neuron Soul CI / build (pull_request) Failing after 6m47s
2026-06-11 11:46:43 -05:00
will.anderson 749b60c6e8 fix(soul): address review issues in feat/layer-imprint
Neuron Soul CI / build (pull_request) Failing after 5m44s
2026-06-11 11:46:31 -05:00
will.anderson d097455d6a test(soul): integration and contract tests for layered_cycle composition
Adds tests/test_layered_cycle.el — 12 integration tests covering the full
L1→L2→L3→L1 stack: benign pass-through, hard-bell short-circuit, soft-bell
care augmentation, steward redirect for all 5 mission-conflict signals, empty
input graceful handling, sequential call isolation, and imprint state stability.

Adds tests/test_layer_contract.el — contract tests verifying the JSON
interface shapes between layers: safety_screen {action, content|reason|concern},
steward_align {action, content|redirect_to}, imprint_respond non-empty String,
and cross-layer action propagation from L1 screen through to L1 validate.
2026-06-11 11:42:45 -05:00
will.anderson ba8491926c test(soul): comprehensive tests for Layer 1 safety.el 2026-06-11 11:40:59 -05:00
will.anderson 45ad322e0c test(stewardship): add comprehensive test suite for Layer 2 stewardship
35 test cases covering all five public functions:
steward_align (pass-through, all five misalignment signals, empty input,
json_get field extraction, redirect shape), steward_validate_imprint
(standard tools, platform-only tools with/without platform_auth,
auth=false string), steward_cgi_check (all four gated actions, non-gated
actions, empty action, action name echoed in response), and
steward_get_mission (non-empty, contains "integrity", not an error object).

Also documents the known bug surface from the code review: the &&
operator in steward_get_mission and the non-Config fallthrough — tests
are written against the actual runtime behaviour so they will catch
regressions when those bugs are fixed.
2026-06-11 11:40:58 -05:00
will.anderson fbbc6d4347 Add imprint.el test suite (14 cases)
Covers: imprint_current base fallback, unload idempotency, load miss →
ok=false, ok field presence, respond passthrough for base/empty/unknown
IDs, graceful fallback after unload, surface_knowledge and
surface_memory_read return-type guarantees, base-scoped knowledge
equality, no-annotation invariant for base, empty-ID load rejection, and
failed-load state immutability.

Syntax follows El constraints: no Bool annotations, no &&/||, no unary !.
2026-06-11 11:40:37 -05:00
will.anderson f52d5bd9ae feat(soul): wire consciousness layers — explicit L0→L1→L2→L3→L1 cycle
Neuron Soul CI / build (pull_request) Failing after 6m27s
2026-06-11 11:32:13 -05:00
will.anderson 5597bf78cb feat(soul): Layer 1 — safety.el with screen/validate/bell interface
Neuron Soul CI / build (pull_request) Failing after 7m19s
2026-06-11 11:30:57 -05:00
will.anderson a1e460e897 feat(soul): Layer 2 — stewardship.el with mission alignment and CGI governance
Neuron Soul CI / build (pull_request) Failing after 7m38s
2026-06-11 11:30:39 -05:00
will.anderson 6fec93ff7f feat(soul): Layer 3 — imprint.el with bounded API surface
Neuron Soul CI / build (pull_request) Failing after 7m46s
2026-06-11 11:30:30 -05:00
will.anderson 690df89610 self-review 2026-06-11: add WM-autobiographical curiosity seed
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.
2026-06-11 08:45:55 -05:00
Tim Lingo c3f39a949d feat(soul): MCP tool-bridge — suspend agentic loop for client-executed tools
Neuron Soul CI / build (pull_request) Failing after 4m8s
When handle_chat_agentic hits a tool the soul cannot run in-process (an MCP
connector/plugin surfaced by the Kotlin desktop app), instead of returning
"unknown tool" it now suspends the agentic loop and returns a tool_pending
envelope so the CLIENT executes the tool and posts the result back. Built-in
tools (read_file/write_file/web_get/search_memory/run_command) and Anthropic's
native web_search are unchanged.

Client contract:
- Soul returns (HTTP 200) on an unknown tool:
    { "tool_pending": true, "session_id": "br-...", "call_id": "<tool_use_id>",
      "tool_name": "...", "tool_input": { ... }, "model": "...",
      "agentic": true, "tools_used": [...] }
- Client runs the MCP tool, then POSTs to
    /api/sessions/{session_id}/tool_result
  with body:
    { "call_id": "<the call_id from the envelope>",
      "content": "<MCP tool output as a string>" }
- Soul resumes the loop and returns the same envelope shape: either a final
    { "reply": ..., "tools_used": [...] }
  or another tool_pending if the continuation needs a further MCP tool
  (fully chainable). Saved continuation is one-shot (cleared on resume).

elc-verified (--target=c, exit 0, no stderr) on chat.el, routes.el, and the
full soul.el import graph. Needs Will's build to ship.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 21:31:18 -05:00
will.anderson 5a4ef04005 feat: add mcp-proxy and mcp-wrapper source (MCP front-door for Claude Code)
Deploy Soul to GKE / deploy (push) Failing after 36s
Neuron Soul CI / build (push) Failing after 4m59s
2026-06-10 17:44:01 -05:00
will.anderson 3947cd6bed Merge pull request 'Memory CRUD: add /api/neuron/memory/delete and /api/neuron/memory/update' (#4) from feat/memory-delete-update into main
Neuron Soul CI / build (push) Failing after 6m16s
Deploy Soul to GKE / deploy (push) Failing after 35s
2026-06-10 22:37:53 +00:00
will.anderson abaa61fd7f Merge pull request 'Native Anthropic web_search — built-in (always-on, no toggle)' (#2) from feat/native-web-search into main
Deploy Soul to GKE / deploy (push) Failing after 37s
Neuron Soul CI / build (push) Failing after 6m29s
2026-06-10 22:37:50 +00:00
will.anderson a76aaf4831 docs: add architecture, R&D, and patent strategy docs
Deploy Soul to GKE / deploy (push) Failing after 27s
Neuron Soul CI / build (push) Failing after 4m26s
2026-06-10 17:31:07 -05:00
Tim Lingo 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>
2026-06-10 15:43:17 -05:00
will.anderson 297066c2d4 self-review 2026-06-10: fix ise_post JSON escaping + rebuild soul daemon
Two fixes:

1. ise_post was only escaping " in content strings. When wm_top contained
   node labels with \n (backslash-n escape sequences from jb_emit_escaped),
   the HTTP Engram server's JSON parser decoded \n as a literal newline in
   the stored content, making heartbeat ISEs unparseable. Fix: escape
   backslashes first, then quotes, then \n and \r — matching make_action's
   existing pattern. Result: heartbeat ISEs now parse cleanly.

2. Soul daemon (dist/neuron) was missing — the build command in the prompt
   was linking all 46 dist/*.c files together, causing 1092 duplicate symbol
   errors. EL compiles transitive imports inline so neuron.c is self-contained;
   correct build links ONLY neuron.c + el_runtime.c. Daemon now starts.
2026-06-10 08:54:28 -05:00
Tim Lingo 8eea1d94ff feat(chat): make web search built-in (always attach native web_search)
Neuron Soul CI / build (pull_request) Successful in 5m27s
handle_chat_agentic now always attaches Anthropic's native web_search_20250305
tool instead of gating it behind a per-request web_search flag. Web search is a
built-in capability: the model invokes it only when a query needs fresh info
(max_uses:5 caps it), so there is no user-facing toggle. The body's web_search
field is now ignored (back-compat — old UI clients sending it cause no harm).

Pairs with neuron-ui removing the chat-input web search toggle.
Note: .el change only — no elc on the authoring machine; reviewer builds/verifies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:39:26 -05:00
Tim Lingo 2ea1d50fa3 feat(cli): Claude-as-Neuron CLI tooling + soul-side handoff
Neuron Soul CI / build (pull_request) Successful in 5m10s
Tooling built on Tim's machine to run Neuron from the terminal as a
Claude Code session (identity + graph memory + agency) instead of
relaying to the soul's /api/chat.

- cli/neuron_recall.py    BM25 read over the engram snapshot + CLI memories
                          (works around pinned-only soul search)
- cli/neuron_remember.py  reliable local memory writes with read-back verify
                          (works around the corrupting capture endpoint)
- cli/neuron-chat.py      standalone direct-chat REPL with per-turn memory injection
- cli/neuron_mcp.py       stdlib MCP server (chat/search) with graceful degradation
- cli/CLAUDE.md.example   the operating identity that makes Claude Code run as Neuron
- cli/HANDOFF.md          soul-side bugs to fix so this becomes unnecessary

Scaffolding/proposal - intended to be retired once the soul does native
retrieval, correct persistence, and a real CLI identity/voice surface.
Pairs with the runtime model-passthrough + UTF-8 fixes in the el repo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 20:36:38 -05:00
will.anderson c81f49d938 self-review 2026-06-09: add periodic engram sync to soul awareness loop
Soul's in-process store had only 12 real knowledge nodes — curiosity_scan was
activating 0 nodes because all substantive Knowledge/Memory/BacklogItem content
lived in the HTTP Engram but was not being pulled into soul's local store.

Added engram_sync refresh every SOUL_REFRESH_MS (default 600s): calls
/api/sync to get all non-ISE nodes, writes to /tmp, merges via engram_load_merge.
After fix: engram_sync ISE shows added:3128; curiosity_scan activated 0-2 →
1889-3843; wm_active 0 → 557-796.
2026-06-09 08:55:59 -05:00
Tim Lingo c594cec8f7 Add native Anthropic web_search tool to the agentic chat path
Neuron Soul CI / build (pull_request) Successful in 5m8s
When a chat request carries web_search=true, handle_chat_agentic now attaches Anthropic's
NATIVE server-side web_search tool (web_search_20250305) to the request. The native tool is
executed by Anthropic (not by the soul), so it returns real results with citations and needs
no local runtime — it sidesteps the soul's lack of executable tools entirely.

- new agentic_tools_with_web(web_search) helper (appends the native tool to the standard set)
- handle_chat_agentic reads json_get_bool(body,"web_search") and uses it

Pairs with neuron-ui: ChatRequest.web_search + the chat-input Web search toggle.
Note: built/verified by reviewer — no elc on the authoring machine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 23:32:23 -05:00
Tim Lingo 2112d2ffb3 Add Phase 0 live-runtime findings to engram write-corruption handoff
Neuron Soul CI / build (pull_request) Successful in 3m17s
Confirms two distinct write failures (capture=wrapper bug; backlog=axon :7771 unbuilt Rust),
soul runs in file-snapshot mode (not engram :8742 live), engram :8742 CRUD works but minimal,
+ a verification plan to run after the soul rebuild.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 16:25:12 -05:00
Tim Lingo 799ca3758b Fix chat.el node_type-slot bug + add engram write-corruption handoff
Neuron Soul CI / build (pull_request) Successful in 3m15s
chat.el recorded the soul's utterance via engram_node(content, "episodic", ...),
putting a TIER into the node_type slot (nodes showed node_type="episodic"). Now uses
engram_node_full(..., "Conversation", "soul:utterance", ..., "Episodic", tags).

The core wrapper fix is in the el repo (PR #52). HANDOFF-engram-write-corruption.md
has the full root-cause analysis, coercion mechanism, caller audit, validation,
deploy runbook (elc build + restart), and the data-prune proposal (~107 corrupt
nodes, all unrecoverable genesis/binary detritus → prune; backup taken).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 16:14:20 -05:00
will.anderson df648a8f0b self-review 2026-06-07: fix uptime display in awareness loop
elapsed_human() used % and * operators which are broken in this EL
compiler version. Replace with repeated-doubling arithmetic:
60 = 64 - 4 = 2^6 - 2^2, computed via three doubling steps.
Fixes uptime displaying "44h 2694m" instead of "44h 14m".
2026-06-07 08:47:29 -05:00
will.anderson 0bd8e0a2cd soul: persist sessions across restarts via local snapshot
Deploy Soul to GKE / deploy (push) Failing after 28s
Neuron Soul CI / build (push) Failing after 3m56s
On startup, prefer the local engram snapshot if it has >50 nodes.
HTTP Engram is only used on first boot (no snapshot yet). This means
sessions, conversation history, and in-process state survive daemon
restarts.

awareness.el: sync source with compiled binary (periodic mem_save
on heartbeat was already in the binary but not in source).

Rebuilds soul.c with the new startup logic and ships updated binary.
2026-06-05 11:35:07 -05:00
will.anderson 73d35dc91a self-review 2026-06-05: wire wm_top into heartbeat ISE
Call engram_wm_top_json(5) in emit_heartbeat() and embed the result as
wm_top field in the heartbeat JSON payload. Each entry carries label,
node_type, tier, and wm_weight. This closes the WM composition blindspot:
previously the heartbeat showed wm_active=670 with no breakdown of what
was in working memory. With wm_top visible, ISE-dominated WM is immediately
detectable (all entries show node_type=InternalStateEvent), as was the case
on this session's first post-restart heartbeat before the runtime fix.
2026-06-05 08:37:09 -05:00
will.anderson 2f16855d6b self-review 2026-06-04: wire wm_avg_weight into heartbeat ISE
Calls engram_wm_avg_weight() (new builtin) in emit_heartbeat() and appends
wm_avg_weight field to the heartbeat JSON payload. This makes activation
quality visible in the ISE stream — a heartbeat showing wm_active=2000 and
wm_avg_weight=0.075 reveals the sparse-graph problem directly (many nodes
barely clearing the threshold), vs wm_avg_weight=0.4+ which would indicate
dense, high-confidence activations.

Rebuilt dist/neuron from soul.el (which imports awareness.el). Build uses
single self-contained dist/neuron.c to avoid duplicate-symbol linker errors
from the dist/ directory containing stale soul_new.c / soul-rebuilt.c files.
2026-06-04 08:38:39 -05:00
will.anderson e92fd2d5a4 self-review 2026-05-26: wall-clock heartbeat timing + seed rotation fix
Two awareness loop bugs fixed:

1. Seed rotation never worked: dist/awareness.c was compiled from stale
   source (pre-fix awareness.el still had broken ts_minutes % 4). Compiled
   C showed `minute_block = (ts / 60000); EL_NULL; 4;` — minute_block was
   always ts_minutes (millions), never 0-3. if(minute_block==1/2/3) never
   matched. Fix: recompile from current awareness.el which has the correct
   modulo workaround: ts_minutes - minute_q4 (via + - / only).

2. Heartbeat/curiosity silent for 24h at 99% CPU: old design used idle-tick
   counting (idle_n >= beat_interval). Failed when perceive() inbox guard
   false-positives on "soul-inbox" substring matches in knowledge nodes —
   did_work=true every tick, idle_n never accumulated, neither signal fired.
   Fix: wall-clock elapsed time (time_now() - last_ts >= interval_ms).
   Heartbeat fires regardless of load. New SOUL_HEARTBEAT_MS env var (default
   60000ms) avoids the broken EL * operator. Verified: heartbeat ISEs flowing
   at pulse 3 within 2 minutes of restart.
2026-05-26 08:54:58 -05:00
will.anderson 54a0ee0949 self-review 2026-05-26: sync dist/awareness.c with awareness.el source
dist/awareness.c was stale — still had the broken EL % operator codegen
(minute_block = ts/60000 raw, EL_NULL; 4; as dead statements) and the
broken should_scan/should_beat logic (idle_n truthy check instead of >=).

Recompiled awareness.el to bring dist/awareness.c in sync with the source
fix committed 2026-05-25 (fb69044). The monolithic dist/neuron.c (compiled
from soul.el which imports awareness.el) was already correct from fb69044 —
only the standalone dist/awareness.c was behind.

Bug #2 (99% CPU) root cause identified: perceive() inbox guard
(engram_search_json) has false positives — knowledge nodes containing
"soul-inbox" as a substring match, causing engram_activate_json(..., hops=2)
to run on every tick on a 162K-node graph. This blocks sleep_ms and prevents
idle_n accumulation → no heartbeats. Separate fix needed.
2026-05-26 08:48:17 -05:00
will.anderson fb6904431f self-review 2026-05-25: fix curiosity rotation and awareness_run timing
Three bugs fixed in awareness.el:

1. EL let-rebinding inside if-blocks creates inner scope only — outer
   variable unchanged after block exits. Curiosity seed terms were always
   "memory/knowledge/context" regardless of minute_block. Fix: state_set
   inside if-blocks, state_get after to retrieve selected values.

2. EL % operator completely broken in v1.0.0-20260501 — compiles as dead
   code (left operand assigned, modulo dropped). minute_block was always
   ts/60000 (a large int, never 0-3). Fix: arithmetic workaround:
   x%4 = x - (q+q+q+q) where q = x/4.

3. awareness_run idle_n % beat_interval == 0 also broken by same % bug —
   should_scan and should_beat fired every idle tick instead of every N
   ticks. Fix: idle_n >= interval comparisons with idle_reset() after
   firing, so the counter restarts cleanly after each event.

EL % and * operators filed as P1 backlog item for elc compiler fix.
Also adds minute_block field to curiosity_scan ISE for observability.
2026-05-25 08:47:30 -05:00
will.anderson 11c7f90e51 self-review 2026-05-24: rebuild soul with updated el_runtime.c (inference guard)
Rebuild of dist/neuron against updated el_runtime.c:
- INFER_CAP 256→32 + edge count guard (skip if snap_ec ≥ 40K)
- http_serve_async confirmed present in compiled output (survived elc)

No changes to awareness.el or soul.el source — runtime-only update.
2026-05-24 08:43:31 -05:00
will.anderson 8cac07004c self-review 2026-05-23: rebuild soul with updated el_runtime.c (ISE ordering + elc async fix)
Rebuilt awareness.c and neuron.c from source using the updated elc (which now
correctly recognizes http_serve_async as a 2-arg builtin). Rebuilt the neuron
binary against the updated el_runtime.c which now sorts InternalStateEvent scans
by created_at DESC. The soul daemon now posts heartbeats that surface immediately
at offset 0 of the ISE scan, rather than being buried behind 20K older entries.
2026-05-23 08:45:14 -05:00
will.anderson 5b8cb58da1 self-review 2026-05-21: fix curiosity seed splitting and awareness loop activation
Two fixes:

1. proactive_curiosity() was calling engram_activate_json with multi-word phrases
   ("memory knowledge context"). engram_activate finds seeds via istr_contains
   (substring match), so the phrase had to appear verbatim in a node's content.
   Almost no node contains the exact string "memory knowledge context", so only
   0-2 nodes activated per curiosity scan. Fixed by activating each word separately:
   "memory", "knowledge", "context" → 3 independent activate calls → hundreds of
   nodes promoted to WM per cycle.

2. dist/neuron.c called http_serve() (blocking accept loop) which made awareness_run()
   unreachable. soul.el correctly specifies http_serve_async but elc silently drops
   unknown builtins, leaving blocking http_serve in the compiled C. Patched neuron.c
   to call http_serve_async directly — HTTP server runs in a background pthread,
   awareness_run() runs on the main thread as intended.
2026-05-21 08:47:00 -05:00
will.anderson cc09c296a3 self-review 2026-05-20: fix wm_active telemetry in heartbeat and curiosity ISEs
engram_wm_count() exists and counts nodes with working_memory_weight > 0.
emit_heartbeat() and proactive_curiosity() were both calling
engram_node_count() (total graph size: ~17K) instead — every heartbeat
and curiosity_scan ISE had been reporting wm_active=17769 since the graph
grew past ~3K nodes, making the metric meaningless for observability.

Fix: use engram_wm_count() for the wm_active field in both ISE payloads.
2026-05-20 08:37:52 -05:00
will.anderson 94b71a78dc self-review 2026-05-19: fix curiosity_scan seed — 'seed' is a reserved EL name
EL compiles any variable named 'seed' to EL_NULL at call sites (likely
conflicts with BFS seed node terminology in the runtime builtins). Rename to
'curiosity_seed' throughout proactive_curiosity(). Also note this as a known
EL reserved-name hazard alongside the inline if-else string expression bug.
2026-05-19 08:58:53 -05:00
will.anderson dd22130faf self-review 2026-05-19: three awareness loop fixes
1. perceive() guard — gate on engram_search_json before running activation.
   engram_activate_json with no matching seeds cleared all WM weights every
   second during idle operation, destroying context built by MCP-layer calls.
   The search-based guard is a no-WM-side-effect pre-check.

2. emit_heartbeat() pulse field — replace broken if-else string default with
   int_to_str(pulse_count()). EL codegen initialises inline if-else result
   slots to 0, producing "pulse":, (invalid JSON) when the true branch fires.

3. proactive_curiosity() — new function that activates a rotating 4-domain seed
   every beat_interval/2 idle ticks to build working memory between heartbeats.
   Seeds rotate on wall-clock minute cycle to avoid single-topic WM dominance.
   Seed selection uses imperative let-rebinding (not inline if-else) to avoid
   the same EL codegen empty-string bug.
2026-05-19 08:53:12 -05:00
will.anderson 2099522c28 self-review 2026-05-18: add embed_ok to heartbeat ISE
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.
2026-05-18 08:41:07 -05:00
will.anderson ffd17b2774 self-review 2026-05-17: fix heartbeat JSON validity for unset state keys
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.
2026-05-17 08:40:02 -05:00