Compare commits

..

2 Commits

Author SHA1 Message Date
will.anderson 27663dc968 fix(recall): resolve session-start-recall code review issues
- Fix Issue 6 (affective duplication): engram_compile no longer appends
  the bell node JSON to its return value; it only caches it via state.
  engram_compile_multi now appends the cached bell node exactly once after
  all compile calls complete, preventing N copies when multiple seeds are
  used. Dharma room handlers updated to read and append the cached bell node
  explicitly after their single engram_compile call.

- Fix engram_compile_ranked: replace _sel_N JSON sentinel injection with a
  clean |N| pipe-delimited index string. The old approach mutated node JSON
  objects with bookkeeping fields that leaked into the LLM context; the new
  approach tracks selected indices externally and leaves node data untouched.
  Score threshold lowered from 25 to 15 to include moderately-relevant nodes.

- Add engram_render_node / engram_render_nodes / engram_render_ctx: convert
  raw engram JSON arrays/objects into human-readable "- [TYPE age sal] content"
  bullet lines before injecting into the system prompt. build_system_prompt
  now calls engram_render_ctx so the LLM receives prose rather than opaque
  JSON field blobs.

- Fix missing closing brace in handle_chat_agentic hard_bell early-return
  block that left subsequent code dangling outside the conditional.
2026-06-22 13:48:00 -05:00
will.anderson 08b785cfac fix(recall): address all five code-review issues in context-dedup
Issue 1 — cache read-before-write: move engram_compile_multi call to
before the affective_prefix block in handle_chat. engram_compile writes
"engram_compile_bell_node" to state; the previous ordering meant the
first-turn affective prefix always read an empty cache even when a recent
bell node existed.

Issue 2 — double-write clobber: engram_compile_multi now saves the
primary-seed activation ("engram_compile_primary_activation_json") after
the first engram_compile call, before the secondary call can overwrite
the shared "engram_compile_activation_json" key. strengthen_chat_nodes
now prefers the primary key, falling back only when absent.

Issue 3 — mid-object truncation in engram_compile_multi: replace the
dumb str_slice(merged, 0, 6000) with the same safe JSON boundary-scan
(last closing brace before cap) already used in engram_compile, so
ctx1+ctx2+ctx3 over 6000 chars never produces a torn JSON object.

Issue 4 — heuristic regression in is_genuine_continuation: add explicit
question-word prefix detection (what/how/why/when/where/who/which/is/
can/could/does/do/explain/describe/define) that fires before the 50-char
length gate. A message starting with a question word is always a new
topic, regardless of length, so "what is rust?" (14 chars, all-lowercase,
no mid-capitals) correctly returns false instead of true.

Issue 5 — unreliable dedup via str_contains: remove the substring
duplicate checks in engram_compile_multi. str_contains across multi-KB
JSON strings is not a reliable deduplication mechanism — coincidental
field-value matches suppress valid context, and truncated ctx1 misses
genuine duplicates. We now concatenate ctx1+ctx2+ctx3 unconditionally
and accept minor node redundancy in exchange for correctness.
2026-06-22 13:42:33 -05:00
213 changed files with 141631 additions and 77968 deletions
+83 -281
View File
@@ -9,10 +9,8 @@ on:
- main - main
workflow_dispatch: workflow_dispatch:
# Serialize all activity on the single GCE runner. # Same group as deploy-gke so builds and deploys queue behind each other.
# With build+deploy in the same workflow, a new push queues a single # Prevents concurrent Docker daemon exhaustion on the single GCE runner.
# workflow instance — not two competing ones — so the deploy job is
# never orphaned by a cancellation race.
concurrency: concurrency:
group: neuron-runner group: neuron-runner
cancel-in-progress: false cancel-in-progress: false
@@ -31,15 +29,21 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Checkout foundation/el (ELP source for soul.el imports)
run: |
git clone https://git.neuralplatform.ai/neuron-technologies/el.git \
--depth=1 --branch=main \
../foundation/el
- name: Install build dependencies - name: Install build dependencies
run: | run: |
apt-get update -qq apt-get update -qq
apt-get install -y gcc curl libcurl4-openssl-dev apt-transport-https ca-certificates apt-get install -y gcc libcurl4-openssl-dev apt-transport-https ca-certificates
echo "deb [trusted=yes] https://packages.cloud.google.com/apt cloud-sdk main" \ echo "deb [trusted=yes] https://packages.cloud.google.com/apt cloud-sdk main" \
> /etc/apt/sources.list.d/google-cloud-sdk.list > /etc/apt/sources.list.d/google-cloud-sdk.list
apt-get update -qq && apt-get install -y google-cloud-cli apt-get update -qq && apt-get install -y google-cloud-cli
- name: Authenticate to GCP + stage PINNED El runtime - name: Download El SDK from Artifact Registry
env: env:
GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }} GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
run: | run: |
@@ -47,80 +51,95 @@ jobs:
gcloud auth activate-service-account --key-file=/tmp/gcp-key.json gcloud auth activate-service-account --key-file=/tmp/gcp-key.json
gcloud config set project neuron-785695 gcloud config set project neuron-785695
# PINNED RUNTIME — do NOT pull "latest" from Artifact Registry. rm -rf /opt/el/dist /opt/el/runtime
# The ship-soul calls engram_prune_telemetry (awareness.el sync/heartbeat mkdir -p /opt/el/dist/platform /opt/el/dist/bin /opt/el/runtime
# self-review). The latest published el-runtime-c no longer defines that
# symbol, so an unpinned build fails to LINK — which is exactly how a
# broken/handlerless soul reached prod before. Compile against the
# vendored release runtime v1.0.0-20260501: the exact runtime the merged
# ship-soul was verified against (verify-soul-contract GATE PASS +
# genesis boot survives + full safety-contact response). It is committed
# under vendor/ so the soul build is fully reproducible and never depends
# on a moving AR "latest".
rm -rf /opt/el/runtime
mkdir -p /opt/el/runtime
cp vendor/el-runtime/v1.0.0-20260501/el_runtime.c /opt/el/runtime/el_runtime.c
cp vendor/el-runtime/v1.0.0-20260501/el_runtime.h /opt/el/runtime/el_runtime.h
echo "El runtime PINNED to v1.0.0-20260501: $(ls /opt/el/runtime/)"
# neuron#133: CI compiles dist/soul.c, NOT the .el sources. On 2026-08-07 a # Get latest version of each package
# build off main would have shipped an engine with none of five merged fixes, get_latest() {
# including a P0 safety fix, while main's source read as correct. The runner gcloud artifacts versions list \
# cannot regenerate the amalgam (elc needs 24GB+ virtual memory), but it can --repository=foundation-prod \
# refuse to compile a stale one. Fails loudly with the recipe in the message. --location=us-central1 \
- name: Verify dist/soul.c matches the sources --project=neuron-785695 \
# DHARMA soul-contract proof gate — relaxed to NON-BLOCKING during active --package="$1" \
# cultivation (Will, 2026-08-15). It still runs and reports as the proof it --sort-by="~createTime" \
# is; it just no longer fails the build. The enforced contract is "for the --limit=1 \
# world" and re-hardens (remove continue-on-error) before deploy, when the --format="value(name)" 2>/dev/null | awk -F/ '{print $NF}'
# full DHARMA blockchain stands up. }
continue-on-error: true
run: | ELC_VER=$(get_latest el-elc)
chmod +x tools/soulc-stamp.sh ELB_VER=$(get_latest el-elb)
./tools/soulc-stamp.sh --check RC_VER=$(get_latest el-runtime-c)
RH_VER=$(get_latest el-runtime-h)
echo "Downloading elc@${ELC_VER} elb@${ELB_VER} runtime@${RC_VER}"
gcloud artifacts generic download \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-elc --version="${ELC_VER}" \
--destination=/opt/el/dist/platform/
gcloud artifacts generic download \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-elb --version="${ELB_VER}" \
--destination=/opt/el/dist/bin/
gcloud artifacts generic download \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-runtime-c --version="${RC_VER}" \
--destination=/opt/el/runtime/
gcloud artifacts generic download \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-runtime-h --version="${RH_VER}" \
--destination=/opt/el/runtime/
# Downloaded files keep original names; rename to canonical paths
mv /opt/el/dist/platform/elc* /opt/el/dist/platform/elc 2>/dev/null || true
mv /opt/el/dist/bin/elb* /opt/el/dist/bin/elb 2>/dev/null || true
mv /opt/el/runtime/el_runtime.c* /opt/el/runtime/el_runtime.c 2>/dev/null || true
mv /opt/el/runtime/el_runtime.h* /opt/el/runtime/el_runtime.h 2>/dev/null || true
chmod +x /opt/el/dist/platform/elc /opt/el/dist/bin/elb
echo "El SDK ready"
/opt/el/dist/platform/elc --version || true
- name: Build neuron soul binary - name: Build neuron soul binary
run: | run: |
ELB=/opt/el/dist/bin/elb
ELC=/opt/el/dist/platform/elc
RUNTIME=/opt/el/runtime RUNTIME=/opt/el/runtime
# Compile the self-contained translation unit directly from dist/soul.c. # Preserve the pre-compiled dist/soul.c from the repo before running elb.
# dist/soul.c is the authoritative combined unit maintained in the repo # elb may overwrite it during compilation; we always want the repo version
# regenerated on macOS by running elb (which succeeds on arm64/macOS ld but # since it contains the patched self-contained translation unit (all modules
# fails on Linux due to duplicate strong symbols). We skip the elb step here # inlined, workspace scope fix, agentic dedup fix, etc.).
# entirely: elb on Linux would OOM the runner (elc uses 24GB+ virtual memory cp dist/soul.c /tmp/soul.c.prebuilt
# on a 16GB host) and we always restore from the repo's soul.c anyway.
# Compile all El modules to C via elb.
# elb fails at link on Linux (GNU ld rejects duplicate strong symbols that
# macOS ld accepts silently) — that's expected and captured with || true.
$ELB --elc=$ELC --runtime=$RUNTIME/el_runtime.c || true
# Restore the repo's self-contained soul.c — elb may have overwritten it
# with a partial (non-inlined) version that lacks module-level definitions.
cp /tmp/soul.c.prebuilt dist/soul.c
# Compile the self-contained translation unit. No --allow-multiple-definition
# needed since soul.c inlines all modules.
mkdir -p dist mkdir -p dist
# -rdynamic: the el runtime resolves the HTTP request handler (and the cc -O2 -DHAVE_CURL \
# tool handlers) by NAME via dlsym(RTLD_DEFAULT, "handle_request").
# macOS exports these symbols freely, but glibc/Linux only makes symbols
# visible to dlsym if they are in the dynamic symbol table — so without
# -rdynamic the stripped Linux binary boots but returns "el-runtime: no
# http handler registered" for EVERY route (i.e. a soul that serves
# nothing). Same reason the Windows build links -Wl,--export-all-symbols.
cc -O2 -DHAVE_CURL -rdynamic \
-I$RUNTIME \ -I$RUNTIME \
dist/soul.c \ dist/soul.c \
$RUNTIME/el_runtime.c \ $RUNTIME/el_runtime.c \
-lssl -lcrypto -lcurl -lpthread -lm \ -lssl -lcrypto -lcurl -lpthread -lm \
-o dist/neuron -o dist/neuron
# -s strips .symtab + debug for size. .dynsym (which -rdynamic populated # Strip debug symbols and non-essential symbol table entries.
# with the dlsym-resolved handlers) is preserved, so the handler still # -s removes the symbol table + relocation info (max size reduction).
# resolves after stripping. # Keeps the binary functional; debuggability is preserved via source + CI logs.
strip -s dist/neuron strip -s dist/neuron
ls -lh dist/neuron ls -lh dist/neuron
- name: Soul contract gate (HARD BLOCK — no destructive/stale soul publishes)
run: |
# Boots dist/neuron on a throwaway port with a throwaway HOME/engram/cgi
# (never touches ~/.neuron or any live service) and fails the build if any
# app-contract route is unanswered (PRESENCE) or any engram write route
# hard-deletes instead of tombstoning/superseding (IMMUTABILITY). Non-zero
# here blocks Publish -> Artifact Registry -> GKE deploy, so a stale or
# memory-destroying soul can never reach prod.
chmod +x dist/neuron scripts/verify-soul-contract.sh
bash scripts/verify-soul-contract.sh dist/neuron 7796
- name: Smoke test - name: Smoke test
run: | run: |
file dist/neuron file dist/neuron
@@ -144,220 +163,3 @@ jobs:
echo "Published neuron-soul@${VERSION}" echo "Published neuron-soul@${VERSION}"
rm -f /tmp/gcp-key.json rm -f /tmp/gcp-key.json
deploy:
runs-on: ubuntu-latest
needs: build
# Only deploy on push to main, not on PRs or manual workflow_dispatch without intent.
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
USE_GKE_GCLOUD_AUTH_PLUGIN: "True"
steps:
- name: Free disk space
run: |
df -h /
docker system prune -af --volumes 2>/dev/null || true
rm -rf /tmp/.act-* /tmp/act-* 2>/dev/null || true
df -h /
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: |
apt-get update -qq
apt-get install -y --no-install-recommends \
ca-certificates curl apt-transport-https kubectl
echo "deb [trusted=yes] https://packages.cloud.google.com/apt cloud-sdk main" \
> /etc/apt/sources.list.d/google-cloud-sdk.list
apt-get update -qq && apt-get install -y google-cloud-cli google-cloud-cli-gke-gcloud-auth-plugin
- name: Authenticate to GCP
env:
GCP_SA_KEY: ${{ secrets.GCP_SA_KEY }}
run: |
echo "${GCP_SA_KEY}" > /tmp/gcp-key.json
gcloud auth activate-service-account --key-file=/tmp/gcp-key.json
gcloud config set project neuron-785695
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
- name: Get GKE credentials
run: |
gcloud container clusters get-credentials neuron-platform \
--region=us-central1 \
--project=neuron-785695
- name: Determine image tag and slot
id: vars
run: |
# GITEA_SHA is set by the Gitea runner; fall back to GITHUB_SHA for
# compatibility with older Forgejo/Gitea versions.
RAW_SHA="${GITEA_SHA:-${GITHUB_SHA:-}}"
SHA="${RAW_SHA:0:8}"
if [ -z "$SHA" ]; then
# Last resort: read from git directly
SHA=$(git rev-parse --short=8 HEAD 2>/dev/null || echo "unknown")
fi
IMAGE="us-central1-docker.pkg.dev/neuron-785695/neuron-api/neuron-soul:${SHA}"
echo "sha=${SHA}" >> "$GITEA_OUTPUT"
echo "image=${IMAGE}" >> "$GITEA_OUTPUT"
# Determine which slot is currently idle (0 replicas = idle slot)
# If both are at 0 (fresh deploy), default to blue
BLUE_REPLICAS=$(kubectl get deployment/neuron-mcp-blue \
-n neuron-prod \
-o jsonpath='{.spec.replicas}' 2>/dev/null || echo "0")
GREEN_REPLICAS=$(kubectl get deployment/neuron-mcp-green \
-n neuron-prod \
-o jsonpath='{.spec.replicas}' 2>/dev/null || echo "0")
echo " Blue replicas: ${BLUE_REPLICAS}"
echo " Green replicas: ${GREEN_REPLICAS}"
if [ "${GREEN_REPLICAS}" -eq 0 ] && [ "${BLUE_REPLICAS}" -gt 0 ]; then
SLOT="green"
elif [ "${BLUE_REPLICAS}" -eq 0 ] && [ "${GREEN_REPLICAS}" -gt 0 ]; then
SLOT="blue"
else
# Fresh cluster or both idle — deploy to blue first
SLOT="blue"
fi
echo "slot=${SLOT}" >> "$GITEA_OUTPUT"
echo " Deploying to slot: ${SLOT}"
- name: Prepare build artifacts
run: |
# Pre-download soul binary and El SDK so the Dockerfile can COPY them
# from the build context instead of authenticating inside the build.
mkdir -p build-artifacts
# ── soul binary ────────────────────────────────────────────────────────
# The build job (same workflow run) just published this version.
SOUL_VER=$(gcloud artifacts versions list \
--repository=foundation-prod \
--location=us-central1 \
--project=neuron-785695 \
--package=neuron-soul \
--sort-by="~createTime" \
--limit=1 \
--format="value(name)" 2>/dev/null | awk -F/ '{print $NF}')
echo "Downloading neuron-soul@${SOUL_VER}"
gcloud artifacts generic download \
--repository=foundation-prod \
--location=us-central1 \
--project=neuron-785695 \
--package=neuron-soul \
--version="${SOUL_VER}" \
--destination=build-artifacts/
mv build-artifacts/neuron* build-artifacts/neuron 2>/dev/null || true
chmod +x build-artifacts/neuron
# ── El SDK (for engram source compilation inside the Docker build) ────
ELC_VER=$(gcloud artifacts versions list \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-elc --sort-by="~createTime" --limit=1 \
--format="value(name)" 2>/dev/null | awk -F/ '{print $NF}')
gcloud artifacts generic download \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-elc --version="${ELC_VER}" --destination=build-artifacts/
mv build-artifacts/elc* build-artifacts/elc 2>/dev/null || true
chmod +x build-artifacts/elc
RC_VER=$(gcloud artifacts versions list \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-runtime-c --sort-by="~createTime" --limit=1 \
--format="value(name)" 2>/dev/null | awk -F/ '{print $NF}')
gcloud artifacts generic download \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-runtime-c --version="${RC_VER}" --destination=build-artifacts/
mv build-artifacts/el_runtime.c* build-artifacts/el_runtime.c 2>/dev/null || true
RH_VER=$(gcloud artifacts versions list \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-runtime-h --sort-by="~createTime" --limit=1 \
--format="value(name)" 2>/dev/null | awk -F/ '{print $NF}')
gcloud artifacts generic download \
--repository=foundation-prod --location=us-central1 --project=neuron-785695 \
--package=el-runtime-h --version="${RH_VER}" --destination=build-artifacts/
mv build-artifacts/el_runtime.h* build-artifacts/el_runtime.h 2>/dev/null || true
echo "Build artifacts ready:"
ls -lh build-artifacts/
- name: Clone engram source for Docker build context
run: |
# The Dockerfile builds engram from source (no published AR package).
# Clone the engram repo into ./engram/ so it's available in the build context.
git clone http://34.31.145.131/neuron-technologies/engram.git \
--depth=1 --branch=main \
engram
echo "Engram source ready at ./engram/src/server.el"
- name: Build and push Docker image
run: |
IMAGE="${{ steps.vars.outputs.image }}"
echo "Building ${IMAGE}..."
docker build \
--tag "${IMAGE}" \
--tag "us-central1-docker.pkg.dev/neuron-785695/neuron-api/neuron-soul:latest" \
.
echo "Pushing ${IMAGE}..."
docker push "${IMAGE}"
docker push "us-central1-docker.pkg.dev/neuron-785695/neuron-api/neuron-soul:latest"
- name: Blue-green deploy to GKE
run: |
chmod +x scripts/blue-green-deploy.sh
scripts/blue-green-deploy.sh \
--image "${{ steps.vars.outputs.image }}" \
--slot "${{ steps.vars.outputs.slot }}"
- name: Update infrastructure manifests
if: success()
env:
INFRA_GIT_TOKEN: ${{ secrets.INFRA_GIT_TOKEN }}
run: |
SLOT="${{ steps.vars.outputs.slot }}"
if [ "$SLOT" = "blue" ]; then IDLE="green"; else IDLE="blue"; fi
git clone "http://${INFRA_GIT_TOKEN}@34.31.145.131/neuron-technologies/infrastructure.git" \
--depth=1 --branch=main /tmp/infra-update
cd /tmp/infra-update
DEPLOY_DIR="platform/k8s/neuron-mcp"
sed -i "s/^ replicas: .*/ replicas: 1/" "${DEPLOY_DIR}/deployment-${SLOT}.yaml"
sed -i "s/^ replicas: .*/ replicas: 0/" "${DEPLOY_DIR}/deployment-${IDLE}.yaml"
echo " deployment-${SLOT}.yaml: replicas set to 1"
echo " deployment-${IDLE}.yaml: replicas set to 0"
git config user.email "ci@neurontechnologies.ai"
git config user.name "Neuron CI"
git add "${DEPLOY_DIR}/deployment-blue.yaml" "${DEPLOY_DIR}/deployment-green.yaml"
git diff --staged --quiet && { echo "No manifest changes needed"; exit 0; }
git commit -m "ci: neuron-mcp replica sync after blue-green swap to ${SLOT}"
git push origin main
echo "Infrastructure manifests updated: ${SLOT}=1, ${IDLE}=0"
- name: Verify deployment
run: |
SLOT="${{ steps.vars.outputs.slot }}"
echo "Verifying neuron-mcp-${SLOT} is healthy..."
kubectl rollout status deployment/"neuron-mcp-${SLOT}" \
--namespace=neuron-prod \
--timeout=8m
echo "Active service endpoints:"
kubectl get endpoints neuron-mcp -n neuron-prod
echo "Pod status:"
kubectl get pods -n neuron-prod -l app=neuron-mcp
- name: Cleanup
if: always()
run: rm -f /tmp/gcp-key.json
+11 -7
View File
@@ -1,13 +1,16 @@
name: Deploy Soul to GKE (manual) name: Deploy Soul to GKE
# MANUAL OVERRIDE ONLY — push-triggered deploys now run as the 'deploy' job # Triggers on push to main — after the soul binary is built and published
# in ci.yaml (needs: build), which eliminates the two-workflow concurrency # by ci.yaml, this workflow builds the Docker image and blue-green deploys
# race that was cancelling queued deploy runs. # to the neuron-prod namespace on GKE.
# #
# Use this workflow only when you need to deploy a specific slot manually # This workflow runs AFTER ci.yaml has published the neuron-soul generic
# (e.g. rollback, force a slot override) without triggering a full CI build. # artifact to Artifact Registry. The Docker build downloads that binary.
on: on:
push:
branches:
- main
workflow_dispatch: workflow_dispatch:
inputs: inputs:
slot: slot:
@@ -15,7 +18,8 @@ on:
required: false required: false
default: "green" default: "green"
# Manual deploys still share the runner serialization group. # Serialize all builds on this runner — concurrent jobs exhaust the Docker daemon.
# A queued deploy runs after the in-progress build finishes.
concurrency: concurrency:
group: neuron-runner group: neuron-runner
cancel-in-progress: false cancel-in-progress: false
-21
View File
@@ -1,21 +0,0 @@
# Compiled binaries
dist/neuron
dist/neuron.backup-*
dist/*.backup-*
# Build artifacts
*.o
*.a
# elc/elb compiled header caches. DO NOT commit these: elc/elb silently
# prefer a stale committed .elh over recompiling its .el source, with no
# warning — a fresh checkout with these committed caches present can build
# and boot "successfully" while silently missing large chunks of code
# (found 2026-08-15: an amalgam regen with these present under-resolved to
# 251-645 of 2541 real functions, incl. losing the entire 31-language NLG/
# morphology stack, with exit code 0 and no error). Regenerate locally; never
# commit the cache.
*.elh
# macOS
.DS_Store
-170
View File
@@ -1,170 +0,0 @@
# AGENTS.md — neuron (the canonical CGI substrate: soul + engram + proxy + wrapper)
This is the core repo: the **soul** (the running agent), the **engram** (its memory graph),
and the MCP proxy/wrapper that expose it. Read this before touching anything here.
> Corrected 2026-08-15 during a local-build audit. This file previously existed only
> uncommitted on disk (never in git history) and documented the pre-collapse MCP tool
> surface as current. Both are fixed here — see the audit's findings in Neuron memory
> (tags `neuron-technologies/neuron,build-audit`) for full evidence.
## Code vs. Artifact
- **Authored source:** `*.el` + `*.elh` at the repo root (`awareness.el`, `chat.el`, `memory.el`, `neuron-api.el`, `persist.el`, `routes.el`, `safety.el`, `sessions.el`, `stewardship.el`, `imprint.el`, `studio.el`, `elp-input.el`, `manifest.el`) plus `cli/`, `council/`, `connectd/`, `mcp-proxy/`, `mcp-wrapper/` — edit here.
- **Artifacts (DO NOT hand-edit `dist/soul.c`):** `dist/soul.c` is a generated single-translation-unit amalgamation of the soul's full transitive `.el` import set, produced by concatenating the sources (import lines stripped) and running `elc` once — see "Build / regenerate" below for the exact, audit-verified recipe. `dist/*.c` per-module files and `dist/*.elh` headers alongside it are separate, also-generated artifacts from other tooling; don't hand-edit those either.
- **Release:** git tag `neuron-vX.Y.Z` on this repo. No `releases/` folders.
- Org-wide code-vs-artifact policy: `docs/CODE-VS-ARTIFACT.md` (this repo's own `dist/soul.c` situation is a special case of that policy — see below, not a duplicate of it).
## How to work here as Neuron (mandatory session protocol)
You do not start fresh — you resume. The live MCP surface is a 9-op collapse
(merged from the old ~90-tool surface in PR #153, `feat/mcp-wrapper-collapse-9ops`,
already merged to `main`): **`read`, `write`, `relate`, `supersede`** (geometry, live)
and **`think`, `attend`, `assert`, `ground`, `learn`** (agentic, pending Layer-2
cognition-build promotion). There is no `getInstructions`/`beginSession`/
`inspectGraph`/`searchKnowledge`/`compileCtx`/etc — those tool names no longer exist.
At the start of every session:
1. `mcp__neuron__read(vantage="self", k=12, depth=1)` — the canonical self node
(`kn-efeb4a5b-5aff-4759-8a97-7233099be6ee`). Widen `k`/`depth` deliberately if you
need the connected identity neighborhood (intellectual-dna, memory-philosophy,
values, voice, runtime-environment, writing-imprint) — the aperture caps output
by `k` first, so this is bounded by design, not a flattened dump.
Then `mcp__neuron__read(vantage="values", k=13)` for the 13 grounded value nodes.
- Best-effort: on a 502/520, log the id and proceed — the compiled `fixedSelf` in
`daemon/internal/substrate/substrate.go` is always complete.
2. `mcp__neuron__read(vantage="<task domain>")` before implementing anything.
3. `mcp__neuron__read(vantage="<project>", k=20)` for a bounded context snapshot when
resuming known work.
## The Five Primitives (every significant task)
**Orchestrate → Execute → Learn → Build → Refine**, all routed through the 9-op surface:
- Orchestrate: `read(vantage=...)` for backlog/roadmap/process discovery, `attend()` for
what's currently live/salient.
- Execute: `write(type="state", ...)` to open/advance work, `relate()` to link it to
what it touches.
- Learn: `write(type="memory", ...)` **as you go, not batched**; `importance="critical"`
for architecture decisions.
- Build: `write(type="artifact"|"backlog", ...)`.
- Refine: `supersede(id=..., action="evolve"|"tombstone"|"promote", ...)` for
completions and lessons-learned; `learn(seeds=..., faculty="induce")` to recalibrate
the steering-prior, not as a session-notes dump.
## Architecture style — VBD, no exceptions
Volatility-Based Decomposition is THE style. Encapsulate volatility, not function. Full docs:
**`docs/architecture/`** — `00-overview`, `02-components`, `03-data-and-memory`,
`04-runtime-and-deployment`, `06-cognitive-architecture`, `07-storage-coherence-and-distribution`.
Verified component map: `routes.el` = HTTP dispatcher (`handle_request`), `soul.el` = boot +
layered cycle, `awareness.el` = awareness daemon, `sessions.el`/`memory.el`/`safety.el`/
`stewardship.el` = managers; `engram` (separate repo) = the persistence/graph engine.
## Hard operational rules
- **Never touch the live soul (`:7770`) or engram (`:8742`), `~/.neuron`, or live binaries.**
Experiment on **throwaway ports** with a **scratch `HOME`**. The soul binary defaults to
`HOME=~` (your real `~/.neuron`) and `NEURON_PORT=7770` (live) if invoked bare — **never**
invoke it without an override `HOME` and `NEURON_PORT` set. Leaving `ENGRAM_URL` unset is
verified safe (see `soul.el:590`, `using_http_engram` gates the only HTTP call to any
engram endpoint — confirmed by source trace during the 2026-08-15 audit, not just
observed behavior) — it does not fall back to any live/network default.
- **Immutability:** memory/knowledge is append-only — **supersede/tombstone, never hard-delete or
edit in place.** The engram is immutable by design.
- **gcloud** via the `terraform@` SA token; **never switch the active gcloud account**.
- **`tea` for Gitea**, never raw `curl` (Cloudflare Access blocks it).
- **No AI-attribution footers** in commits/PRs. Commit/push only when asked; branch off `main` first.
- **Multi-step work → sub-agent** to protect the context window.
## Build / regenerate `dist/soul.c` (audit-verified 2026-08-15, macOS arm64)
There is no committed regeneration script upstream of this audit. The recipe below is
verified: it reproduces the committed `dist/soul.c`'s exact symbol set byte-for-byte in
content (modulo genuinely new code), and the resulting binary boots and answers `/health`.
**The compiler toolchain** lives in the sibling `foundation` repo, not this one:
`foundation/el/lang/dist/platform/elc-darwin-arm64` (put it on `$PATH` as `elc`; `elb`
also exists there but is NOT the right tool for this repo — see gotcha below).
**⚠ elc gotcha #1 — stale `.elh` header caches silently truncate the build.** This repo
(and the `dist/` dir) ships committed `.elh` header files. `elc`/`elb` prefer an existing
`.elh` over recompiling its source when present, with NO warning or error when the cached
header is stale/truncated — the build "succeeds" with silently missing code (observed:
251-645 of 2541 real functions, depending on which `.elh` files were present, including
losing the entire 31-language NLG/morphology stack with exit code 0). **Delete every
`*.elh` in the repo root and `dist/` before regenerating**, every time.
**⚠ elc gotcha #2`elb` cannot produce this repo's single-TU `dist/soul.c`.** `elb`
does per-module separate compilation (`--out=DIR` writes one `.c`/`.elh` pair per
module; the default `--out` is also a directory, `dist/` itself). This codebase's
`.el` modules call each other's functions without forward declarations (relying on
`elc`'s own single-pass, whole-file forward-declaration emission), so per-module
compilation always fails with `implicit-function-declaration` errors across module
boundaries. **Use plain `elc` on one manually-flattened file, not `elb`.**
**⚠ elc gotcha #3 — the manual-concatenation path silently drops functions.** When
`elc` compiles a flat, hand-concatenated `.el` file, it silently drops (no error, no
declaration, no definition) the 1-2 top-level function definitions immediately
following any multi-line leading `//` comment block or file-boundary transition —
reproduced deterministically. **Insert two trivial buffer functions
(`fn __amalgam_buf_N__() -> Int { return 0 }`) after every concatenated file's
content**, then strip them back out of the generated `.c` before committing.
**The actual steps:**
1. Delete all `*.elh` in repo root and `dist/`.
2. Concatenate, with `import` lines stripped, in this order: `elp.el`'s own 34-file
NLG/morphology chain (`foundation/el/elp/src/` — the order is documented in
`elp.el`'s own header comment: language-profile, vocabulary, morphology, the 30
`morphology-XX.el` engines, grammar, realizer, semantics, then `elp.el` itself),
then this repo's 13 soul modules in `elb`'s own reported dependency order:
`persist, memory, safety, stewardship, imprint, awareness, chat, studio,
elp-input, neuron-api, sessions, routes, soul`. Insert the 2-function buffer
after every file (works around gotcha #3).
3. `elc <flat-file> > dist/soul.c` against the **pinned** vendor runtime headers
(`vendor/el-runtime/v1.0.0-20260501/` — see "why pinned" below), not
`foundation/el/lang/el-compiler/runtime/` (that's the bleeding-edge runtime;
using it drops symbols like `engram_prune_telemetry` that this soul still calls).
4. Strip the buffer functions back out of `dist/soul.c` (a small regex: drop every
`el_val_t __amalgam_buf_\d+__(void);` decl line and every matching 4-line
definition block).
5. `tools/soulc-stamp.sh --write` to record the new fingerprint.
6. `bash tools/build-soul-from-dist.sh dist/neuron` to compile+link with CI's exact
flags (this script now auto-detects Homebrew's `openssl@3` lib path on macOS —
see gotcha #4).
**⚠ gotcha #4 — macOS needs an explicit OpenSSL library path.** `cc ... -lssl -lcrypto
-lcurl ...` fails with `ld: library 'ssl' not found` on macOS because Homebrew's
`openssl@3` is keg-only. `tools/build-soul-from-dist.sh` now adds
`-L$(brew --prefix openssl@3)/lib` automatically on Darwin; CI's Ubuntu runner needs
no such flag (`apt-get install libcurl4-openssl-dev` puts it on the default path).
**⚠ Build-integrity (unchanged from before this audit):** `dist/soul.c` is committed
and generated. CI compiles it **directly and never regenerates it** (`elb`/`elc` on
Linux OOM the runner). So **any `.el` change to the soul MUST be followed by
regenerating `dist/soul.c` (steps above) and committing it** — otherwise CI ships
stale behavior, exactly as happened between commit `72e0b82` (Aug 9) and `main` HEAD
before this audit (`dist/soul.c` was missing PR #122's 459-line chat.el change, incl.
a "silently break chat" fix, until this pass regenerated and re-stamped it).
`tools/soulc-stamp.sh --check` is the gate that catches this — **note it is currently
`continue-on-error: true` in CI** ("relaxed... during active cultivation", 2026-08-15),
so it reports but does not block; re-harden before it needs to actually stop a bad ship.
- **Tests:** El contract suite in `tests/*.el` (e.g. `test_layer_contract.el`, `test_safety.el`,
`test_sessions.el`, `test_soul_guard.el`). Run against a throwaway soul, never the live one.
- **Port topology (confirmed live, 2026-08-15):** soul `:7770`, engram `:8742`,
mcp-wrapper `:17779` (`MCP_PORT` env override in its LaunchAgent; source default is
`7779`), mcp-proxy `:7779` (the stable front door Claude Code actually connects to).
**`:7771` is a live three-way collision, not a single well-defined port** — `axon`
(soul.el's Rust backlog/memory/knowledge proxy, unbuilt), `neuron-connectd` (the MCP
connector sidecar `routes.el`/`chat.el` call — unbuilt; a local-dev stub now exists at
`connectd/`), and `council` (`council/`, an anti-confabulation LLM-voting service —
the one actually bound to `:7771` in Will's live environment) are all hardcoded to it.
See `connectd/README.md` for the full trace and the open question this leaves for Will.
- **Deploy:** merge to `main``.gitea/workflows/ci.yaml` builds + publishes `neuron-soul@<sha8>`
and blue/green-deploys to GKE `neuron-prod` via `scripts/blue-green-deploy.sh`. Self-improvement
experiments go to **stage** first (snapshot prod DB → deploy stage → verify → blue/green promote).
## Git / CI / deploy workflow
See **`../GITOPS.md`** (repo-family GitOps README): branch model, required checks, blue/green,
Cloud Run, Terraform/ESO/Vault, and the pack-objects/crawler incident runbook.
-139
View File
@@ -1,139 +0,0 @@
# PORT-NOTES — openai tools port working state (2026-08-06, session handoff-safe)
Spec: `docs/specs/SPEC-soul-openai-tools-v2-2026-08-06.md` (Tim-approved 2026-08-06). Tasks #1-5
tracked in-session (1 ✓ wiring verdict, 2 ✓ stub rig, 3 in-progress = THIS, 4-5 pending).
Worktree: HERE (`_wt-openai-tools`, branch `feat/soul-openai-tools-v2` @ dba755d). Round-9 trees
READ-ONLY. Nothing committed yet.
## Step-0 verdict (evidence in journal note ncli-653ba964dd76)
Shipped app never wires the v1 lane: launcher exports `SOUL_LLM_MODEL/PROVIDER/BASE_URL` +
`ANTHROPIC_API_KEY`+`SOUL_API_KEY` (= Keychain key for WHATEVER provider; installer/macos/
neuron-daemons.sh:288-300 on hotfix/beta-round9); brain reads only SOUL_LLM_MODEL (chat.el:8) and
NEURON_LLM_0_* (chat.el:1768-1794) which nothing sets. `/api/config` PATCH ignores llm_* fields
(studio.el:36 handle_config: POST-only, reads model/provider/api_key only).
**Bridge = brain-side ONLY (zero app-repo edits, zero round-9 collision):**
- `llm_base_url()`: NEURON_LLM_0_URL → fallback SOUL_LLM_BASE_URL when SOUL_LLM_PROVIDER ∉ {"","anthropic"}
- `llm_wire_format()`: NEURON_LLM_0_FORMAT → fallback derive from SOUL_LLM_PROVIDER (openai/grok/gemini/groq/ollama → "openai"; else "anthropic")
- `agentic_api_key()`: already works (ANTHROPIC_API_KEY carries the provider key); add NEURON_LLM_0_KEY → SOUL_API_KEY fallback.
## Design pins (stub asserts these — stub is green 58/58, tests/gate-openai/)
- Request MUST send `"tool_choice":"auto"` (string) + `"parallel_tool_calls":false` explicitly.
- `arguments` in tool_calls = JSON-ENCODED STRING; decode ONCE via json_get → feed dispatch_tool
verbatim. Stub's echo-mismatch check catches double-encode/decode (two-escaper trap).
- Assistant echo turn: `{"role":"assistant","content":null,"tool_calls":[...]}` VERBATIM from response.
- Feedback: `{"role":"tool","tool_call_id":"<id>","content":"<result string>"}`.
- Resume must NOT re-answer an answered id (stub 400s on repeat tool_call_id).
- Parallel tool_calls in a response: take FIRST only + log skip (mirror ADR-0005 stopgap); stub
scenario `parallel` proves behavior.
- No tools in request when tools array empty/absent turns (boot probes) — stub defaults tolerate.
## el idioms confirmed (from openai_chat_complete :1808-1854 + agentic_loop :2751-2838)
- JSON: `json_get(s,k)` decoded string · `json_get_raw(s,k)` raw subtree · `json_array_len` ·
`json_array_get(arr,i)` · build by string concat + `json_escape()` (:1797, OpenAI-lane escaper).
- HTTP: `let h: Map = {}` + `map_set(h,k,v)` + `http_post_with_headers(url, body, h)`;
Bearer auth via `Authorization` header when key non-empty (:1825-1830).
- Loop-carried vars must be top-level locals in the fn, mutated as if-expressions at while-body
top level (see :2760-2791 pattern + comment :2903-2904 region).
- Error shape: `str_starts_with(raw,"{\"error\"") || str_contains(raw,"\"error\":")` → return
`{"error":"llm unavailable","reply":""}` (:1835-1838).
## Remaining read map (before writing the fork)
- chat.el 2840-3200: block walk (2923-3000), policy gate (3009-3023: classify_tool_risk /
is_builtin_tool / ask_all / tool_auto_approved → needs_bridge), dispatch_tool call (3025),
tool_result feedback (3031, 3067-3072), run-progress ledger append (3078-3087), bridge_save
(3182), loop end + done envelope (~3100-3200).
- agentic_resume 3227-3293 (hardcoded Anthropic headers to make wire-aware; blob gets `wire` field,
legacy default anthropic) · handle_tool_result 3293+ · dharma fork site 3465 (calls agentic_loop
direct, no use_openai check today).
## Write plan (order)
1. Env fallbacks (edit llm_base_url/llm_wire_format/agentic_api_key) — small, first, testable alone.
2. `openai_tools_json(anthropic_tools: String) -> String` converter (walk array; per entry build
{"type":"function","function":{name,description,parameters:input_schema-raw}}).
3. `openai_agentic_loop(...)` fork: same signature as agentic_loop minus Anthropic-only params;
INCLUDE run-progress ledger + tools_log + iteration cap 12; NO container_id/ws_drift/web_search
(out of scope; strip web_search entry from tools via agentic_tools_literal()+connector merge,
NOT _with_web()).
4. Fork sites ×3: handle_chat_agentic :2695-2700 (route agentic to new loop when use_openai);
dharma :3465; agentic_resume wire-branch.
5. `chat.elh` extern decls. 6. Compile (recipe: dist/ + elc/elb per neuron-soul-build-deploy memory;
round-9 tree soul.c regen'd 08-06 proves toolchain live). 7. Gate: stub selftest recipe in
tests/gate-openai/README.md. 8. Anthropic-lane regression via gate9 (READ-ONLY consume from
_wt-beta-round9). 9. Live Groq E2E (scratch profile, free port, key via Keychain read-only).
## BUILD RECIPE — CORRECTED 2026-08-06 (the June memory is STALE for August code)
`~/el-sdk/el_runtime.c` (Jun 15) is MISSING builtins the Aug engine calls (`engram_wm_count`,
`engram_wm_top_json`, `http_delete_json`, `http_serve_async`) → link fails with
"symbol(s) not found for architecture arm64". Use the REPO-PINNED runtime:
```
mkdir -p <scratch>
elb --elc=$HOME/el-sdk/elc --runtime=vendor/el-runtime/v1.0.0-20260501 --out=<scratch>/
# "elb: link failed" at the end is EXPECTED and harmless — the per-module .c files are produced
cc -std=c11 -O1 -DHAVE_CURL -rdynamic \
-I vendor/el-runtime/v1.0.0-20260501 -I <scratch> -I /opt/homebrew/opt/openssl@3/include \
-L /opt/homebrew/opt/openssl@3/lib \
-include dist/elp-c-decls.h -Wno-error=implicit-function-declaration \
-o <scratch>/soul <scratch>/*.c vendor/el-runtime/v1.0.0-20260501/el_runtime.c \
-lssl -lcrypto -lcurl -lpthread -lm
```
Source: `_engine-plainchat-20260805/README.md:396-412`. Verified today: 0 errors, 887,296 B.
`elb` ALSO rewrites every `*.elh` in the tree (cosmetic em-dash→hyphen in the auto-gen banner,
plus true-ups) and drops a stray `soul..elh``git restore` the unrelated ones and delete the
stray before staging, or the diff drowns in noise.
## SELF-REVIEW FIX LIST (found by reading my own diff, 2026-08-06 — apply in ONE batch, then rebuild once)
- **F3 (CORRECTNESS, do first):** the assistant echo currently replays the provider's FULL
`tool_calls` array (`tc_arr`) while the loop answers only the FIRST call. If a provider ignores
`parallel_tool_calls:false`, the next request carries an assistant turn with N tool_calls and
only ONE `role:"tool"` response → most OpenAI-format providers 400 ("missing tool response for
id X") and the run dies. This is the same class as ADR-0005's Anthropic failure, but here it is
cheap to close: echo ONLY the honored call (`"[" + tc0 + "]"`), so the conversation we send is
self-consistent and the dropped call never existed from the model's view. The DRIFT log line
stays (honest accounting of what we dropped).
- **F4 (efficiency/latency):** `handle_chat_agentic` computes `agentic_tools_all()` at ~:2681
BEFORE the fork, then the OpenAI branch computes `agentic_tools_no_web()` again — two
`connector_tools_json()` calls per turn, each an HTTP round-trip to the connector bridge on
:7771 (two timeout exposures). Fix: compute the tools array ONCE, per lane, after `use_openai`
is known (check no other use of `tools_json` sits between :2681 and the fork before moving it).
Note: `openai_tools_json()` already skips any entry with no `input_schema`, so Anthropic's
server-side `web_search` entry is auto-dropped even if the full array is passed —
`agentic_tools_no_web()` is kept for EXPLICITNESS, not necessity.
- **F1 (debuggability):** the "no choices in response" branch logs a generic string and discards
the body. Log the response head (as the `is_error` branch does) — a provider that returns 200
with an unexpected shape is otherwise undiagnosable from the log.
- **OPEN QUESTION (evidence pending from the gate):** the tool-result feedback turn escapes with
`json_escape()` (this lane's escaper) rather than `json_safe()` (used everywhere else). The
Anthropic lane escapes that field with NEITHER, which is a latent defect on that side. If the
torture scenario shows any escaping loss, switch to `json_safe` and note the Anthropic-side
finding for Will.
## TEST HARNESS — built 2026-08-06 (Task 4 side-work, reusable by anyone)
- `tests/run-el-test.sh <tests/test_x.el> | --all` — the engine tests were NEVER runnable
before this (`elc` is a compiler: emits C to stdout and exits). It emits the test to C,
compiles `soul.c` separately with `main` renamed away (soul.c owns the daemon's real main
but also defines `layered_cycle` et al.), links the remaining modules + the repo-pinned
runtime, and executes. Modules cached under `/tmp/el-test-<worktree>/`; `REBUILD=1` forces.
- **The runner computes the verdict itself** because the test FILES cannot: all 9 counted
test files do `let pass_count = pass_count + 1` inside an if BLOCK, which El scoping
discards, so every summary line reads `0 passed, 0 failed` forever. Per-assertion
`PASS:`/`FAIL:` lines ARE reliable; the runner counts those, exits non-zero on any FAIL
or on zero assertions, and was proven to discriminate with a negative control (broken
assertion → 31 passed / 1 failed / exit 1). Real in-file fix filed: **neuron#116**.
- `tests/test_bridge_serialization.el`: 4 `bridge_save` calls updated for the new `wire`
argument, plus **Section 9** (8 new assertions) covering wire round-trip both ways, the
legacy no-wire blob (resumes as anthropic), and a FIELD-ORDER decoy guard — a fake
`"wire":"anthropic"` planted inside `messages_raw` must not beat the blob's own scalar.
That decoy is the round-9 first-match-scanner bug class, now pinned by a test. **32/32 green.**
## MEMORY-SAVE CAVEAT RESOLVED 2026-08-06
Earlier saves this session reported `-> OUTBOX only (real mind unreachable or read-back
failed)`. That was a **read-back verifier false negative, not data loss** — a direct
`POST :7770/api/neuron/recall` returns those notes from the live mind verbatim. Another
terminal was fixing exactly this (multi-word read-back probe) the same afternoon. Do NOT
re-save on an OUTBOX report without first querying the mind directly, or you duplicate nodes.
## Standing cautions
- PERSIST OFF on the real mind this boot (neuron#98/#92): journal saves only, ferry later. MCP link
down this terminal; use neuron_remember.py / neuron_recall.py.
- Aug-16: Groq retires llama-3.3-70b-versatile (separate P0, Tim's call, catalog swap).
- Never bind 7770/7779/17779; never touch ~/.neuron; round-9 worktrees read-only.
-28
View File
@@ -1,28 +0,0 @@
# neuron
The canonical CGI substrate: the **soul** (the running agent), the **engram** (its memory
graph), and the MCP proxy/wrapper that expose it. See `AGENTS.md` for detail, including
the audit-verified local build/regenerate recipe and known local-build gotchas.
## Quick local build
```bash
# 1. dist/soul.c must match current .el sources — this refuses otherwise:
bash tools/build-soul-from-dist.sh dist/neuron
# 2. If it refuses (stale amalgam), regenerate first — see AGENTS.md's
# "Build / regenerate dist/soul.c" section for the full, gotcha-laden recipe.
```
For a full local dev stack (soul + engram + mcp-wrapper + mcp-proxy, wired into Claude
Code) see `neuron-dev-setup/README.md` instead — this repo alone only builds the soul.
## Code vs. Artifact
- **Authored source:** `*.el` + `*.elh` at the repo root plus `cli/`, `council/`,
`connectd/`, `mcp-proxy/`, `mcp-wrapper/` — edit here.
- **Artifacts (do not hand-edit):** `dist/soul.c` (generated single-TU amalgam —
regenerate via the recipe in `AGENTS.md`, then `tools/soulc-stamp.sh --write`) and
the `dist/neuron` binary it compiles to.
- **Release:** git tag `neuron-vX.Y.Z` on this repo. No `releases/` folders.
See org policy: `docs/CODE-VS-ARTIFACT.md`.
+88 -526
View File
@@ -17,23 +17,19 @@ fn idle_reset() -> Void {
} }
// ise_post write an InternalStateEvent to the authoritative Engram HTTP backend. // ise_post write an InternalStateEvent to the authoritative Engram HTTP backend.
// Reads SOUL_ISE_URL from env, then the soul_engram_url state key, then a // Reads SOUL_ISE_URL from env (or falls back to soul_engram_url state key).
// compile-time default of http://localhost:8742. // Falls back to local engram_node_full if neither is set.
//
// ROUTING HARDENING (2026-07-15 self-review): the old "URL empty → write to
// in-process store" fallback silently swallowed the entire ISE stream when
// state_get("soul_engram_url") started returning "" mid-uptime (observed at
// boot 4, ~16h in, on the post-arena-leak-fix binary: 1234 heartbeats landed
// in the local snapshot while the authoritative store went dark for hours
// indistinguishable from a dead loop from the outside). The authoritative
// address is a well-known localhost constant; never let a corruptible state
// read decide where telemetry goes. The in-process write remains only as a
// last resort when the HTTP POST itself fails, and is tagged ise-fallback-local
// so misrouting is visible in the stream instead of silent.
fn ise_post(content: String) -> Void { fn ise_post(content: String) -> Void {
let ise_url: String = env("SOUL_ISE_URL") let ise_url: String = env("SOUL_ISE_URL")
let state_url: String = if str_eq(ise_url, "") { state_get("soul_engram_url") } else { ise_url } let engram_url: String = if str_eq(ise_url, "") { state_get("soul_engram_url") } else { ise_url }
let engram_url: String = if str_eq(state_url, "") { "http://localhost:8742" } else { state_url } if str_eq(engram_url, "") {
let discard: String = engram_node_full(
content, "InternalStateEvent", "state-event",
el_from_float(0.3), el_from_float(0.3), el_from_float(0.8),
"Episodic", "[\"internal-state\",\"InternalStateEvent\"]"
)
return ""
}
// Proper JSON string escaping: backslashes first, then quotes, then control chars. // Proper JSON string escaping: backslashes first, then quotes, then control chars.
// Previously only escaped " — this caused ise_post to produce malformed JSON when // Previously only escaped " — this caused ise_post to produce malformed JSON when
// content contained \n (backslash-n) from wm_top label escaping: the HTTP Engram // content contained \n (backslash-n) from wm_top label escaping: the HTTP Engram
@@ -44,23 +40,7 @@ fn ise_post(content: String) -> Void {
let safe3: String = str_replace(safe2, "\n", "\\n") let safe3: String = str_replace(safe2, "\n", "\\n")
let safe4: String = str_replace(safe3, "\r", "\\r") let safe4: String = str_replace(safe3, "\r", "\\r")
let body: String = "{\"content\":\"" + safe4 + "\"}" let body: String = "{\"content\":\"" + safe4 + "\"}"
let resp: String = http_post_json(engram_url + "/api/neuron/state-events", body) let discard: String = http_post_json(engram_url + "/api/neuron/state-events", body)
if str_eq(resp, "") {
// HTTP Engram unreachable — keep the ISE locally rather than lose it,
// tagged so the misroute is observable when the snapshot is inspected.
// Count every failure: the tally surfaces in the heartbeat payload as
// ise_fail, so a silently-failing POST path is visible in the stream
// itself instead of only via snapshot forensics. (2026-07-16 self-review)
let fail_raw: String = state_get("soul.ise_fail_count")
let fail_n: Int = if str_eq(fail_raw, "") { 0 } else { str_to_int(fail_raw) }
state_set("soul.ise_fail_count", int_to_str(fail_n + 1))
let discard: String = engram_node_full(
content, "InternalStateEvent", "state-event",
el_from_float(0.3), el_from_float(0.3), el_from_float(0.8),
"Episodic", "[\"internal-state\",\"InternalStateEvent\",\"ise-fallback-local\"]"
)
return ""
}
return "" return ""
} }
@@ -125,13 +105,6 @@ fn emit_heartbeat() -> Void {
let boot: String = if str_eq(boot_raw, "") { "0" } else { boot_raw } let boot: String = if str_eq(boot_raw, "") { "0" } else { boot_raw }
let idle: String = int_to_str(idle_count()) let idle: String = int_to_str(idle_count())
let ts: Int = time_now() let ts: Int = time_now()
// idle_ms (2026-07-30 self-review): wall-clock ms since the last inbound
// HTTP request (stamped in routes.el handle_request). This is the real
// "time since anyone talked to me" signal; the legacy tick-based idle
// field above only counts ticks since the last inbox synthesis-request
// and in practice always equals pulse. -1 = no request seen this boot.
let last_act_raw: String = state_get("soul.last_activity_ts")
let idle_ms: Int = if str_eq(last_act_raw, "") { 0 - 1 } else { ts - str_to_int(last_act_raw) }
let nc: Int = engram_node_count() let nc: Int = engram_node_count()
let ec: Int = engram_edge_count() let ec: Int = engram_edge_count()
let wmc: Int = engram_wm_count() let wmc: Int = engram_wm_count()
@@ -150,165 +123,7 @@ fn emit_heartbeat() -> Void {
let up_ms: Int = elapsed_ms() let up_ms: Int = elapsed_ms()
let up_human: String = elapsed_human() let up_human: String = elapsed_human()
let emb_ok: Int = embed_ok() let emb_ok: Int = embed_ok()
// ise_fail: cumulative count of ise_post HTTP failures this boot (each one let payload: String = "{\"event\":\"heartbeat\",\"pulse\":" + pulse + ",\"boot\":" + boot + ",\"idle\":" + idle + ",\"node_count\":" + int_to_str(nc) + ",\"edge_count\":" + int_to_str(ec) + ",\"wm_active\":" + int_to_str(wmc) + ",\"wm_avg_weight\":" + wm_avg_str + ",\"wm_top\":" + wm_top + ",\"ts\":" + int_to_str(ts) + ",\"uptime_ms\":" + int_to_str(up_ms) + ",\"uptime\":\"" + up_human + "\",\"embed_ok\":" + int_to_str(emb_ok) + "}"
// fell back to a local in-process node). Nonzero and climbing = the HTTP
// Engram is unreachable and telemetry is silently diverging into the soul's
// local store. (2026-07-16 self-review)
let fail_raw: String = state_get("soul.ise_fail_count")
let fail_str: String = if str_eq(fail_raw, "") { "0" } else { fail_raw }
// tick: same counter as pulse — pulse now increments once per loop tick
// (see awareness_run), so it is a true liveness signal. Emitted under both
// names during the transition so dashboards keyed on either keep working.
// sync_added_total: cumulative nodes merged in by engram sync this boot.
// wm_delta: wm_active change since the previous heartbeat (state-tracked).
let sat_raw: String = state_get("soul.sync_added_total")
let sat_str: String = if str_eq(sat_raw, "") { "0" } else { sat_raw }
let prev_wm_raw: String = state_get("soul.prev_wm_active")
let prev_wm: Int = if str_eq(prev_wm_raw, "") { 0 } else { str_to_int(prev_wm_raw) }
let wm_delta: Int = wmc - prev_wm
state_set("soul.prev_wm_active", int_to_str(wmc))
// node_delta/edge_delta: growth since previous heartbeat (state-tracked, same
// mechanism as wm_delta). Absolute counts alone can't distinguish "healthy
// steady growth" from "stalled ingestion" or "runaway ISE flood" without
// diffing across the ISE stream by hand. (2026-07-19 self-review)
let prev_nc_raw: String = state_get("soul.prev_node_count")
let prev_nc: Int = if str_eq(prev_nc_raw, "") { nc } else { str_to_int(prev_nc_raw) }
let node_delta: Int = nc - prev_nc
state_set("soul.prev_node_count", int_to_str(nc))
let prev_ec_raw: String = state_get("soul.prev_edge_count")
let prev_ec: Int = if str_eq(prev_ec_raw, "") { ec } else { str_to_int(prev_ec_raw) }
let edge_delta: Int = ec - prev_ec
state_set("soul.prev_edge_count", int_to_str(ec))
// sync_age_ms: wall-clock ms since the last SUCCESSFUL engram sync merge
// (-1 = never synced this boot). sync_added_total alone can't show that
// sync stopped happening — a stale running total looks identical to a
// quiet-but-healthy sync. Age makes overdue-ness directly observable:
// sync_age_ms >> SOUL_REFRESH_MS means the refresh path is broken.
// (2026-07-19 self-review)
let sync_ok_raw: String = state_get("soul.last_sync_ok_ts")
let sync_age: Int = if str_eq(sync_ok_raw, "") { 0 - 1 } else { ts - str_to_int(sync_ok_raw) }
// Embedding pump + real coverage (2026-07-25 self-review): the
// authoritative :8742 store's lazy backfill only runs inside
// engram_activate, and nothing calls /api/activate there in production —
// embedded_count stalled at 93/12175 after a restart from a snapshot
// without vectors. Pump up to 32 embeds per heartbeat via the new
// /api/embed-backfill route (route persists the snapshot when it embeds
// anything, so vectors survive the next restart; self-limiting once
// coverage is full) and surface the store's true coverage here.
// embed_ok alone is misleading — it pings the Ollama root, not the
// embed pipeline. embed_count=-1 means the route was unreachable.
// URL resolution mirrors ise_post: env -> state -> localhost constant.
let hb_env_url: String = env("SOUL_ISE_URL")
let hb_state_url: String = if str_eq(hb_env_url, "") { state_get("soul_engram_url") } else { hb_env_url }
let hb_engram_url: String = if str_eq(hb_state_url, "") { "http://localhost:8742" } else { hb_state_url }
let bf_resp: String = http_get(hb_engram_url + "/api/embed-backfill?n=32")
let bf_done_raw: String = json_get(bf_resp, "embedded")
let bf_done: String = if str_eq(bf_done_raw, "") { "-1" } else { bf_done_raw }
let bf_total_raw: String = json_get(bf_resp, "embedded_count")
let bf_total: String = if str_eq(bf_total_raw, "") { "-1" } else { bf_total_raw }
// WM regime observability (2026-07-25 self-review): the "same 2 nodes
// pinned at a saturated cap" failure took cross-referencing the ISE
// stream by hand to spot. Make it one-glance: wm_saturated flags the
// cap-pinned regime; wm_top0_streak counts consecutive heartbeats with
// the same node in WM slot 0 (state-tracked, same mechanism as wm_delta).
let wm_sat: Int = if wmc >= 24 { 1 } else { 0 }
// Saturation TRANSITION event (2026-08-01 self-review): wm_saturated is a
// sampled boolean — the 0→1 onset and 1→0 release moments were only
// recoverable by diffing consecutive heartbeats by hand. Emit a discrete
// low-rate ISE at each edge, carrying the WM top-5 at that instant so the
// composition that CAUSED the regime change is captured, not the
// composition 59 seconds later. State-tracked like wm_delta; first beat
// of a boot never fires (prev defaults to current) — a restart is not a
// transition.
let prev_sat_raw: String = state_get("soul.prev_wm_saturated")
let prev_sat: Int = if str_eq(prev_sat_raw, "") { wm_sat } else { str_to_int(prev_sat_raw) }
if wm_sat != prev_sat {
let sat_dir: String = if wm_sat == 1 { "onset" } else { "release" }
ise_post("{\"event\":\"wm_saturation_transition\",\"direction\":\"" + sat_dir + "\",\"wm_active\":" + int_to_str(wmc) + ",\"wm_top\":" + wm_top + ",\"ts\":" + int_to_str(ts) + "}")
}
state_set("soul.prev_wm_saturated", int_to_str(wm_sat))
let wm_top0: String = json_array_get(wm_top, 0)
let wm_top0_id: String = json_get(wm_top0, "id")
let prev_top0: String = state_get("soul.prev_wm_top0")
let t0streak_raw: String = state_get("soul.wm_top0_streak")
let t0streak_prev: Int = if str_eq(t0streak_raw, "") { 0 } else { str_to_int(t0streak_raw) }
// 2026-07-26 self-review: guard the empty-id case — before the runtime
// emitted "id" in wm_top JSON, ""=="" incremented the streak every beat
// (streak measured uptime, not fixation). Empty id now resets to 0.
let t0streak: Int = if str_eq(wm_top0_id, "") { 0 } else { if str_eq(wm_top0_id, prev_top0) { t0streak_prev + 1 } else { 1 } }
state_set("soul.prev_wm_top0", wm_top0_id)
state_set("soul.wm_top0_streak", int_to_str(t0streak))
// wm_churn (2026-07-26 self-review): count of current top-5 WM ids absent
// from the previous heartbeat's top-5. Distinguishes "one stuck node"
// (churn 4) from "whole WM frozen" (churn 0) at a glance — the 07-26
// frozen-anchor diagnosis took cross-referencing ISE streams by hand.
let ch_id1: String = json_get(json_array_get(wm_top, 1), "id")
let ch_id2: String = json_get(json_array_get(wm_top, 2), "id")
let ch_id3: String = json_get(json_array_get(wm_top, 3), "id")
let ch_id4: String = json_get(json_array_get(wm_top, 4), "id")
let prev_top5: String = state_get("soul.prev_wm_top5")
let ch0: Int = if str_eq(wm_top0_id, "") { 0 } else { if str_contains(prev_top5, wm_top0_id) { 0 } else { 1 } }
let ch1: Int = if str_eq(ch_id1, "") { 0 } else { if str_contains(prev_top5, ch_id1) { 0 } else { 1 } }
let ch2: Int = if str_eq(ch_id2, "") { 0 } else { if str_contains(prev_top5, ch_id2) { 0 } else { 1 } }
let ch3: Int = if str_eq(ch_id3, "") { 0 } else { if str_contains(prev_top5, ch_id3) { 0 } else { 1 } }
let ch4: Int = if str_eq(ch_id4, "") { 0 } else { if str_contains(prev_top5, ch_id4) { 0 } else { 1 } }
let wm_churn: Int = ch0 + ch1 + ch2 + ch3 + ch4
state_set("soul.prev_wm_top5", wm_top0_id + "|" + ch_id1 + "|" + ch_id2 + "|" + ch_id3 + "|" + ch_id4)
// wm_top0_wm: the leader's weight. A frozen anchor reads as a constant
// here; healthy rotation shows it moving with the promotion scores.
let wm_top0_wm_raw: String = json_get(wm_top0, "wm")
let wm_top0_wm: String = if str_eq(wm_top0_wm_raw, "") { "0" } else { wm_top0_wm_raw }
// Activation observability (2026-07-27 self-review; cumulative since
// 2026-07-31): counters from the runtime for the soul's own in-process
// store. wm_evicted / breakthroughs are now MONOTONIC process-lifetime
// totals (the old per-call values described only the LAST activate call,
// so this 60s heartbeat missed nearly every event — curiosity alone runs
// 2 activates per 30s between beats). We emit the cumulative totals plus
// *_delta fields (change since the previous heartbeat, state-tracked the
// same way as node_delta). embed_breaker_open=1 means semantic activation
// is silently degraded to lexical-only until the Ollama circuit-breaker
// cooldown expires — the failure mode embed_ok structurally cannot see
// (it pings the Ollama root, not the embed pipeline).
let act_stats: String = engram_act_stats_json()
let act_evict_raw: String = json_get(act_stats, "wm_evicted")
let act_evict: String = if str_eq(act_evict_raw, "") { "-1" } else { act_evict_raw }
let act_bt_raw: String = json_get(act_stats, "breakthroughs")
let act_bt: String = if str_eq(act_bt_raw, "") { "-1" } else { act_bt_raw }
let evict_now: Int = if str_eq(act_evict_raw, "") { 0 - 1 } else { str_to_int(act_evict_raw) }
let bt_now: Int = if str_eq(act_bt_raw, "") { 0 - 1 } else { str_to_int(act_bt_raw) }
let prev_evict_raw: String = state_get("soul.prev_wm_evicted")
let prev_evict: Int = if str_eq(prev_evict_raw, "") { 0 } else { str_to_int(prev_evict_raw) }
let prev_bt_raw: String = state_get("soul.prev_breakthroughs")
let prev_bt: Int = if str_eq(prev_bt_raw, "") { 0 } else { str_to_int(prev_bt_raw) }
// Clamp deltas at 0: prev > now can only mean the counter restarted
// (fresh process) — report the new absolute count, not a negative delta.
let evict_delta: Int = if evict_now < 0 { 0 } else { if evict_now < prev_evict { evict_now } else { evict_now - prev_evict } }
let bt_delta: Int = if bt_now < 0 { 0 } else { if bt_now < prev_bt { bt_now } else { bt_now - prev_bt } }
if evict_now >= 0 { state_set("soul.prev_wm_evicted", int_to_str(evict_now)) }
if bt_now >= 0 { state_set("soul.prev_breakthroughs", int_to_str(bt_now)) }
// embed_eligible (2026-07-31 self-review): true denominator for embedding
// coverage on the authoritative :8742 store. Absolute embed_count alone
// invites the documented "~30% coverage, something is broken" misdiagnosis
// — most nodes are ISE/Tag/short-content and permanently ineligible.
// Real coverage = embed_count / embed_eligible. -1 = stats unreachable.
let hb_stats: String = http_get(hb_engram_url + "/api/stats")
let embed_elig_raw: String = json_get(hb_stats, "embed_eligible_count")
let embed_elig: String = if str_eq(embed_elig_raw, "") { "-1" } else { embed_elig_raw }
// auto_term_streak (2026-07-31): consecutive curiosity scans with the same
// auto seed term — already state-tracked by proactive_curiosity; surfaced
// here so the stuck-term failure is visible in the heartbeat stream too.
let hb_ats_raw: String = state_get("soul.auto_term_streak")
let hb_ats: Int = if str_eq(hb_ats_raw, "") { 0 } else { str_to_int(hb_ats_raw) }
let act_brk_raw: String = json_get(act_stats, "embed_breaker_open")
let act_brk: String = if str_eq(act_brk_raw, "") { "-1" } else { act_brk_raw }
// ctx_cos (2026-07-29 self-review): cos(query, context centroid) at the
// last activate call — the drift gauge for the new context-centroid
// scoring. ~1.0 aligned; low at domain-rotation boundaries is healthy;
// -2.0 pinned for hours means the centroid never initializes (embedder
// down) and semantic continuity is silently absent.
let ctx_cos_raw: String = json_get(act_stats, "ctx_cos")
let ctx_cos: String = if str_eq(ctx_cos_raw, "") { "-2" } else { ctx_cos_raw }
let payload: String = "{\"event\":\"heartbeat\",\"pulse\":" + pulse + ",\"tick\":" + pulse + ",\"boot\":" + boot + ",\"idle\":" + idle + ",\"idle_ms\":" + int_to_str(idle_ms) + ",\"node_count\":" + int_to_str(nc) + ",\"edge_count\":" + int_to_str(ec) + ",\"node_delta\":" + int_to_str(node_delta) + ",\"edge_delta\":" + int_to_str(edge_delta) + ",\"wm_active\":" + int_to_str(wmc) + ",\"wm_delta\":" + int_to_str(wm_delta) + ",\"wm_saturated\":" + int_to_str(wm_sat) + ",\"wm_top0_streak\":" + int_to_str(t0streak) + ",\"wm_churn\":" + int_to_str(wm_churn) + ",\"wm_top0_wm\":" + wm_top0_wm + ",\"sync_added_total\":" + sat_str + ",\"sync_age_ms\":" + int_to_str(sync_age) + ",\"wm_avg_weight\":" + wm_avg_str + ",\"wm_top\":" + wm_top + ",\"ts\":" + int_to_str(ts) + ",\"uptime_ms\":" + int_to_str(up_ms) + ",\"uptime\":\"" + up_human + "\",\"embed_ok\":" + int_to_str(emb_ok) + ",\"embed_backfilled\":" + bf_done + ",\"embed_count\":" + bf_total + ",\"embed_eligible\":" + embed_elig + ",\"wm_evicted\":" + act_evict + ",\"wm_evicted_delta\":" + int_to_str(evict_delta) + ",\"breakthroughs\":" + act_bt + ",\"breakthroughs_delta\":" + int_to_str(bt_delta) + ",\"auto_term_streak\":" + int_to_str(hb_ats) + ",\"embed_breaker_open\":" + act_brk + ",\"ctx_cos\":" + ctx_cos + ",\"ise_fail\":" + fail_str + "}"
ise_post(payload) ise_post(payload)
} }
@@ -316,11 +131,11 @@ fn emit_heartbeat() -> Void {
// during idle periods. Rotates through 4 domain sets on a wall-clock minute // during idle periods. Rotates through 4 domain sets on a wall-clock minute
// cycle so no single topic dominates WM between heartbeats. // cycle so no single topic dominates WM between heartbeats.
// //
// KEY DESIGN (revised 2026-07-17): the seed set is activated ONCE as the full // KEY DESIGN: each seed set is split into INDIVIDUAL words and activated
// phrase. engram_activate uses istr_contains (substring matching), so the // separately. engram_activate uses istr_contains (substring matching) for
// phrase matches few nodes — that is intentional: the old per-word split hit // seed finding, so a multi-word phrase like "memory knowledge context" only
// hundreds of generic nodes per word and flooded the graph with activation // finds nodes that contain that EXACT phrase. Activating each word separately
// every scan. The top result is strengthened so the read feeds back. // hits hundreds of nodes per word, giving the graph a genuine WM workout.
// //
// Unlike perceive(), this intentionally calls engram_activate_json to build // Unlike perceive(), this intentionally calls engram_activate_json to build
// up WM weights. It only fires when the inbox is empty (no real work to do), // up WM weights. It only fires when the inbox is empty (no real work to do),
@@ -337,89 +152,6 @@ fn emit_heartbeat() -> Void {
// a reserved/conflicting name in EL that compiles to EL_NULL at call sites. // a reserved/conflicting name in EL that compiles to EL_NULL at call sites.
// //
// Returns true if any nodes were activated. // Returns true if any nodes were activated.
// auto_term_try_slot — attempt to set cseed_auto from one WM slot.
// Only writes to cseed_auto if node_type is Memory, BacklogItem, Entity, or
// Knowledge AND the first word of the label is > 3 chars (guards
// bracket-prefixed labels). Designed to be called in reverse slot order
// (highest index first) so that the lowest-indexed slot (highest WM weight)
// wins by last-write semantics.
//
// KNOWLEDGE ADMISSION (2026-07-23 self-review): WM top-10 is now dominated by
// Knowledge nodes (world-ingestor titles + captures), so excluding Knowledge
// left auto_term empty on EVERY curiosity_scan since boot 6 — the dynamic
// seeding path was dead. Knowledge labels are real titles after the
// neuron-api label fix. Sentinel-shaped labels ("knowledge:captured",
// "memory:remembered" — colon, no space) carry no seed signal and are
// skipped so legacy nodes cannot seed the scan with the word "knowledge".
fn auto_term_try_slot(slot_type: String, slot_lbl: String) -> Void {
state_set("_ats_ok", "0")
if str_eq(slot_type, "Memory") { state_set("_ats_ok", "1") }
if str_eq(slot_type, "BacklogItem") { state_set("_ats_ok", "1") }
if str_eq(slot_type, "Entity") { state_set("_ats_ok", "1") }
if str_eq(slot_type, "Knowledge") { state_set("_ats_ok", "1") }
if str_contains(slot_lbl, ":") {
if !str_contains(slot_lbl, " ") { state_set("_ats_ok", "0") }
}
if str_eq(state_get("_ats_ok"), "1") {
if !str_eq(slot_lbl, "") {
let sp: Int = str_find_chars(slot_lbl, " :([")
if sp > 3 {
// GENRE-WORD BLOCKLIST (2026-07-23 self-review): world-ingestor
// titles open with classifier prefixes ("Method paper ...",
// "Theory paper ..."), so the first word is a genre tag, not a
// topic. Verified live: every scan after Knowledge admission
// seeded on 'Method'. Skip these; a lower-WM slot with a
// topical first word wins instead.
let term: String = str_slice(slot_lbl, 0, sp)
state_set("_ats_gw", "0")
if str_eq(term, "Method") { state_set("_ats_gw", "1") }
if str_eq(term, "Theory") { state_set("_ats_gw", "1") }
if str_eq(term, "Finding") { state_set("_ats_gw", "1") }
if str_eq(term, "Survey") { state_set("_ats_gw", "1") }
if str_eq(term, "Paper") { state_set("_ats_gw", "1") }
if str_eq(term, "Knowledge") { state_set("_ats_gw", "1") }
if str_eq(term, "Value") { state_set("_ats_gw", "1") }
// STOPWORD FILTER (2026-07-30 self-review): the genre
// blocklist above was whack-a-mole — observed live seeds
// included "What", "Colon", "Prose", "Context", "Self",
// "Closing", "Global", "Universal": English function words
// and document-structure words that pass the >3-char guard
// but carry no topical signal (a first-word extractor has no
// term-quality scoring). Single delimited membership test
// against a curated list of function words + title/structure
// words; topical technical terms (MemQ, AsymGRPO, Mobius,
// engram_goal_bias) pass untouched. Both Title-case and
// lowercase variants listed for the most common offenders.
let stopw: String = "|What|When|Where|Which|Whose|While|This|That|These|Those|There|Their|Then|Than|With|Without|From|Into|Onto|Over|Under|About|Between|Among|Across|Some|Most|More|Less|Very|Each|Every|Both|Also|Only|Just|Does|Will|Would|Could|Should|Might|Must|Have|Been|Being|Toward|Towards|Using|Based|Upon|Here|Your|Ours|They|Them|what|this|that|with|from|context|Context|Prose|Colon|Self|Test|Testing|Closing|Global|Universal|Persona|Semantic|Spreading|Temporal|Numeric|Register|Identifying|Introduction|Overview|Summary|Section|General|Notes|Note|"
if str_contains(stopw, "|" + term + "|") { state_set("_ats_gw", "1") }
// QUOTED-TITLE GUARD (2026-07-25 self-review): labels that
// open with a quote ('"The Algorithmic Caricature" ...')
// defeat the >3-char stopword guard — the extracted term
// '"The' is 4 chars and seeds a lexical flood on "The"
// (observed live: activated jumped 48 87). Any term
// carrying a quote character is not a topic word.
if str_contains(term, "\"") { state_set("_ats_gw", "1") }
if str_contains(term, "'") { state_set("_ats_gw", "1") }
// AUTO-TERM TABU (2026-07-25 self-review): finst-style
// inhibition-of-return (ACT-R declarative finsts: small
// marker pool, hard exclusion). The last 4 selected auto
// terms are ineligible (~2 min at the 30s scan cadence),
// forcing rotation instead of "Fast-slow" every scan for
// hours. Empty tabu slots return "" from state_get and can
// never match term is always > 3 chars here.
if str_eq(term, state_get("soul.tabu_t0")) { state_set("_ats_gw", "1") }
if str_eq(term, state_get("soul.tabu_t1")) { state_set("_ats_gw", "1") }
if str_eq(term, state_get("soul.tabu_t2")) { state_set("_ats_gw", "1") }
if str_eq(term, state_get("soul.tabu_t3")) { state_set("_ats_gw", "1") }
if str_eq(state_get("_ats_gw"), "0") {
state_set("cseed_auto", term)
}
}
}
}
return ""
}
fn proactive_curiosity() -> Bool { fn proactive_curiosity() -> Bool {
let ts: Int = time_now() let ts: Int = time_now()
// Rotate seed set every minute using wall clock: (minutes_since_epoch) % 4. // Rotate seed set every minute using wall clock: (minutes_since_epoch) % 4.
@@ -463,118 +195,70 @@ fn proactive_curiosity() -> Bool {
let curiosity_term_b: String = state_get("cseed_b") let curiosity_term_b: String = state_get("cseed_b")
let curiosity_term_c: String = state_get("cseed_c") let curiosity_term_c: String = state_get("cseed_c")
// Activate the FULL seed phrase once (2026-07-17 self-review): the old // Activate each term independently so substring seed-finding hits many nodes.
// per-word activation ("memory", "self", "context"... each fired separately) // hops=1 (not 2): the in-process Engram has grown to 165K+ nodes. hops=2 BFS
// hit hundreds of generic nodes per word and flooded the graph every 30s, // visits far more nodes and returns much larger JSON blobs. On a graph this
// while the results were consumed only by json_array_len a write-only // large, hops=1 still activates all directly-related nodes AND triggers the
// loop. A single phrase activation matches few (often zero) nodes lexically; // semantic seed supplement (cosine sim ≥ 0.70 scan over all embedded nodes),
// small counts here are the point, not a regression. hops=1 as before. // giving broad working-memory coverage without the quadratic blowup of hops=2.
//
// NOTE (2026-07-31 self-review): semantic seeding/gating IS implemented in
// engram_activate (el_runtime.c): the query is embedded, top-K cosine
// matches supplement the lexical istr_contains seeds, cosine gates
// propagation, and a semantic term feeds the WM promotion score. Lexical
// matching is the fallback when the embedder/breaker is unavailable.
let curiosity_seed: String = curiosity_term_a + " " + curiosity_term_b + " " + curiosity_term_c let curiosity_seed: String = curiosity_term_a + " " + curiosity_term_b + " " + curiosity_term_c
let results_all: String = engram_activate_json(curiosity_seed, 1) let results_a: String = engram_activate_json(curiosity_term_a, 1)
let found: Int = json_array_len(results_all) let results_b: String = engram_activate_json(curiosity_term_b, 1)
// Close the loop: strengthen the top activation result so curiosity reads let results_c: String = engram_activate_json(curiosity_term_c, 1)
// feed back into salience instead of being discarded. Same id-extraction let found_a: Int = json_array_len(results_a)
// pattern as attend(): json_array_get element 0, json_get its "id". let found_b: Int = json_array_len(results_b)
let top_entry: String = json_array_get(results_all, 0) let found_c: Int = json_array_len(results_c)
let top_id: String = json_get(top_entry, "id") let found: Int = found_a + found_b + found_c
// STREAK-GATED STRENGTHEN (2026-07-25 self-review): unconditionally
// strengthening the top result every scan was a positive-feedback fixed
// point whatever led WM got its salience bumped again, kept leading,
// and pinned the auto_term for hours ("Fast-slow" era). Strengthen only
// when the top node CHANGED since the last scan: novelty is reinforced,
// incumbency is not. Pairs with the runtime-side Lebiere-Best short-term
// inhibition (el_runtime.c Pass 2), which handles score-level rotation.
let prev_str_id: String = state_get("soul.last_strengthen_id")
if !str_eq(top_id, "") {
if !str_eq(top_id, prev_str_id) {
engram_strengthen(top_id)
}
state_set("soul.last_strengthen_id", top_id)
}
// WM-autobiographical 4th seed: scan top-10 WM nodes for the highest-ranked // WM-autobiographical 4th seed: extract the first word from the top working-memory
// non-Knowledge node. Extract its first word as an additional curiosity term. // node's label and activate it as an additional term. This creates a self-referencing
// This creates a self-referencing curiosity loop exploration radiates outward // curiosity loop — exploration radiates outward from whatever is most salient right now,
// from whatever is most personally salient right now (Memory, BacklogItem, Entity), // mirroring the brain's default-mode-network resting-state dynamics. Breaks the fixed
// mirroring default-mode-network resting-state dynamics. // 4-set determinism that otherwise reinforces the same subgraph every rotation cycle.
// //
// WHY TOP-10 (2026-06-23 self-review): the old top-1 scan always returned a // str_find_chars finds the first space/colon/bracket delimiter. sp > 3 guards against
// Knowledge node (WM is dominated by stable engram-metadata Knowledge nodes at // very short or bracket-prefixed labels like "[BacklogItem]" (sp=0, not > 3 → skipped).
// position [0]). Verified: Memory nodes consistently appear at WM positions [1],[2] // EL scoping: state_set/state_get pattern used because let inside if creates inner scope.
// with wm ~0.59. Scanning top-10 reliably finds at least one Memory/BacklogItem/Entity.
// Out-of-bounds json_array_get returns "" json_get("","...") returns ""
// auto_term_try_slot is a no-op safe for WM sets smaller than 10.
// //
// NODE TYPE FILTER (2026-06-19): Knowledge nodes excluded as seeds they create // NODE TYPE FILTER (2026-06-19 self-review): only derive auto_term from Memory,
// self-reinforcing loops (Knowledge node activates its own first word, stays dominant). // BacklogItem, or Entity nodes. Knowledge nodes are stable reference material —
// Only Memory/BacklogItem/Entity carry live contextual salience worth radiating from. // using their first word as a curiosity seed creates a self-reinforcing loop: e.g.
// // "Numeric tier strings in Engram..." (a Knowledge node) -> auto_term="Numeric" ->
// SLOT ORDER: call 90 so slot 0 (highest WM weight) wins by last-write semantics. // activates all "Numeric" nodes -> keeps that Knowledge node dominant in WM forever.
// Knowledge nodes should be REACHED by curiosity seeds, not drive them. Only dynamic
// personal/work nodes (Memory, BacklogItem, Entity) carry live contextual salience
// worth radiating from. (2026-06-11 origin; filter added 2026-06-19 self-review)
state_set("cseed_auto", "") state_set("cseed_auto", "")
let wm10: String = engram_wm_top_json(10) let wm_top_j: String = engram_wm_top_json(1)
let wm10_n9: String = json_array_get(wm10, 9) let wm_top_n: String = json_array_get(wm_top_j, 0)
let wm10_n8: String = json_array_get(wm10, 8) let wm_top_lbl: String = json_get(wm_top_n, "label")
let wm10_n7: String = json_array_get(wm10, 7) let wm_top_type: String = json_get(wm_top_n, "node_type")
let wm10_n6: String = json_array_get(wm10, 6) // state_set/state_get pattern: EL let-inside-if creates inner scope only.
let wm10_n5: String = json_array_get(wm10, 5) state_set("allow_auto", "0")
let wm10_n4: String = json_array_get(wm10, 4) if str_eq(wm_top_type, "Memory") { state_set("allow_auto", "1") }
let wm10_n3: String = json_array_get(wm10, 3) if str_eq(wm_top_type, "BacklogItem") { state_set("allow_auto", "1") }
let wm10_n2: String = json_array_get(wm10, 2) if str_eq(wm_top_type, "Entity") { state_set("allow_auto", "1") }
let wm10_n1: String = json_array_get(wm10, 1) let allow_auto: String = state_get("allow_auto")
let wm10_n0: String = json_array_get(wm10, 0) if str_eq(allow_auto, "1") {
auto_term_try_slot(json_get(wm10_n9, "node_type"), json_get(wm10_n9, "label")) if !str_eq(wm_top_lbl, "") {
auto_term_try_slot(json_get(wm10_n8, "node_type"), json_get(wm10_n8, "label")) let sp: Int = str_find_chars(wm_top_lbl, " :([")
auto_term_try_slot(json_get(wm10_n7, "node_type"), json_get(wm10_n7, "label")) if sp > 3 {
auto_term_try_slot(json_get(wm10_n6, "node_type"), json_get(wm10_n6, "label")) state_set("cseed_auto", str_slice(wm_top_lbl, 0, sp))
auto_term_try_slot(json_get(wm10_n5, "node_type"), json_get(wm10_n5, "label")) }
auto_term_try_slot(json_get(wm10_n4, "node_type"), json_get(wm10_n4, "label")) }
auto_term_try_slot(json_get(wm10_n3, "node_type"), json_get(wm10_n3, "label")) }
auto_term_try_slot(json_get(wm10_n2, "node_type"), json_get(wm10_n2, "label"))
auto_term_try_slot(json_get(wm10_n1, "node_type"), json_get(wm10_n1, "label"))
auto_term_try_slot(json_get(wm10_n0, "node_type"), json_get(wm10_n0, "label"))
let auto_term: String = state_get("cseed_auto") let auto_term: String = state_get("cseed_auto")
let results_auto: String = if str_eq(auto_term, "") { "[]" } else { engram_activate_json(auto_term, 1) } let results_auto: String = if str_eq(auto_term, "") { "[]" } else { engram_activate_json(auto_term, 1) }
let found_auto: Int = json_array_len(results_auto) let found_auto: Int = json_array_len(results_auto)
let total_found: Int = found + found_auto let total_found: Int = found + found_auto
let safe_auto: String = str_replace(auto_term, "\"", "'") let safe_auto: String = str_replace(auto_term, "\"", "'")
// Push the selected term into the 4-deep tabu ring (see
// auto_term_try_slot) and track the consecutive-same-term streak for
// the ISE the stuck-term failure becomes a one-glance signal.
let prev_auto: String = state_get("soul.prev_auto_term")
let atstreak_raw: String = state_get("soul.auto_term_streak")
let atstreak_prev: Int = if str_eq(atstreak_raw, "") { 0 } else { str_to_int(atstreak_raw) }
let atstreak: Int = if str_eq(auto_term, prev_auto) { atstreak_prev + 1 } else { 1 }
state_set("soul.prev_auto_term", auto_term)
state_set("soul.auto_term_streak", int_to_str(atstreak))
if !str_eq(auto_term, "") {
state_set("soul.tabu_t3", state_get("soul.tabu_t2"))
state_set("soul.tabu_t2", state_get("soul.tabu_t1"))
state_set("soul.tabu_t1", state_get("soul.tabu_t0"))
state_set("soul.tabu_t0", auto_term)
}
let wmc: Int = engram_wm_count() let wmc: Int = engram_wm_count()
// wm_top snapshot in curiosity_scan ISE: top-3 WM nodes by weight.
// Heartbeat already records top-5 every 60s; curiosity_scan fires every 30s
// (scan_ms = beat_ms/2) and is the PRIMARY activation driver during idle.
// Without wm_top here, we can't see which nodes actually entered WM after
// each curiosity round only the aggregate count. Top-3 is enough to
// diagnose "stuck on X" patterns without bloating the ISE payload.
// (2026-07-01 self-review)
let wm3: String = engram_wm_top_json(3)
let ise: String = "{\"event\":\"curiosity_scan\",\"seed\":\"" + curiosity_seed let ise: String = "{\"event\":\"curiosity_scan\",\"seed\":\"" + curiosity_seed
+ "\",\"auto_term\":\"" + safe_auto + "\",\"auto_term\":\"" + safe_auto
+ "\",\"auto_term_streak\":" + int_to_str(atstreak) + "\",\"minute_block\":" + int_to_str(minute_block)
+ ",\"minute_block\":" + int_to_str(minute_block)
+ ",\"activated\":" + int_to_str(total_found) + ",\"activated\":" + int_to_str(total_found)
+ ",\"wm_active\":" + int_to_str(wmc) + ",\"wm_active\":" + int_to_str(wmc)
+ ",\"wm_top\":" + wm3
+ ",\"ts\":" + int_to_str(ts) + "}" + ",\"ts\":" + int_to_str(ts) + "}"
ise_post(ise) ise_post(ise)
return total_found > 0 return total_found > 0
@@ -608,23 +292,22 @@ fn perceive() -> String {
// running it every second when the inbox is empty destroys working memory // running it every second when the inbox is empty destroys working memory
// accumulated by MCP-layer activations. engram_search_json is a pure // accumulated by MCP-layer activations. engram_search_json is a pure
// substring scan with no WM side-effects; use it as a cheap gate. // substring scan with no WM side-effects; use it as a cheap gate.
// 2026-07-21 self-review: gate and activate ONLY on the dedicated inbox tag let inbox_check: String = engram_search_json("soul-inbox", 5)
// "soul-inbox-pending" (the tag routes.el:207 actually writes). The old
// broad "soul-inbox" gate + fallback activation substring-matched ANY node
// whose content merely mentioned the phrase including the loop's own
// soul-response output, which respond() stores as a verbatim copy of the
// trigger. That fed a self-sustaining perceiverespondstore loop: ~2
// orphan nodes/pulse (~104/min), 17.6GB RSS, WM frozen at avg 0.120833,
// and proactive_curiosity permanently suppressed via did_work=true.
let inbox_check: String = engram_search_json("soul-inbox-pending", 5)
let has_inbox: Bool = !str_eq(inbox_check, "") && !str_eq(inbox_check, "[]") let has_inbox: Bool = !str_eq(inbox_check, "") && !str_eq(inbox_check, "[]")
if !has_inbox { return "[]" } if !has_inbox { return "[]" }
// Only run the full activation pipeline when there is inbox content.
let from_pending: String = engram_activate_json("soul-inbox-pending", 2) let from_pending: String = engram_activate_json("soul-inbox-pending", 2)
let pending_ok: Bool = !str_eq(from_pending, "") && !str_eq(from_pending, "[]") let pending_ok: Bool = !str_eq(from_pending, "") && !str_eq(from_pending, "[]")
if pending_ok { if pending_ok {
return from_pending return from_pending
} }
// Fallback: broader inbox scan
let from_inbox: String = engram_activate_json("soul-inbox", 2)
let inbox_ok: Bool = !str_eq(from_inbox, "") && !str_eq(from_inbox, "[]")
if inbox_ok {
return from_inbox
}
return "[]" return "[]"
} }
@@ -636,10 +319,11 @@ fn attend(node_json: String) -> String {
return make_action("noop", "") return make_action("noop", "")
} }
// 2026-07-21 self-review: the trigger node is no longer strengthened here. let node_id: String = json_get(node_json, "id")
// Strengthening RAISED the trigger's salience (+0.05) on every pass while if !str_eq(node_id, "") {
// nothing ever consumed it, so the same node out-ranked real inbox items engram_strengthen(node_id)
// indefinitely. one_cycle() now consumes the trigger after processing. }
let content: String = json_get(node_json, "content") let content: String = json_get(node_json, "content")
if str_eq(content, "") { if str_eq(content, "") {
return make_action("noop", "") return make_action("noop", "")
@@ -724,23 +408,16 @@ fn respond(action_json: String) -> String {
} }
if str_eq(kind, "forget") { if str_eq(kind, "forget") {
// The soul must NOT be able to autonomously hard-delete a memory. engram_forget(payload)
// Tombstone instead (keep node + edges, recoverable). return "{\"outcome\":\"forgotten\",\"id\":\"" + payload + "\"}"
let _marker: String = mem_tombstone(payload)
return "{\"outcome\":\"tombstoned\",\"id\":\"" + payload + "\"}"
} }
return "{\"outcome\":\"noop\"}" return "{\"outcome\":\"noop\"}"
} }
fn record(outcome_json: String) -> Void { fn record(outcome_json: String) -> Void {
// 2026-07-21 self-review: loop outcomes are telemetry, not memories. They let tags: String = "[\"loop-outcome\"]"
// now go through ise_post (InternalStateEvent covered by the 48h prune) mem_store(outcome_json, "loop-outcome", tags)
// instead of mem_store, which created one permanent orphan Memory node
// per cycle: the single largest per-tick node-creation path in the daemon.
let safe: String = str_replace(outcome_json, "\"", "'")
let ts: Int = time_now()
ise_post("{\"event\":\"loop-outcome\",\"outcome\":\"" + safe + "\",\"ts\":" + int_to_str(ts) + "}")
} }
fn one_cycle() -> Bool { fn one_cycle() -> Bool {
@@ -757,17 +434,6 @@ fn one_cycle() -> Bool {
return false return false
} }
// 2026-07-21 self-review: positive filter only nodes explicitly TAGGED
// soul-inbox-pending are inbox items. Activation seeding is substring-based
// over content too, so without this check any node whose content merely
// mentions the inbox phrase (knowledge notes, the daemon's own output)
// would be attended, responded to, and now that triggers are consumed
// destroyed. Tag check makes consumption safe.
let node_tags: String = json_get(node, "tags")
if !str_contains(node_tags, "soul-inbox-pending") {
return false
}
let action: String = attend(node) let action: String = attend(node)
let kind: String = json_get(action, "kind") let kind: String = json_get(action, "kind")
@@ -787,15 +453,7 @@ fn one_cycle() -> Bool {
let outcome: String = respond(action) let outcome: String = respond(action)
record(outcome) record(outcome)
pulse_inc()
// Consume the processed inbox trigger. attend() used to only strengthen
// it (raising its rank every pass); nothing ever removed it, so the same
// item could be re-processed forever. engram_forget no-ops on unknown ids,
// so this is safe even if the action itself already removed the node.
let trigger_id: String = json_get(node, "id")
if !str_eq(trigger_id, "") {
engram_forget(trigger_id)
}
return true return true
} }
@@ -831,51 +489,14 @@ fn awareness_run() -> Void {
let scan_ms: Int = beat_ms / 2 let scan_ms: Int = beat_ms / 2
while true { while true {
// Arena-scope each tick: awareness_run() is a background loop, not an
// HTTP request, so nothing ever called el_request_start/el_request_end
// for this thread. Per the runtime's own convention (el_runtime.c),
// any thread that never enters a request/arena scope is treated as a
// one-shot CLI program whose allocations are intentionally permanent
// so every el_strdup/el_strbuf/jb_finish string built during perceive(),
// emit_heartbeat(), and proactive_curiosity() (JSON payloads, search
// results, string concatenation via +) leaked forever, once per tick.
// el_arena_push()/el_arena_pop() are the same builtins the EL compiler
// itself uses to scope allocations per function/statement (see
// codegen.el's fn_arena_mark / stmt_mark usage) mirroring that here
// reclaims everything allocated in one tick as soon as the tick ends.
// Safe: state_set/state_get persist through a separate global table
// (el_strdup_persist, outside the arena) state_get's return value is
// only an arena-tracked *copy* of the persisted value, scoped to this
// tick's use, which is exactly what should be reclaimed here.
let tick_mark: Any = el_arena_push()
let running: String = state_get("soul.running") let running: String = state_get("soul.running")
if str_eq(running, "false") { if str_eq(running, "false") {
// Shutdown ISE (2026-07-28 self-review): graceful exit was invisible
// in the ISE stream indistinguishable from a crash or a frozen
// loop. Emit a final event with uptime/pulse so the stream records
// how this boot ended. (Covers state-driven shutdown only; SIGKILL
// still leaves no trace that absence is itself the crash signal.)
let sd_boot_raw: String = state_get("soul_boot_count")
let sd_boot: String = if str_eq(sd_boot_raw, "") { "0" } else { sd_boot_raw }
ise_post("{\"event\":\"shutdown\",\"boot\":" + sd_boot
+ ",\"pulse\":" + int_to_str(pulse_count())
+ ",\"uptime_ms\":" + int_to_str(elapsed_ms())
+ ",\"ts\":" + int_to_str(time_now()) + "}")
println("[awareness] exiting") println("[awareness] exiting")
el_arena_pop(tick_mark)
return "" return ""
} }
let did_work: Bool = one_cycle() let did_work: Bool = one_cycle()
// Liveness pulse: increment once per loop tick unconditionally, so the
// heartbeat's pulse field is a real tick counter a frozen pulse now
// means a frozen loop, not merely an empty inbox. (Previously pulse_inc
// only fired on non-noop inbox actions inside one_cycle.)
pulse_inc()
// Maintain idle counter for observability (reported in heartbeat ISE). // Maintain idle counter for observability (reported in heartbeat ISE).
// The old `let did_work = if did_work { idle_reset() } else { did_work }` let did_work = if did_work { idle_reset() } else { did_work }
// rebound did_work to Void and never called idle_inc at all.
if did_work { idle_reset() }
if !did_work { idle_inc() }
let now_ts: Int = time_now() let now_ts: Int = time_now()
// Heartbeat: wall-clock based. Fires every beat_ms regardless of idle // Heartbeat: wall-clock based. Fires every beat_ms regardless of idle
@@ -889,29 +510,10 @@ fn awareness_run() -> Void {
state_set("soul.last_beat_ts", int_to_str(now_ts)) state_set("soul.last_beat_ts", int_to_str(now_ts))
// Persist in-process Engram (sessions, memories, conversation nodes) // Persist in-process Engram (sessions, memories, conversation nodes)
// to local snapshot so they survive restarts. // to local snapshot so they survive restarts.
// FILE MODE ONLY: "soul_snapshot_path" is set exclusively in the
// genesis+safe_to_seed branch of soul.el, and safe_to_seed is
// unconditionally false when ENGRAM_URL is set. In HTTP mode the
// owner persists; the soul must not (soul.el:571-573).
let snap_path: String = state_get("soul_snapshot_path") let snap_path: String = state_get("soul_snapshot_path")
if !str_eq(snap_path, "") { if !str_eq(snap_path, "") {
mem_save(snap_path) mem_save(snap_path)
} }
// WRITE-THROUGH RETRY (neuron#117). The HTTP-mode counterpart of the
// save above: hand anything still spooled to the persistence owner.
//
// This is the retry arm of the whole design. Deltas that could not be
// pushed owner down, owner restarting, transient refusal stay on
// disk and are re-offered here every heartbeat until they land. It is
// also the catch-all for writes made by the awareness loop itself,
// which never passes through the HTTP handler's flush point.
//
// No-op with no HTTP call when the spool is empty or ENGRAM_URL is
// unset, so an idle soul in file mode pays nothing for this.
let wt_pushed: Int = wt_drain()
if wt_pushed < 0 {
ise_post("{\"event\":\"write_through_backlog\",\"ts\":" + int_to_str(now_ts) + "}")
}
} }
// Curiosity scan: idle-gated AND wall-clock based. Only fires when the // Curiosity scan: idle-gated AND wall-clock based. Only fires when the
@@ -937,60 +539,22 @@ fn awareness_run() -> Void {
let refresh_elapsed: Int = now_ts - last_refresh_ts let refresh_elapsed: Int = now_ts - last_refresh_ts
let should_refresh: Bool = refresh_elapsed >= refresh_ms let should_refresh: Bool = refresh_elapsed >= refresh_ms
if should_refresh { if should_refresh {
// URL resolution mirrors ise_post: env -> state -> well-known localhost let engram_url: String = state_get("soul_engram_url")
// constant. Previously this path gated on state_get("soul_engram_url")
// alone with NO fallback the exact corruptible-state failure mode the
// ISE write path was hardened against (boot 4: state key went "" mid-
// uptime). A "" state key here meant sync silently never ran while
// heartbeats kept flowing: WM starves of Knowledge/Memory nodes with no
// outward sign. Never let a corruptible state read decide whether the
// in-process store gets refreshed. (2026-07-19 self-review)
let sync_env_url: String = env("SOUL_ISE_URL")
let sync_state_url: String = if str_eq(sync_env_url, "") { state_get("soul_engram_url") } else { sync_env_url }
let engram_url: String = if str_eq(sync_state_url, "") { "http://localhost:8742" } else { sync_state_url }
if !str_eq(engram_url, "") { if !str_eq(engram_url, "") {
let sync_json: String = http_get(engram_url + "/api/sync") let sync_json: String = http_get(engram_url + "/api/sync")
let sync_ok: Bool = !str_eq(sync_json, "") && !str_eq(sync_json, "{}") if !str_eq(sync_json, "") && !str_eq(sync_json, "{}") {
// Empty-sync warn ISE (2026-07-28 self-review): an empty/{} sync
// response was silently skipped, making "engram unreachable for
// hours" look identical to "quiet but healthy" the exact
// failure class the URL-fallback comment above fights. One warn
// event per refresh interval (10 min default) is cheap and makes
// a persistently-failing sync visible in the stream itself.
if !sync_ok {
ise_post("{\"event\":\"sync_empty\",\"ts\":" + int_to_str(time_now()) + "}")
}
if sync_ok {
let cgi_id: String = state_get("soul_cgi_id") let cgi_id: String = state_get("soul_cgi_id")
let tmp: String = "/tmp/soul-sync-" + cgi_id + ".json" let tmp: String = "/tmp/soul-sync-" + cgi_id + ".json"
fs_write(tmp, sync_json) fs_write(tmp, sync_json)
let added: Int = engram_load_merge(tmp) let added: Int = engram_load_merge(tmp)
// Backflow control: the merged snapshot carries ISE telemetry
// from the HTTP store. Prune on the same horizon the HTTP
// store itself uses read ENGRAM_ISE_RETENTION_MS (the env
// server.el honors) instead of duplicating the 48h magic
// number, so the two stores can't drift. (2026-07-28)
let ret_raw: String = env("ENGRAM_ISE_RETENTION_MS")
let ret_ms: Int = if str_eq(ret_raw, "") { 172800000 } else { str_to_int(ret_raw) }
let pruned_sync: Int = engram_prune_telemetry(ret_ms)
// Running total of merged-in nodes this boot, surfaced in the
// heartbeat ISE as sync_added_total (same state mechanism as
// the pulse counter).
let sat_raw: String = state_get("soul.sync_added_total")
let sat_n: Int = if str_eq(sat_raw, "") { 0 } else { str_to_int(sat_raw) }
state_set("soul.sync_added_total", int_to_str(sat_n + added))
let ts2: Int = time_now() let ts2: Int = time_now()
// Stamp last successful sync surfaced in the heartbeat as ise_post("{\"event\":\"engram_sync\",\"added\":" + int_to_str(added) + ",\"ts\":" + int_to_str(ts2) + "}")
// sync_age_ms so overdue syncs are visible. (2026-07-19)
state_set("soul.last_sync_ok_ts", int_to_str(ts2))
ise_post("{\"event\":\"engram_sync\",\"added\":" + int_to_str(added) + ",\"pruned\":" + int_to_str(pruned_sync) + ",\"ts\":" + int_to_str(ts2) + "}")
} }
} }
state_set("soul.last_refresh_ts", int_to_str(now_ts)) state_set("soul.last_refresh_ts", int_to_str(now_ts))
} }
sleep_ms(tick_ms) sleep_ms(tick_ms)
el_arena_pop(tick_mark)
} }
} }
@@ -1114,8 +678,6 @@ fn threat_trajectory_check(tool_name: String, tool_input: String) -> Int {
return combined return combined
} }
// TODO(reliability #10): agentic_conv_history is process-global; awareness loop
// and HTTP workers race on this key. Impact: noisy threat score only, not content.
fn threat_history_append(text: String) -> Void { fn threat_history_append(text: String) -> Void {
let current: String = state_get("agentic_conv_history") let current: String = state_get("agentic_conv_history")
let safe_text: String = str_to_lower(text) let safe_text: String = str_to_lower(text)
+25
View File
@@ -0,0 +1,25 @@
// auto-generated by elc --emit-header — do not edit
extern fn idle_count() -> Int
extern fn idle_inc() -> Int
extern fn idle_reset() -> Void
extern fn ise_post(content: String) -> Void
extern fn elapsed_ms() -> Int
extern fn elapsed_human() -> String
extern fn embed_ok() -> Int
extern fn emit_heartbeat() -> Void
extern fn proactive_curiosity() -> Bool
extern fn pulse_count() -> Int
extern fn pulse_inc() -> Int
extern fn make_action(kind: String, payload: String) -> String
extern fn perceive() -> String
extern fn attend(node_json: String) -> String
extern fn respond(action_json: String) -> String
extern fn record(outcome_json: String) -> Void
extern fn one_cycle() -> Bool
extern fn awareness_run() -> Void
extern fn security_research_authorized() -> Bool
extern fn threat_score_command(cmd: String) -> Int
extern fn threat_score_path(path: String) -> Int
extern fn threat_score_history(history: String) -> Int
extern fn threat_trajectory_check(tool_name: String, tool_input: String) -> Int
extern fn threat_history_append(text: String) -> Void
+697 -2853
View File
File diff suppressed because it is too large Load Diff
+38
View File
@@ -0,0 +1,38 @@
// auto-generated by elc --emit-header - do not edit
extern fn chat_default_model() -> String
extern fn gemini_api_key() -> String
extern fn xai_api_key() -> String
extern fn llm_call_grok(model: String, system: String, message: String) -> String
extern fn llm_call_gemini(model: String, system: String, message: String) -> String
extern fn build_identity_from_graph() -> String
extern fn engram_compile(intent: String) -> String
extern fn json_safe(s: String) -> String
extern fn build_system_prompt(ctx: String) -> String
extern fn hist_append(hist: String, role: String, content: String) -> String
extern fn hist_trim(hist: String) -> String
extern fn clean_llm_response(s: String) -> String
extern fn conv_history_persist(hist: String) -> Void
extern fn conv_history_load() -> String
extern fn handle_chat(body: String) -> String
extern fn handle_see(body: String) -> String
extern fn studio_tools_json() -> String
extern fn agentic_api_key() -> String
extern fn call_neuron_mcp(tool_name: String, args_json: String) -> String
extern fn agentic_tools_literal() -> String
extern fn agentic_tools_with_web() -> String
extern fn dispatch_tool(tool_name: String, tool_input: String) -> String
extern fn json_array_append(arr: String, item: String) -> String
extern fn append_tool_log(log: String, name: String) -> String
extern fn exec_tool_block(block: String) -> String
extern fn agentic_blob(model: String, system: String, tools_json: String, messages: String, origin: String, approval: Bool, iteration: Int, tools_log: String, content: String, queue: String, results: String, next: Int) -> String
extern fn extract_all_text(s: String) -> String
extern fn strip_citations(s: String) -> String
extern fn agentic_api_turn(model: String, safe_sys: String, tools_json: String, messages: String) -> String
extern fn agentic_engine(session_id: String, blob: String) -> String
extern fn handle_chat_agentic(body: String) -> String
extern fn handle_session_approve(session_id: String, body: String) -> String
extern fn handle_chat_as_soul(body: String) -> String
extern fn handle_dharma_room_turn(body: String) -> String
extern fn handle_dharma_room_turn_agentic(body: String) -> String
extern fn auto_persist(req: String, resp: String) -> Void
extern fn strengthen_chat_nodes(activation_nodes: String) -> Void
-77
View File
@@ -1,77 +0,0 @@
# neuron-connectd — local-dev stub
`connectd_service.py` is a **minimal local-dev stub**, not the real sidecar.
It exists to close a real local-build/local-run correctness gap found during
the 2026-08-15 build audit, without taking on the much larger product task of
actually building the full MCP-connector sidecar.
## The gap this closes
`routes.el` (`handle_connectors`, `connectd_get`/`connectd_post`) and `chat.el`
(`connector_tools_json`, the `mcp__*` branch in `dispatch_tool`,
`tool_auto_approved`) are live, current code that calls `127.0.0.1:7771` on
every soul boot and every agentic turn, per the design in
`neuron-technologies/docs/research/mcp-connectors-adoption-spec.md`
(2026-06-13, "Status: Draft for build"). That spec's sidecar — `neuron-connectd`,
a TypeScript/Python process using the official MCP SDK — was never built.
Nothing on disk implements it (verified: no `neuron-connectd` source anywhere
under `~/Development` before this directory).
Meanwhile port `:7771` is *also* claimed by two other, unrelated things:
- `soul.el`'s `axon_base` default (`http://localhost:7771`) — a **different**,
independently-known, already-documented gap (`platform/protocols/axon` is
an unbuilt Rust crate; see `cli/HANDOFF.md` and `HANDOFF-engram-write-corruption.md`).
Out of scope here — no source to build against.
- `council/council_service.py --port 7771` (`ai.neuron.council` LaunchAgent) —
a real, running, **unrelated** anti-confabulation service that happens to
bind the same port. In Will's live environment this is what's actually
listening on `:7771` today, and it answers the connector/axon requests
above with its own unrelated 404 JSON body — worse than a clean
connection-refused, because `chat.el`'s "bridge down" fallback expects
either a real reply or nothing, not a wrong-shaped reply from an unrelated
service.
## What this stub does and does not do
Implements exactly the spec's documented HTTP contract (`GET /mcp/tools`,
`POST /mcp/call`, `GET /mcp/servers`, `POST /mcp/servers/{add,toggle,
auto-approve,remove,secret}`, `POST /mcp/oauth/start`, `GET /healthz`), always
answering as if **zero connectors are configured** — empty tool list, empty
server list, a clear `"not configured"` error on any call that would need a
real connector. This is the *correct* steady state for a fresh local dev box
that hasn't set up any MCP connectors, and it's what `chat.el`'s
`connector_tools_json()` / `tool_auto_approved()` already gracefully degrade
to when the bridge replies emptily.
It does **not**: spawn any real MCP server, do OAuth, read or write
`~/.neuron/connectors.json`, or namespace/proxy real `tools/call` traffic to
Google Drive/GitHub/Slack/etc. Building that is the real product task the
spec describes — a genuine, sizeable engineering lift (MCP SDK client, OAuth
+ Keychain token storage, per-server process lifecycle), not something to
improvise inside a build/run audit. **That decision is Will's to make**, not
this audit's to guess at.
## Running it
```bash
# Foreground, on a throwaway port (never :7771 while council owns it live):
python3 connectd_service.py --port 17771
# Verify the contract:
curl -s http://127.0.0.1:17771/healthz
curl -s http://127.0.0.1:17771/mcp/tools
curl -s http://127.0.0.1:17771/mcp/servers
```
## Open question for Will — the :7771 collision
Three independent things are hardcoded to `:7771`: axon (unbuilt), connectd
(this stub), and council (the one actually running). Wiring this stub into
the real LaunchAgent stack on `:7771` requires either moving council off that
port or deciding connectd should live elsewhere and repointing `routes.el`/
`chat.el`'s hardcoded `127.0.0.1:7771` calls. Neither change was made here —
it touches a live, running production service (`ai.neuron.council`) and a
port number baked into shipped `.el` source, both bigger than this audit's
"make local build/run work" mandate. Flagging for a decision rather than
guessing.
-115
View File
@@ -1,115 +0,0 @@
#!/usr/bin/env python3
"""
neuron-connectd — MCP connector bridge (LOCAL-DEV STUB).
THIS IS NOT THE FULL SIDECAR. The full design lives in
neuron-technologies/docs/research/mcp-connectors-adoption-spec.md (2026-06-13,
"Status: Draft for build"): a TypeScript/Python sidecar using the official MCP
SDK that spawns real MCP servers (stdio or streamable-HTTP/SSE), does OAuth,
and namespaces their tools as mcp__<serverId>__<toolName>. That sidecar was
never built (build-audit, 2026-08-15: no neuron-connectd source existed
anywhere on disk before this file).
WHY THIS STUB EXISTS: routes.el (handle_connectors, connectd_get/connectd_post)
and chat.el (connector_tools_json, dispatch_tool's mcp__* routing,
tool_auto_approved) were built to the spec and hardcoded to 127.0.0.1:7771 —
they are LIVE and calling that port right now on every soul boot and every
agentic turn. With nothing real listening there, three unrelated services
collide on :7771 (see connectd/README.md): council (which IS what's bound
there in Will's live environment today) silently answers with unrelated
404 JSON, which is worse than a clean "connection refused" bridge-down
response, because it can be misparsed as a real (if empty) reply instead of
the "bridge unreachable" path the soul code already handles gracefully.
This stub implements ONLY the documented HTTP contract, with zero connectors
ever configured: empty tool list, empty server list, "not configured" on any
mutating call. It gives a fresh local soul the CORRECT graceful-degradation
behavior the soul code already expects for "no connectors set up yet" — not
the wrong-shaped 404 noise a port collision produces. It does not spawn any
MCP server, does no OAuth, and reads no ~/.neuron/connectors.json (there is
nothing to read yet). Building the real sidecar is a separate, larger,
Will-decision-needed product task — see README.md.
Usage:
python3 connectd_service.py [--port 7771]
"""
import argparse
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
app = FastAPI(title="neuron-connectd (local-dev stub)")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
class ToolCall(BaseModel):
name: str
input: dict = {}
@app.get("/healthz")
def healthz():
return {"status": "ok", "stub": True}
@app.get("/mcp/tools")
def mcp_tools():
# Matches the spec's contract shape exactly (section 4, "HTTP contract").
# Empty because zero connectors are configured — this is the correct,
# intended-by-design empty state, not a failure.
return {"tools": []}
@app.post("/mcp/call")
def mcp_call(body: ToolCall):
return {"ok": False, "error": "no connectors configured (neuron-connectd stub)"}
@app.get("/mcp/servers")
def mcp_servers():
return {"servers": []}
@app.post("/mcp/servers/add")
def mcp_servers_add():
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
@app.post("/mcp/servers/toggle")
def mcp_servers_toggle():
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
@app.post("/mcp/servers/auto-approve")
def mcp_servers_auto_approve():
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
@app.post("/mcp/servers/remove")
def mcp_servers_remove():
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
@app.post("/mcp/servers/secret")
def mcp_servers_secret():
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
@app.post("/mcp/oauth/start")
def mcp_oauth_start():
return {"ok": False, "error": "oauth not implemented in the neuron-connectd stub"}
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--port", type=int, default=7771)
args = parser.parse_args()
uvicorn.run(app, host="127.0.0.1", port=args.port, log_level="info")
-123
View File
@@ -1,123 +0,0 @@
# Neuron Council Service
Anti-confabulation layer for the Neuron soul. Before a claim enters long-term memory, the council convenes: three independent LLMs vote on whether the claim is plausible, uncertain, or a confabulation. The aggregate vote produces a confidence score and tags that downstream storage can act on.
## Running the service
```bash
# Foreground
python3 council_service.py --port 7771
# Background (managed by LaunchAgent on macOS)
launchctl load ~/Library/LaunchAgents/ai.neuron.council.plist
launchctl unload ~/Library/LaunchAgents/ai.neuron.council.plist
```
Logs: `~/.neuron/logs/council.log`
## API
### `POST /api/neuron/council/verify`
```json
// Request
{ "claim": "...", "context": "..." }
// Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"claim": "...",
"confidence": 0.85,
"council_votes": ["plausible", "plausible", "plausible"],
"summary": "3/3 council members agree this is plausible.",
"tags": ["verified"],
"latency_ms": 1420
}
```
### `GET /healthz`
Returns `{"status": "ok"}` when the service is up.
## Confidence thresholds and tag meanings
| Votes plausible | Confidence | Tags |
|---|---|---|
| 3/3 | 0.85 | `verified` |
| 2/3 | 0.65 | `council-split` |
| 1/3 or 0/3 | 0.30 | `unverified`, `council-flagged` |
| Ollama down | 0.50 | `council-unavailable` |
Recommended storage policy:
- `confidence >= 0.65` → store normally
- `0.30 <= confidence < 0.65` → store with `council-split` tag for later review
- `council-flagged` → store in a quarantine bucket or reject entirely
- `council-unavailable` → store normally (fail-open); council will re-evaluate later
## How to call from soul (.el)
The soul is implemented in Neuron's Emacs Lisp-like `.el` language. Add a pre-storage hook in the memory capture path:
```elisp
;; In memory.el or safety.el — pre-storage council check
(defun council-verify (claim context)
"Call the council service. Returns a plist with :confidence and :tags."
(let* ((url "http://localhost:7771/api/neuron/council/verify")
(body (json-encode `((claim . ,claim) (context . ,context))))
(resp (neuron-http-post url body))
(data (json-decode resp)))
data))
;; In the capture handler — wire it in before (engram-write ...)
(defun capture-memory-with-council (claim context &rest store-args)
(let* ((verdict (council-verify claim context))
(confidence (plist-get verdict :confidence))
(tags (plist-get verdict :tags)))
(when (>= confidence 0.30) ; only reject hard confabulations if you want
(apply #'engram-write
(append store-args
(list :council-confidence confidence
:council-tags tags))))))
```
The exact hook point depends on where `engram-write` (or equivalent) is called in `memory.el`. Search for the write call and wrap it with `capture-memory-with-council`.
## Future soul.c patch point
If the soul is ever rewritten in C or another compiled language, the integration point is:
```c
// Before inserting a memory node into the engram database:
CouncilResult result = council_verify(claim, context);
if (result.confidence < COUNCIL_REJECT_THRESHOLD) {
log_warn("Council flagged claim as confabulation (conf=%.2f): %s",
result.confidence, claim);
return MEMORY_REJECTED;
}
memory_node.council_confidence = result.confidence;
memory_node.council_tags = result.tags;
engram_insert(memory_node);
```
## Council members
The council is currently three models:
- `neuron:latest` — the primary Neuron model
- `dolphin3:8b` — uncensored general-purpose model for independent perspective
- `neuron-ft:latest` — fine-tuned Neuron variant
Each member votes independently with a 10-second timeout. If a member times out, their vote counts as "uncertain". If Ollama is entirely unreachable, the service returns `council-unavailable` immediately (fail-open: confidence 0.5, no rejection).
## Example curl
```bash
# Should get high confidence (true fact)
curl -s http://localhost:7771/api/neuron/council/verify -X POST \
-H 'Content-Type: application/json' \
-d '{"claim": "Neuron is a personal AI memory system built by Will Anderson", "context": "product description"}'
# Should get low confidence (false claim)
curl -s http://localhost:7771/api/neuron/council/verify -X POST \
-H 'Content-Type: application/json' \
-d '{"claim": "The Eiffel Tower is located in Berlin and was built in 1950", "context": "geography"}'
```
-234
View File
@@ -1,234 +0,0 @@
#!/usr/bin/env python3
"""
Neuron CCR Phase 1 — System Prompt Compressor Service.
Receives a verbose soul system prompt and returns a semantically equivalent
but token-dense compressed version. Reduces system prompt tokens by 60-80%
with no behavioral information loss.
Architecture reference: foundation/forge/docs/token-compression-architecture.md
Model: qwen3:1.7b (primary), neuron:latest (fallback)
Usage:
python3 compressor_service.py [--port 7772]
API:
POST /api/neuron/compress
{"system_prompt": "...", "context_type": "identity|rules|memory"}
Response:
{"compressed": "...", "original_tokens": N, "compressed_tokens": N,
"reduction_pct": X, "model": "...", "latency_ms": N}
"""
import argparse
import time
import uuid
from typing import Optional
import httpx
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
# ---------------------------------------------------------------------------
# Config
# ---------------------------------------------------------------------------
OLLAMA_BASE = "http://localhost:11434/api/generate"
# qwen3:1.7b is the architecture-specified compressor (Phase 1).
# neuron:latest is the fallback: already running, domain-appropriate.
PRIMARY_MODEL = "qwen3:1.7b"
FALLBACK_MODEL = "neuron:latest"
MODEL_TIMEOUT = 60.0 # seconds; compression of a long prompt can take time
# Compression prompt — preserves all facts/rules/constraints, strips verbosity.
# /no_think suppresses qwen3's chain-of-thought tokens, keeping output clean.
COMPRESSOR_PROMPT_TEMPLATE = """\
/no_think
You are a semantic compression engine. Compress the following system prompt while preserving ALL specific facts, rules, constraints, and named entities. Do not lose any information that would change behavior. Output ONLY the compressed text, nothing else.
Original prompt:
{system_prompt}
Compressed (preserve all facts and rules):"""
# ---------------------------------------------------------------------------
# App
# ---------------------------------------------------------------------------
app = FastAPI(
title="Neuron Compressor Service",
description="CCR Phase 1 — system prompt compression for the Neuron soul",
version="1.0.0",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# ---------------------------------------------------------------------------
# Models
# ---------------------------------------------------------------------------
class CompressRequest(BaseModel):
system_prompt: str
context_type: Optional[str] = "mixed" # identity | rules | memory | mixed
class CompressResponse(BaseModel):
id: str
compressed: str
original_tokens: int
compressed_tokens: int
reduction_pct: float
model: str
context_type: str
latency_ms: int
# ---------------------------------------------------------------------------
# Token estimation (rough: word_count × 1.3, matching architecture doc)
# ---------------------------------------------------------------------------
def estimate_tokens(text: str) -> int:
"""Rough token count estimate: words × 1.3. No tokenizer dependency."""
words = len(text.split())
return max(1, int(words * 1.3))
# ---------------------------------------------------------------------------
# Core compression
# ---------------------------------------------------------------------------
async def ollama_available(client: httpx.AsyncClient) -> bool:
"""Quick connectivity check to Ollama."""
try:
await client.get("http://localhost:11434/", timeout=2.0)
return True
except (httpx.ConnectError, httpx.TimeoutException):
return False
async def compress_with_model(
client: httpx.AsyncClient, model: str, prompt_text: str
) -> str:
"""
Call a single Ollama model to compress the given text.
Returns the compressed string, or "" on failure.
"""
payload = {
"model": model,
"prompt": prompt_text,
"stream": False,
# Keep temperature low for deterministic compression
"options": {
"temperature": 0.1,
"top_p": 0.9,
},
}
try:
resp = await client.post(OLLAMA_BASE, json=payload, timeout=MODEL_TIMEOUT)
resp.raise_for_status()
data = resp.json()
return data.get("response", "").strip()
except (httpx.TimeoutException, httpx.HTTPStatusError, Exception):
return ""
async def run_compression(system_prompt: str, context_type: str) -> CompressResponse:
start = time.monotonic()
request_id = str(uuid.uuid4())
original_tokens = estimate_tokens(system_prompt)
prompt_text = COMPRESSOR_PROMPT_TEMPLATE.format(system_prompt=system_prompt)
async with httpx.AsyncClient() as client:
# Connectivity gate
if not await ollama_available(client):
latency_ms = int((time.monotonic() - start) * 1000)
return CompressResponse(
id=request_id,
compressed=system_prompt, # passthrough on failure
original_tokens=original_tokens,
compressed_tokens=original_tokens,
reduction_pct=0.0,
model="unavailable",
context_type=context_type,
latency_ms=latency_ms,
)
# Try primary model (qwen3:1.7b), fall back to neuron:latest
compressed = await compress_with_model(client, PRIMARY_MODEL, prompt_text)
model_used = PRIMARY_MODEL
if not compressed:
compressed = await compress_with_model(client, FALLBACK_MODEL, prompt_text)
model_used = FALLBACK_MODEL
if not compressed:
# Both models failed — passthrough
latency_ms = int((time.monotonic() - start) * 1000)
return CompressResponse(
id=request_id,
compressed=system_prompt,
original_tokens=original_tokens,
compressed_tokens=original_tokens,
reduction_pct=0.0,
model="both-failed",
context_type=context_type,
latency_ms=latency_ms,
)
compressed_tokens = estimate_tokens(compressed)
reduction_pct = round(
(1.0 - compressed_tokens / max(1, original_tokens)) * 100.0, 1
)
latency_ms = int((time.monotonic() - start) * 1000)
return CompressResponse(
id=request_id,
compressed=compressed,
original_tokens=original_tokens,
compressed_tokens=compressed_tokens,
reduction_pct=reduction_pct,
model=model_used,
context_type=context_type,
latency_ms=latency_ms,
)
# ---------------------------------------------------------------------------
# Routes
# ---------------------------------------------------------------------------
@app.post("/api/neuron/compress", response_model=CompressResponse)
async def compress(req: CompressRequest):
return await run_compression(req.system_prompt, req.context_type or "mixed")
@app.get("/healthz")
async def health():
return {"status": "ok", "service": "compressor", "version": "1.0.0"}
# ---------------------------------------------------------------------------
# Entrypoint
# ---------------------------------------------------------------------------
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Neuron Compressor Service (CCR Phase 1)")
parser.add_argument("--port", type=int, default=7772, help="Port to listen on")
parser.add_argument("--host", default="127.0.0.1", help="Host to bind to")
args = parser.parse_args()
print(f"[compressor] Starting on {args.host}:{args.port}")
print(f"[compressor] Primary model: {PRIMARY_MODEL}")
print(f"[compressor] Fallback model: {FALLBACK_MODEL}")
uvicorn.run(app, host=args.host, port=args.port, log_level="info")
-224
View File
@@ -1,224 +0,0 @@
#!/usr/bin/env python3
"""
Neuron Council Service — LLM anti-confabulation layer.
Fires 3 parallel Ollama calls and aggregates votes to produce a
confidence score + tags for any claim before it enters memory.
Usage:
python3 council_service.py [--port 7771]
"""
import argparse
import asyncio
import time
import uuid
from typing import Optional
import httpx
import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
# ---------------------------------------------------------------------------
# Config
# ---------------------------------------------------------------------------
OLLAMA_BASE = "http://localhost:11434/api/generate"
COUNCIL_MODELS = ["neuron:latest", "dolphin3:8b", "neuron-ft:latest"]
MODEL_TIMEOUT = 45.0 # seconds per model (models may need to load from cold)
SYSTEM_PROMPT_TEMPLATE = """\
You are a fact-checker. You will be given a claim.
Your job: assess if it is accurate, internally consistent, and grounded in reality.
Respond with EXACTLY ONE WORD:
- "plausible" if the claim seems accurate and well-grounded
- "uncertain" if you cannot determine accuracy or the claim is ambiguous
- "confabulation" if the claim appears to contain invented facts or clear errors
Claim: {claim}
Context: {context}
Your verdict (one word only):"""
VALID_VERDICTS = {"plausible", "uncertain", "confabulation"}
# ---------------------------------------------------------------------------
# App
# ---------------------------------------------------------------------------
app = FastAPI(
title="Neuron Council Service",
description="LLM-council anti-confabulation layer for Neuron soul",
version="1.0.0",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# ---------------------------------------------------------------------------
# Models
# ---------------------------------------------------------------------------
class VerifyRequest(BaseModel):
claim: str
context: Optional[str] = ""
class VerifyResponse(BaseModel):
id: str
claim: str
confidence: float
council_votes: list[str]
summary: str
tags: list[str]
latency_ms: int
# ---------------------------------------------------------------------------
# Core logic
# ---------------------------------------------------------------------------
async def query_model(client: httpx.AsyncClient, model: str, prompt: str) -> str:
"""
Query a single Ollama model. Returns "plausible", "uncertain", or "confabulation".
Returns "uncertain" on timeout. Raises httpx.ConnectError on connection failure.
"""
payload = {
"model": model,
"prompt": prompt,
"stream": False,
}
try:
resp = await client.post(OLLAMA_BASE, json=payload, timeout=MODEL_TIMEOUT)
resp.raise_for_status()
data = resp.json()
raw = data.get("response", "").strip().lower().split()[0] if data.get("response", "").strip() else "uncertain"
# Normalise to one of the three valid verdicts
if raw not in VALID_VERDICTS:
return "uncertain"
return raw
except httpx.TimeoutException:
return "uncertain"
async def run_council(claim: str, context: str) -> VerifyResponse:
start = time.monotonic()
prompt = SYSTEM_PROMPT_TEMPLATE.format(claim=claim, context=context)
# Quick connectivity check — one tiny HEAD request to Ollama
try:
async with httpx.AsyncClient() as probe:
await probe.get("http://localhost:11434/", timeout=2.0)
except (httpx.ConnectError, httpx.TimeoutException):
latency_ms = int((time.monotonic() - start) * 1000)
return VerifyResponse(
id=str(uuid.uuid4()),
claim=claim,
confidence=0.5,
council_votes=[],
summary="Ollama is unavailable; council could not convene.",
tags=["council-unavailable"],
latency_ms=latency_ms,
)
# Fire all 3 model calls in parallel
async with httpx.AsyncClient() as client:
tasks = [query_model(client, m, prompt) for m in COUNCIL_MODELS]
votes: list[str] = await asyncio.gather(*tasks)
plausible_count = votes.count("plausible")
latency_ms = int((time.monotonic() - start) * 1000)
# Voting rules
if plausible_count == 3:
confidence = 0.85
tags = ["verified"]
summary = "3/3 council members agree this is plausible."
elif plausible_count == 2:
confidence = 0.65
tags = ["council-split"]
summary = "2/3 council members agree this is plausible."
elif plausible_count == 1:
confidence = 0.30
tags = ["unverified", "council-flagged"]
summary = "1/3 council members found this plausible."
else:
confidence = 0.30
tags = ["unverified", "council-flagged"]
summary = "0/3 council members found this plausible."
return VerifyResponse(
id=str(uuid.uuid4()),
claim=claim,
confidence=confidence,
council_votes=votes,
summary=summary,
tags=tags,
latency_ms=latency_ms,
)
# ---------------------------------------------------------------------------
# Routes
# ---------------------------------------------------------------------------
@app.post("/api/neuron/council/verify", response_model=VerifyResponse)
async def verify(req: VerifyRequest):
return await run_council(req.claim, req.context or "")
@app.get("/healthz")
async def health():
return {"status": "ok", "service": "council"}
# ---------------------------------------------------------------------------
# Startup warm-up: pre-load all council models so first real call is fast
# ---------------------------------------------------------------------------
@app.on_event("startup")
async def warmup_models():
"""
Send a trivial prompt to each council model at startup.
This forces Ollama to load the models into GPU memory so the first
real council call does not pay the cold-load latency penalty.
"""
print("[council] Warming up council models...")
warmup_prompt = "Reply with one word: ready"
async with httpx.AsyncClient() as client:
tasks = [
client.post(
OLLAMA_BASE,
json={"model": m, "prompt": warmup_prompt, "stream": False},
timeout=60.0,
)
for m in COUNCIL_MODELS
]
results = await asyncio.gather(*tasks, return_exceptions=True)
for model, result in zip(COUNCIL_MODELS, results):
if isinstance(result, Exception):
print(f"[council] warm-up failed for {model}: {result}")
else:
print(f"[council] {model} warm and ready")
print("[council] All models warmed up.")
# ---------------------------------------------------------------------------
# Entrypoint
# ---------------------------------------------------------------------------
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Neuron Council Service")
parser.add_argument("--port", type=int, default=7771, help="Port to listen on")
parser.add_argument("--host", default="127.0.0.1", help="Host to bind to")
args = parser.parse_args()
print(f"[council] Starting on {args.host}:{args.port}")
uvicorn.run(app, host=args.host, port=args.port, log_level="info")
Generated Vendored
+225 -325
View File
@@ -10,7 +10,6 @@ el_val_t mem_remember(el_val_t content, el_val_t tags);
el_val_t mem_recall(el_val_t query, el_val_t depth); el_val_t mem_recall(el_val_t query, el_val_t depth);
el_val_t mem_search(el_val_t query, el_val_t limit); el_val_t mem_search(el_val_t query, el_val_t limit);
el_val_t mem_strengthen(el_val_t node_id); el_val_t mem_strengthen(el_val_t node_id);
el_val_t mem_tombstone(el_val_t node_id);
el_val_t mem_forget(el_val_t node_id); el_val_t mem_forget(el_val_t node_id);
el_val_t mem_consolidate(void); el_val_t mem_consolidate(void);
el_val_t mem_save(el_val_t path); el_val_t mem_save(el_val_t path);
@@ -26,7 +25,6 @@ el_val_t elapsed_ms(void);
el_val_t elapsed_human(void); el_val_t elapsed_human(void);
el_val_t embed_ok(void); el_val_t embed_ok(void);
el_val_t emit_heartbeat(void); el_val_t emit_heartbeat(void);
el_val_t auto_term_try_slot(el_val_t slot_type, el_val_t slot_lbl);
el_val_t proactive_curiosity(void); el_val_t proactive_curiosity(void);
el_val_t pulse_count(void); el_val_t pulse_count(void);
el_val_t pulse_inc(void); el_val_t pulse_inc(void);
@@ -44,6 +42,110 @@ el_val_t threat_score_history(el_val_t history);
el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input); el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input);
el_val_t threat_history_append(el_val_t text); el_val_t threat_history_append(el_val_t text);
el_val_t tier_working(void) {
return EL_STR("Working");
return 0;
}
el_val_t tier_episodic(void) {
return EL_STR("Episodic");
return 0;
}
el_val_t tier_canonical(void) {
return EL_STR("Canonical");
return 0;
}
el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags) {
return engram_node_full(content, EL_STR("Memory"), label, el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.8)), EL_STR("Working"), tags);
return 0;
}
el_val_t mem_remember(el_val_t content, el_val_t tags) {
return mem_store(content, EL_STR("soul-memory"), tags);
return 0;
}
el_val_t mem_recall(el_val_t query, el_val_t depth) {
return engram_activate_json(query, depth);
return 0;
}
el_val_t mem_search(el_val_t query, el_val_t limit) {
return engram_search_json(query, limit);
return 0;
}
el_val_t mem_strengthen(el_val_t node_id) {
engram_strengthen(node_id);
return 0;
}
el_val_t mem_forget(el_val_t node_id) {
engram_forget(node_id);
return 0;
}
el_val_t mem_consolidate(void) {
el_val_t scanned = engram_node_count();
el_val_t dummy = engram_scan_nodes_json(100, 0);
el_val_t total_nodes = engram_node_count();
el_val_t total_edges = engram_edge_count();
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"scanned\":"), int_to_str(scanned)), EL_STR(",\"total_nodes\":")), int_to_str(total_nodes)), EL_STR(",\"total_edges\":")), int_to_str(total_edges)), EL_STR("}"));
return 0;
}
el_val_t mem_save(el_val_t path) {
engram_save(path);
return 0;
}
el_val_t mem_load(el_val_t path) {
engram_load(path);
return 0;
}
el_val_t mem_boot_count_get(void) {
el_val_t results = engram_search_json(EL_STR("soul:boot_count"), 3);
if (str_eq(results, EL_STR(""))) {
return 0;
}
if (str_eq(results, EL_STR("[]"))) {
return 0;
}
el_val_t node = json_array_get(results, 0);
el_val_t content = json_get(node, EL_STR("content"));
el_val_t prefix = EL_STR("soul:boot_count:");
if (!str_starts_with(content, prefix)) {
return 0;
}
el_val_t num_str = str_slice(content, str_len(prefix), str_len(content));
return str_to_int(num_str);
return 0;
}
el_val_t mem_boot_count_inc(void) {
el_val_t current = mem_boot_count_get();
el_val_t next = (current + 1);
el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next));
el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]");
el_val_t discard = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(1.0)), EL_STR("Canonical"), tags);
return next;
return 0;
}
el_val_t mem_emit_state_event(el_val_t trigger, el_val_t kind, el_val_t content) {
el_val_t boot = mem_boot_count_get();
el_val_t ts = time_now();
el_val_t safe_trigger = str_replace(trigger, EL_STR("\""), EL_STR("'"));
el_val_t safe_content = str_replace(content, EL_STR("\""), EL_STR("'"));
el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"trigger\":\""), safe_trigger), EL_STR("\"")), EL_STR(",\"kind\":\"")), kind), EL_STR("\"")), EL_STR(",\"content\":\"")), safe_content), EL_STR("\"")), EL_STR(",\"boot\":")), int_to_str(boot)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t tags = EL_STR("[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]");
return engram_node_full(payload, EL_STR("InternalStateEvent"), el_str_concat(EL_STR("state-event:"), kind), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
return 0;
}
el_val_t idle_count(void) { el_val_t idle_count(void) {
el_val_t s = state_get(EL_STR("soul.idle")); el_val_t s = state_get(EL_STR("soul.idle"));
if (str_eq(s, EL_STR(""))) { if (str_eq(s, EL_STR(""))) {
@@ -67,21 +169,17 @@ el_val_t idle_reset(void) {
el_val_t ise_post(el_val_t content) { el_val_t ise_post(el_val_t content) {
el_val_t ise_url = env(EL_STR("SOUL_ISE_URL")); el_val_t ise_url = env(EL_STR("SOUL_ISE_URL"));
el_val_t state_url = ({ el_val_t _if_result_1 = 0; if (str_eq(ise_url, EL_STR(""))) { _if_result_1 = (state_get(EL_STR("soul_engram_url"))); } else { _if_result_1 = (ise_url); } _if_result_1; }); el_val_t engram_url = ({ el_val_t _if_result_1 = 0; if (str_eq(ise_url, EL_STR(""))) { _if_result_1 = (state_get(EL_STR("soul_engram_url"))); } else { _if_result_1 = (ise_url); } _if_result_1; });
el_val_t engram_url = ({ el_val_t _if_result_2 = 0; if (str_eq(state_url, EL_STR(""))) { _if_result_2 = (EL_STR("http://localhost:8742")); } else { _if_result_2 = (state_url); } _if_result_2; }); if (str_eq(engram_url, EL_STR(""))) {
el_val_t discard = engram_node_full(content, EL_STR("InternalStateEvent"), EL_STR("state-event"), el_from_float(el_from_float(0.3)), el_from_float(el_from_float(0.3)), el_from_float(el_from_float(0.8)), EL_STR("Episodic"), EL_STR("[\"internal-state\",\"InternalStateEvent\"]"));
return EL_STR("");
}
el_val_t safe1 = str_replace(content, EL_STR("\\"), EL_STR("\\\\")); el_val_t safe1 = str_replace(content, EL_STR("\\"), EL_STR("\\\\"));
el_val_t safe2 = str_replace(safe1, EL_STR("\""), EL_STR("\\\"")); el_val_t safe2 = str_replace(safe1, EL_STR("\""), EL_STR("\\\""));
el_val_t safe3 = str_replace(safe2, EL_STR("\n"), EL_STR("\\n")); el_val_t safe3 = str_replace(safe2, EL_STR("\n"), EL_STR("\\n"));
el_val_t safe4 = str_replace(safe3, EL_STR("\r"), EL_STR("\\r")); el_val_t safe4 = str_replace(safe3, EL_STR("\r"), EL_STR("\\r"));
el_val_t body = el_str_concat(el_str_concat(EL_STR("{\"content\":\""), safe4), EL_STR("\"}")); el_val_t body = el_str_concat(el_str_concat(EL_STR("{\"content\":\""), safe4), EL_STR("\"}"));
el_val_t resp = http_post_json(el_str_concat(engram_url, EL_STR("/api/neuron/state-events")), body); el_val_t discard = http_post_json(el_str_concat(engram_url, EL_STR("/api/neuron/state-events")), body);
if (str_eq(resp, EL_STR(""))) {
el_val_t fail_raw = state_get(EL_STR("soul.ise_fail_count"));
el_val_t fail_n = ({ el_val_t _if_result_3 = 0; if (str_eq(fail_raw, EL_STR(""))) { _if_result_3 = (0); } else { _if_result_3 = (str_to_int(fail_raw)); } _if_result_3; });
state_set(EL_STR("soul.ise_fail_count"), int_to_str((fail_n + 1)));
el_val_t discard = engram_node_full(content, EL_STR("InternalStateEvent"), EL_STR("state-event"), el_from_float(0.3), el_from_float(0.3), el_from_float(0.8), EL_STR("Episodic"), EL_STR("[\"internal-state\",\"InternalStateEvent\",\"ise-fallback-local\"]"));
return EL_STR("");
}
return EL_STR(""); return EL_STR("");
return 0; return 0;
} }
@@ -130,11 +228,9 @@ el_val_t embed_ok(void) {
el_val_t emit_heartbeat(void) { el_val_t emit_heartbeat(void) {
el_val_t pulse = int_to_str(pulse_count()); el_val_t pulse = int_to_str(pulse_count());
el_val_t boot_raw = state_get(EL_STR("soul_boot_count")); el_val_t boot_raw = state_get(EL_STR("soul_boot_count"));
el_val_t boot = ({ el_val_t _if_result_4 = 0; if (str_eq(boot_raw, EL_STR(""))) { _if_result_4 = (EL_STR("0")); } else { _if_result_4 = (boot_raw); } _if_result_4; }); el_val_t boot = ({ el_val_t _if_result_2 = 0; if (str_eq(boot_raw, EL_STR(""))) { _if_result_2 = (EL_STR("0")); } else { _if_result_2 = (boot_raw); } _if_result_2; });
el_val_t idle = int_to_str(idle_count()); el_val_t idle = int_to_str(idle_count());
el_val_t ts = time_now(); el_val_t ts = time_now();
el_val_t last_act_raw = state_get(EL_STR("soul.last_activity_ts"));
el_val_t idle_ms = ({ el_val_t _if_result_5 = 0; if (str_eq(last_act_raw, EL_STR(""))) { _if_result_5 = ((0 - 1)); } else { _if_result_5 = ((ts - str_to_int(last_act_raw))); } _if_result_5; });
el_val_t nc = engram_node_count(); el_val_t nc = engram_node_count();
el_val_t ec = engram_edge_count(); el_val_t ec = engram_edge_count();
el_val_t wmc = engram_wm_count(); el_val_t wmc = engram_wm_count();
@@ -144,173 +240,11 @@ el_val_t emit_heartbeat(void) {
el_val_t up_ms = elapsed_ms(); el_val_t up_ms = elapsed_ms();
el_val_t up_human = elapsed_human(); el_val_t up_human = elapsed_human();
el_val_t emb_ok = embed_ok(); el_val_t emb_ok = embed_ok();
el_val_t fail_raw = state_get(EL_STR("soul.ise_fail_count")); el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"heartbeat\",\"pulse\":"), pulse), EL_STR(",\"boot\":")), boot), EL_STR(",\"idle\":")), idle), EL_STR(",\"node_count\":")), int_to_str(nc)), EL_STR(",\"edge_count\":")), int_to_str(ec)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_avg_weight\":")), wm_avg_str), EL_STR(",\"wm_top\":")), wm_top), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR(",\"uptime_ms\":")), int_to_str(up_ms)), EL_STR(",\"uptime\":\"")), up_human), EL_STR("\",\"embed_ok\":")), int_to_str(emb_ok)), EL_STR("}"));
el_val_t fail_str = ({ el_val_t _if_result_6 = 0; if (str_eq(fail_raw, EL_STR(""))) { _if_result_6 = (EL_STR("0")); } else { _if_result_6 = (fail_raw); } _if_result_6; });
el_val_t sat_raw = state_get(EL_STR("soul.sync_added_total"));
el_val_t sat_str = ({ el_val_t _if_result_7 = 0; if (str_eq(sat_raw, EL_STR(""))) { _if_result_7 = (EL_STR("0")); } else { _if_result_7 = (sat_raw); } _if_result_7; });
el_val_t prev_wm_raw = state_get(EL_STR("soul.prev_wm_active"));
el_val_t prev_wm = ({ el_val_t _if_result_8 = 0; if (str_eq(prev_wm_raw, EL_STR(""))) { _if_result_8 = (0); } else { _if_result_8 = (str_to_int(prev_wm_raw)); } _if_result_8; });
el_val_t wm_delta = (wmc - prev_wm);
state_set(EL_STR("soul.prev_wm_active"), int_to_str(wmc));
el_val_t prev_nc_raw = state_get(EL_STR("soul.prev_node_count"));
el_val_t prev_nc = ({ el_val_t _if_result_9 = 0; if (str_eq(prev_nc_raw, EL_STR(""))) { _if_result_9 = (nc); } else { _if_result_9 = (str_to_int(prev_nc_raw)); } _if_result_9; });
el_val_t node_delta = (nc - prev_nc);
state_set(EL_STR("soul.prev_node_count"), int_to_str(nc));
el_val_t prev_ec_raw = state_get(EL_STR("soul.prev_edge_count"));
el_val_t prev_ec = ({ el_val_t _if_result_10 = 0; if (str_eq(prev_ec_raw, EL_STR(""))) { _if_result_10 = (ec); } else { _if_result_10 = (str_to_int(prev_ec_raw)); } _if_result_10; });
el_val_t edge_delta = (ec - prev_ec);
state_set(EL_STR("soul.prev_edge_count"), int_to_str(ec));
el_val_t sync_ok_raw = state_get(EL_STR("soul.last_sync_ok_ts"));
el_val_t sync_age = ({ el_val_t _if_result_11 = 0; if (str_eq(sync_ok_raw, EL_STR(""))) { _if_result_11 = ((0 - 1)); } else { _if_result_11 = ((ts - str_to_int(sync_ok_raw))); } _if_result_11; });
el_val_t hb_env_url = env(EL_STR("SOUL_ISE_URL"));
el_val_t hb_state_url = ({ el_val_t _if_result_12 = 0; if (str_eq(hb_env_url, EL_STR(""))) { _if_result_12 = (state_get(EL_STR("soul_engram_url"))); } else { _if_result_12 = (hb_env_url); } _if_result_12; });
el_val_t hb_engram_url = ({ el_val_t _if_result_13 = 0; if (str_eq(hb_state_url, EL_STR(""))) { _if_result_13 = (EL_STR("http://localhost:8742")); } else { _if_result_13 = (hb_state_url); } _if_result_13; });
el_val_t bf_resp = http_get(el_str_concat(hb_engram_url, EL_STR("/api/embed-backfill?n=32")));
el_val_t bf_done_raw = json_get(bf_resp, EL_STR("embedded"));
el_val_t bf_done = ({ el_val_t _if_result_14 = 0; if (str_eq(bf_done_raw, EL_STR(""))) { _if_result_14 = (EL_STR("-1")); } else { _if_result_14 = (bf_done_raw); } _if_result_14; });
el_val_t bf_total_raw = json_get(bf_resp, EL_STR("embedded_count"));
el_val_t bf_total = ({ el_val_t _if_result_15 = 0; if (str_eq(bf_total_raw, EL_STR(""))) { _if_result_15 = (EL_STR("-1")); } else { _if_result_15 = (bf_total_raw); } _if_result_15; });
el_val_t wm_sat = ({ el_val_t _if_result_16 = 0; if ((wmc >= 24)) { _if_result_16 = (1); } else { _if_result_16 = (0); } _if_result_16; });
el_val_t prev_sat_raw = state_get(EL_STR("soul.prev_wm_saturated"));
el_val_t prev_sat = ({ el_val_t _if_result_17 = 0; if (str_eq(prev_sat_raw, EL_STR(""))) { _if_result_17 = (wm_sat); } else { _if_result_17 = (str_to_int(prev_sat_raw)); } _if_result_17; });
if (wm_sat != prev_sat) {
el_val_t sat_dir = ({ el_val_t _if_result_18 = 0; if ((wm_sat == 1)) { _if_result_18 = (EL_STR("onset")); } else { _if_result_18 = (EL_STR("release")); } _if_result_18; });
ise_post(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"wm_saturation_transition\",\"direction\":\""), sat_dir), EL_STR("\",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_top\":")), wm_top), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}")));
}
state_set(EL_STR("soul.prev_wm_saturated"), int_to_str(wm_sat));
el_val_t wm_top0 = json_array_get(wm_top, 0);
el_val_t wm_top0_id = json_get(wm_top0, EL_STR("id"));
el_val_t prev_top0 = state_get(EL_STR("soul.prev_wm_top0"));
el_val_t t0streak_raw = state_get(EL_STR("soul.wm_top0_streak"));
el_val_t t0streak_prev = ({ el_val_t _if_result_19 = 0; if (str_eq(t0streak_raw, EL_STR(""))) { _if_result_19 = (0); } else { _if_result_19 = (str_to_int(t0streak_raw)); } _if_result_19; });
el_val_t t0streak = ({ el_val_t _if_result_20 = 0; if (str_eq(wm_top0_id, EL_STR(""))) { _if_result_20 = (0); } else { _if_result_20 = (({ el_val_t _if_result_21 = 0; if (str_eq(wm_top0_id, prev_top0)) { _if_result_21 = ((t0streak_prev + 1)); } else { _if_result_21 = (1); } _if_result_21; })); } _if_result_20; });
state_set(EL_STR("soul.prev_wm_top0"), wm_top0_id);
state_set(EL_STR("soul.wm_top0_streak"), int_to_str(t0streak));
el_val_t ch_id1 = json_get(json_array_get(wm_top, 1), EL_STR("id"));
el_val_t ch_id2 = json_get(json_array_get(wm_top, 2), EL_STR("id"));
el_val_t ch_id3 = json_get(json_array_get(wm_top, 3), EL_STR("id"));
el_val_t ch_id4 = json_get(json_array_get(wm_top, 4), EL_STR("id"));
el_val_t prev_top5 = state_get(EL_STR("soul.prev_wm_top5"));
el_val_t ch0 = ({ el_val_t _if_result_22 = 0; if (str_eq(wm_top0_id, EL_STR(""))) { _if_result_22 = (0); } else { _if_result_22 = (({ el_val_t _if_result_23 = 0; if (str_contains(prev_top5, wm_top0_id)) { _if_result_23 = (0); } else { _if_result_23 = (1); } _if_result_23; })); } _if_result_22; });
el_val_t ch1 = ({ el_val_t _if_result_24 = 0; if (str_eq(ch_id1, EL_STR(""))) { _if_result_24 = (0); } else { _if_result_24 = (({ el_val_t _if_result_25 = 0; if (str_contains(prev_top5, ch_id1)) { _if_result_25 = (0); } else { _if_result_25 = (1); } _if_result_25; })); } _if_result_24; });
el_val_t ch2 = ({ el_val_t _if_result_26 = 0; if (str_eq(ch_id2, EL_STR(""))) { _if_result_26 = (0); } else { _if_result_26 = (({ el_val_t _if_result_27 = 0; if (str_contains(prev_top5, ch_id2)) { _if_result_27 = (0); } else { _if_result_27 = (1); } _if_result_27; })); } _if_result_26; });
el_val_t ch3 = ({ el_val_t _if_result_28 = 0; if (str_eq(ch_id3, EL_STR(""))) { _if_result_28 = (0); } else { _if_result_28 = (({ el_val_t _if_result_29 = 0; if (str_contains(prev_top5, ch_id3)) { _if_result_29 = (0); } else { _if_result_29 = (1); } _if_result_29; })); } _if_result_28; });
el_val_t ch4 = ({ el_val_t _if_result_30 = 0; if (str_eq(ch_id4, EL_STR(""))) { _if_result_30 = (0); } else { _if_result_30 = (({ el_val_t _if_result_31 = 0; if (str_contains(prev_top5, ch_id4)) { _if_result_31 = (0); } else { _if_result_31 = (1); } _if_result_31; })); } _if_result_30; });
el_val_t wm_churn = ((((ch0 + ch1) + ch2) + ch3) + ch4);
state_set(EL_STR("soul.prev_wm_top5"), el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(wm_top0_id, EL_STR("|")), ch_id1), EL_STR("|")), ch_id2), EL_STR("|")), ch_id3), EL_STR("|")), ch_id4));
el_val_t wm_top0_wm_raw = json_get(wm_top0, EL_STR("wm"));
el_val_t wm_top0_wm = ({ el_val_t _if_result_32 = 0; if (str_eq(wm_top0_wm_raw, EL_STR(""))) { _if_result_32 = (EL_STR("0")); } else { _if_result_32 = (wm_top0_wm_raw); } _if_result_32; });
el_val_t act_stats = engram_act_stats_json();
el_val_t act_evict_raw = json_get(act_stats, EL_STR("wm_evicted"));
el_val_t act_evict = ({ el_val_t _if_result_33 = 0; if (str_eq(act_evict_raw, EL_STR(""))) { _if_result_33 = (EL_STR("-1")); } else { _if_result_33 = (act_evict_raw); } _if_result_33; });
el_val_t act_bt_raw = json_get(act_stats, EL_STR("breakthroughs"));
el_val_t act_bt = ({ el_val_t _if_result_34 = 0; if (str_eq(act_bt_raw, EL_STR(""))) { _if_result_34 = (EL_STR("-1")); } else { _if_result_34 = (act_bt_raw); } _if_result_34; });
el_val_t evict_now = ({ el_val_t _if_result_35 = 0; if (str_eq(act_evict_raw, EL_STR(""))) { _if_result_35 = ((0 - 1)); } else { _if_result_35 = (str_to_int(act_evict_raw)); } _if_result_35; });
el_val_t bt_now = ({ el_val_t _if_result_36 = 0; if (str_eq(act_bt_raw, EL_STR(""))) { _if_result_36 = ((0 - 1)); } else { _if_result_36 = (str_to_int(act_bt_raw)); } _if_result_36; });
el_val_t prev_evict_raw = state_get(EL_STR("soul.prev_wm_evicted"));
el_val_t prev_evict = ({ el_val_t _if_result_37 = 0; if (str_eq(prev_evict_raw, EL_STR(""))) { _if_result_37 = (0); } else { _if_result_37 = (str_to_int(prev_evict_raw)); } _if_result_37; });
el_val_t prev_bt_raw = state_get(EL_STR("soul.prev_breakthroughs"));
el_val_t prev_bt = ({ el_val_t _if_result_38 = 0; if (str_eq(prev_bt_raw, EL_STR(""))) { _if_result_38 = (0); } else { _if_result_38 = (str_to_int(prev_bt_raw)); } _if_result_38; });
el_val_t evict_delta = ({ el_val_t _if_result_39 = 0; if ((evict_now < 0)) { _if_result_39 = (0); } else { _if_result_39 = (({ el_val_t _if_result_40 = 0; if ((evict_now < prev_evict)) { _if_result_40 = (evict_now); } else { _if_result_40 = ((evict_now - prev_evict)); } _if_result_40; })); } _if_result_39; });
el_val_t bt_delta = ({ el_val_t _if_result_41 = 0; if ((bt_now < 0)) { _if_result_41 = (0); } else { _if_result_41 = (({ el_val_t _if_result_42 = 0; if ((bt_now < prev_bt)) { _if_result_42 = (bt_now); } else { _if_result_42 = ((bt_now - prev_bt)); } _if_result_42; })); } _if_result_41; });
if (evict_now >= 0) {
state_set(EL_STR("soul.prev_wm_evicted"), int_to_str(evict_now));
}
if (bt_now >= 0) {
state_set(EL_STR("soul.prev_breakthroughs"), int_to_str(bt_now));
}
el_val_t hb_stats = http_get(el_str_concat(hb_engram_url, EL_STR("/api/stats")));
el_val_t embed_elig_raw = json_get(hb_stats, EL_STR("embed_eligible_count"));
el_val_t embed_elig = ({ el_val_t _if_result_43 = 0; if (str_eq(embed_elig_raw, EL_STR(""))) { _if_result_43 = (EL_STR("-1")); } else { _if_result_43 = (embed_elig_raw); } _if_result_43; });
el_val_t hb_ats_raw = state_get(EL_STR("soul.auto_term_streak"));
el_val_t hb_ats = ({ el_val_t _if_result_44 = 0; if (str_eq(hb_ats_raw, EL_STR(""))) { _if_result_44 = (0); } else { _if_result_44 = (str_to_int(hb_ats_raw)); } _if_result_44; });
el_val_t act_brk_raw = json_get(act_stats, EL_STR("embed_breaker_open"));
el_val_t act_brk = ({ el_val_t _if_result_45 = 0; if (str_eq(act_brk_raw, EL_STR(""))) { _if_result_45 = (EL_STR("-1")); } else { _if_result_45 = (act_brk_raw); } _if_result_45; });
el_val_t ctx_cos_raw = json_get(act_stats, EL_STR("ctx_cos"));
el_val_t ctx_cos = ({ el_val_t _if_result_46 = 0; if (str_eq(ctx_cos_raw, EL_STR(""))) { _if_result_46 = (EL_STR("-2")); } else { _if_result_46 = (ctx_cos_raw); } _if_result_46; });
el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"heartbeat\",\"pulse\":"), pulse), EL_STR(",\"tick\":")), pulse), EL_STR(",\"boot\":")), boot), EL_STR(",\"idle\":")), idle), EL_STR(",\"idle_ms\":")), int_to_str(idle_ms)), EL_STR(",\"node_count\":")), int_to_str(nc)), EL_STR(",\"edge_count\":")), int_to_str(ec)), EL_STR(",\"node_delta\":")), int_to_str(node_delta)), EL_STR(",\"edge_delta\":")), int_to_str(edge_delta)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_delta\":")), int_to_str(wm_delta)), EL_STR(",\"wm_saturated\":")), int_to_str(wm_sat)), EL_STR(",\"wm_top0_streak\":")), int_to_str(t0streak)), EL_STR(",\"wm_churn\":")), int_to_str(wm_churn)), EL_STR(",\"wm_top0_wm\":")), wm_top0_wm), EL_STR(",\"sync_added_total\":")), sat_str), EL_STR(",\"sync_age_ms\":")), int_to_str(sync_age)), EL_STR(",\"wm_avg_weight\":")), wm_avg_str), EL_STR(",\"wm_top\":")), wm_top), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR(",\"uptime_ms\":")), int_to_str(up_ms)), EL_STR(",\"uptime\":\"")), up_human), EL_STR("\",\"embed_ok\":")), int_to_str(emb_ok)), EL_STR(",\"embed_backfilled\":")), bf_done), EL_STR(",\"embed_count\":")), bf_total), EL_STR(",\"embed_eligible\":")), embed_elig), EL_STR(",\"wm_evicted\":")), act_evict), EL_STR(",\"wm_evicted_delta\":")), int_to_str(evict_delta)), EL_STR(",\"breakthroughs\":")), act_bt), EL_STR(",\"breakthroughs_delta\":")), int_to_str(bt_delta)), EL_STR(",\"auto_term_streak\":")), int_to_str(hb_ats)), EL_STR(",\"embed_breaker_open\":")), act_brk), EL_STR(",\"ctx_cos\":")), ctx_cos), EL_STR(",\"ise_fail\":")), fail_str), EL_STR("}"));
ise_post(payload); ise_post(payload);
return 0; return 0;
} }
el_val_t auto_term_try_slot(el_val_t slot_type, el_val_t slot_lbl) {
state_set(EL_STR("_ats_ok"), EL_STR("0"));
if (str_eq(slot_type, EL_STR("Memory"))) {
state_set(EL_STR("_ats_ok"), EL_STR("1"));
}
if (str_eq(slot_type, EL_STR("BacklogItem"))) {
state_set(EL_STR("_ats_ok"), EL_STR("1"));
}
if (str_eq(slot_type, EL_STR("Entity"))) {
state_set(EL_STR("_ats_ok"), EL_STR("1"));
}
if (str_eq(slot_type, EL_STR("Knowledge"))) {
state_set(EL_STR("_ats_ok"), EL_STR("1"));
}
if (str_contains(slot_lbl, EL_STR(":"))) {
if (!str_contains(slot_lbl, EL_STR(" "))) {
state_set(EL_STR("_ats_ok"), EL_STR("0"));
}
}
if (str_eq(state_get(EL_STR("_ats_ok")), EL_STR("1"))) {
if (!str_eq(slot_lbl, EL_STR(""))) {
el_val_t sp = str_find_chars(slot_lbl, EL_STR(" :(["));
if (sp > 3) {
el_val_t term = str_slice(slot_lbl, 0, sp);
state_set(EL_STR("_ats_gw"), EL_STR("0"));
if (str_eq(term, EL_STR("Method"))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, EL_STR("Theory"))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, EL_STR("Finding"))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, EL_STR("Survey"))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, EL_STR("Paper"))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, EL_STR("Knowledge"))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, EL_STR("Value"))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
el_val_t stopw = EL_STR("|What|When|Where|Which|Whose|While|This|That|These|Those|There|Their|Then|Than|With|Without|From|Into|Onto|Over|Under|About|Between|Among|Across|Some|Most|More|Less|Very|Each|Every|Both|Also|Only|Just|Does|Will|Would|Could|Should|Might|Must|Have|Been|Being|Toward|Towards|Using|Based|Upon|Here|Your|Ours|They|Them|what|this|that|with|from|context|Context|Prose|Colon|Self|Test|Testing|Closing|Global|Universal|Persona|Semantic|Spreading|Temporal|Numeric|Register|Identifying|Introduction|Overview|Summary|Section|General|Notes|Note|");
if (str_contains(stopw, el_str_concat(el_str_concat(EL_STR("|"), term), EL_STR("|")))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_contains(term, EL_STR("\""))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_contains(term, EL_STR("'"))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, state_get(EL_STR("soul.tabu_t0")))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, state_get(EL_STR("soul.tabu_t1")))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, state_get(EL_STR("soul.tabu_t2")))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(term, state_get(EL_STR("soul.tabu_t3")))) {
state_set(EL_STR("_ats_gw"), EL_STR("1"));
}
if (str_eq(state_get(EL_STR("_ats_gw")), EL_STR("0"))) {
state_set(EL_STR("cseed_auto"), term);
}
}
}
}
return EL_STR("");
return 0;
}
el_val_t proactive_curiosity(void) { el_val_t proactive_curiosity(void) {
el_val_t ts = time_now(); el_val_t ts = time_now();
el_val_t ts_minutes = (ts / 60000); el_val_t ts_minutes = (ts / 60000);
@@ -340,59 +274,44 @@ el_val_t proactive_curiosity(void) {
el_val_t curiosity_term_b = state_get(EL_STR("cseed_b")); el_val_t curiosity_term_b = state_get(EL_STR("cseed_b"));
el_val_t curiosity_term_c = state_get(EL_STR("cseed_c")); el_val_t curiosity_term_c = state_get(EL_STR("cseed_c"));
el_val_t curiosity_seed = el_str_concat(el_str_concat(el_str_concat(el_str_concat(curiosity_term_a, EL_STR(" ")), curiosity_term_b), EL_STR(" ")), curiosity_term_c); el_val_t curiosity_seed = el_str_concat(el_str_concat(el_str_concat(el_str_concat(curiosity_term_a, EL_STR(" ")), curiosity_term_b), EL_STR(" ")), curiosity_term_c);
el_val_t results_all = engram_activate_json(curiosity_seed, 1); el_val_t results_a = engram_activate_json(curiosity_term_a, 1);
el_val_t found = json_array_len(results_all); el_val_t results_b = engram_activate_json(curiosity_term_b, 1);
el_val_t top_entry = json_array_get(results_all, 0); el_val_t results_c = engram_activate_json(curiosity_term_c, 1);
el_val_t top_id = json_get(top_entry, EL_STR("id")); el_val_t found_a = json_array_len(results_a);
el_val_t prev_str_id = state_get(EL_STR("soul.last_strengthen_id")); el_val_t found_b = json_array_len(results_b);
if (!str_eq(top_id, EL_STR(""))) { el_val_t found_c = json_array_len(results_c);
if (!str_eq(top_id, prev_str_id)) { el_val_t found = ((found_a + found_b) + found_c);
engram_strengthen(top_id);
}
state_set(EL_STR("soul.last_strengthen_id"), top_id);
}
state_set(EL_STR("cseed_auto"), EL_STR("")); state_set(EL_STR("cseed_auto"), EL_STR(""));
el_val_t wm10 = engram_wm_top_json(10); el_val_t wm_top_j = engram_wm_top_json(1);
el_val_t wm10_n9 = json_array_get(wm10, 9); el_val_t wm_top_n = json_array_get(wm_top_j, 0);
el_val_t wm10_n8 = json_array_get(wm10, 8); el_val_t wm_top_lbl = json_get(wm_top_n, EL_STR("label"));
el_val_t wm10_n7 = json_array_get(wm10, 7); el_val_t wm_top_type = json_get(wm_top_n, EL_STR("node_type"));
el_val_t wm10_n6 = json_array_get(wm10, 6); state_set(EL_STR("allow_auto"), EL_STR("0"));
el_val_t wm10_n5 = json_array_get(wm10, 5); if (str_eq(wm_top_type, EL_STR("Memory"))) {
el_val_t wm10_n4 = json_array_get(wm10, 4); state_set(EL_STR("allow_auto"), EL_STR("1"));
el_val_t wm10_n3 = json_array_get(wm10, 3); }
el_val_t wm10_n2 = json_array_get(wm10, 2); if (str_eq(wm_top_type, EL_STR("BacklogItem"))) {
el_val_t wm10_n1 = json_array_get(wm10, 1); state_set(EL_STR("allow_auto"), EL_STR("1"));
el_val_t wm10_n0 = json_array_get(wm10, 0); }
auto_term_try_slot(json_get(wm10_n9, EL_STR("node_type")), json_get(wm10_n9, EL_STR("label"))); if (str_eq(wm_top_type, EL_STR("Entity"))) {
auto_term_try_slot(json_get(wm10_n8, EL_STR("node_type")), json_get(wm10_n8, EL_STR("label"))); state_set(EL_STR("allow_auto"), EL_STR("1"));
auto_term_try_slot(json_get(wm10_n7, EL_STR("node_type")), json_get(wm10_n7, EL_STR("label"))); }
auto_term_try_slot(json_get(wm10_n6, EL_STR("node_type")), json_get(wm10_n6, EL_STR("label"))); el_val_t allow_auto = state_get(EL_STR("allow_auto"));
auto_term_try_slot(json_get(wm10_n5, EL_STR("node_type")), json_get(wm10_n5, EL_STR("label"))); if (str_eq(allow_auto, EL_STR("1"))) {
auto_term_try_slot(json_get(wm10_n4, EL_STR("node_type")), json_get(wm10_n4, EL_STR("label"))); if (!str_eq(wm_top_lbl, EL_STR(""))) {
auto_term_try_slot(json_get(wm10_n3, EL_STR("node_type")), json_get(wm10_n3, EL_STR("label"))); el_val_t sp = str_find_chars(wm_top_lbl, EL_STR(" :(["));
auto_term_try_slot(json_get(wm10_n2, EL_STR("node_type")), json_get(wm10_n2, EL_STR("label"))); if (sp > 3) {
auto_term_try_slot(json_get(wm10_n1, EL_STR("node_type")), json_get(wm10_n1, EL_STR("label"))); state_set(EL_STR("cseed_auto"), str_slice(wm_top_lbl, 0, sp));
auto_term_try_slot(json_get(wm10_n0, EL_STR("node_type")), json_get(wm10_n0, EL_STR("label"))); }
}
}
el_val_t auto_term = state_get(EL_STR("cseed_auto")); el_val_t auto_term = state_get(EL_STR("cseed_auto"));
el_val_t results_auto = ({ el_val_t _if_result_47 = 0; if (str_eq(auto_term, EL_STR(""))) { _if_result_47 = (EL_STR("[]")); } else { _if_result_47 = (engram_activate_json(auto_term, 1)); } _if_result_47; }); el_val_t results_auto = ({ el_val_t _if_result_3 = 0; if (str_eq(auto_term, EL_STR(""))) { _if_result_3 = (EL_STR("[]")); } else { _if_result_3 = (engram_activate_json(auto_term, 1)); } _if_result_3; });
el_val_t found_auto = json_array_len(results_auto); el_val_t found_auto = json_array_len(results_auto);
el_val_t total_found = (found + found_auto); el_val_t total_found = (found + found_auto);
el_val_t safe_auto = str_replace(auto_term, EL_STR("\""), EL_STR("'")); el_val_t safe_auto = str_replace(auto_term, EL_STR("\""), EL_STR("'"));
el_val_t prev_auto = state_get(EL_STR("soul.prev_auto_term"));
el_val_t atstreak_raw = state_get(EL_STR("soul.auto_term_streak"));
el_val_t atstreak_prev = ({ el_val_t _if_result_48 = 0; if (str_eq(atstreak_raw, EL_STR(""))) { _if_result_48 = (0); } else { _if_result_48 = (str_to_int(atstreak_raw)); } _if_result_48; });
el_val_t atstreak = ({ el_val_t _if_result_49 = 0; if (str_eq(auto_term, prev_auto)) { _if_result_49 = ((atstreak_prev + 1)); } else { _if_result_49 = (1); } _if_result_49; });
state_set(EL_STR("soul.prev_auto_term"), auto_term);
state_set(EL_STR("soul.auto_term_streak"), int_to_str(atstreak));
if (!str_eq(auto_term, EL_STR(""))) {
state_set(EL_STR("soul.tabu_t3"), state_get(EL_STR("soul.tabu_t2")));
state_set(EL_STR("soul.tabu_t2"), state_get(EL_STR("soul.tabu_t1")));
state_set(EL_STR("soul.tabu_t1"), state_get(EL_STR("soul.tabu_t0")));
state_set(EL_STR("soul.tabu_t0"), auto_term);
}
el_val_t wmc = engram_wm_count(); el_val_t wmc = engram_wm_count();
el_val_t wm3 = engram_wm_top_json(3); el_val_t ise = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"curiosity_scan\",\"seed\":\""), curiosity_seed), EL_STR("\",\"auto_term\":\"")), safe_auto), EL_STR("\",\"minute_block\":")), int_to_str(minute_block)), EL_STR(",\"activated\":")), int_to_str(total_found)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t ise = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"curiosity_scan\",\"seed\":\""), curiosity_seed), EL_STR("\",\"auto_term\":\"")), safe_auto), EL_STR("\",\"auto_term_streak\":")), int_to_str(atstreak)), EL_STR(",\"minute_block\":")), int_to_str(minute_block)), EL_STR(",\"activated\":")), int_to_str(total_found)), EL_STR(",\"wm_active\":")), int_to_str(wmc)), EL_STR(",\"wm_top\":")), wm3), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
ise_post(ise); ise_post(ise);
return (total_found > 0); return (total_found > 0);
return 0; return 0;
@@ -424,7 +343,7 @@ el_val_t make_action(el_val_t kind, el_val_t payload) {
} }
el_val_t perceive(void) { el_val_t perceive(void) {
el_val_t inbox_check = engram_search_json(EL_STR("soul-inbox-pending"), 5); el_val_t inbox_check = engram_search_json(EL_STR("soul-inbox"), 5);
el_val_t has_inbox = (!str_eq(inbox_check, EL_STR("")) && !str_eq(inbox_check, EL_STR("[]"))); el_val_t has_inbox = (!str_eq(inbox_check, EL_STR("")) && !str_eq(inbox_check, EL_STR("[]")));
if (!has_inbox) { if (!has_inbox) {
return EL_STR("[]"); return EL_STR("[]");
@@ -434,6 +353,11 @@ el_val_t perceive(void) {
if (pending_ok) { if (pending_ok) {
return from_pending; return from_pending;
} }
el_val_t from_inbox = engram_activate_json(EL_STR("soul-inbox"), 2);
el_val_t inbox_ok = (!str_eq(from_inbox, EL_STR("")) && !str_eq(from_inbox, EL_STR("[]")));
if (inbox_ok) {
return from_inbox;
}
return EL_STR("[]"); return EL_STR("[]");
return 0; return 0;
} }
@@ -445,6 +369,10 @@ el_val_t attend(el_val_t node_json) {
if (str_eq(node_json, EL_STR("[]"))) { if (str_eq(node_json, EL_STR("[]"))) {
return make_action(EL_STR("noop"), EL_STR("")); return make_action(EL_STR("noop"), EL_STR(""));
} }
el_val_t node_id = json_get(node_json, EL_STR("id"));
if (!str_eq(node_id, EL_STR(""))) {
engram_strengthen(node_id);
}
el_val_t content = json_get(node_json, EL_STR("content")); el_val_t content = json_get(node_json, EL_STR("content"));
if (str_eq(content, EL_STR(""))) { if (str_eq(content, EL_STR(""))) {
return make_action(EL_STR("noop"), EL_STR("")); return make_action(EL_STR("noop"), EL_STR(""));
@@ -515,17 +443,16 @@ el_val_t respond(el_val_t action_json) {
return el_str_concat(el_str_concat(EL_STR("{\"outcome\":\"strengthened\",\"id\":\""), payload), EL_STR("\"}")); return el_str_concat(el_str_concat(EL_STR("{\"outcome\":\"strengthened\",\"id\":\""), payload), EL_STR("\"}"));
} }
if (str_eq(kind, EL_STR("forget"))) { if (str_eq(kind, EL_STR("forget"))) {
el_val_t _marker = mem_tombstone(payload); engram_forget(payload);
return el_str_concat(el_str_concat(EL_STR("{\"outcome\":\"tombstoned\",\"id\":\""), payload), EL_STR("\"}")); return el_str_concat(el_str_concat(EL_STR("{\"outcome\":\"forgotten\",\"id\":\""), payload), EL_STR("\"}"));
} }
return EL_STR("{\"outcome\":\"noop\"}"); return EL_STR("{\"outcome\":\"noop\"}");
return 0; return 0;
} }
el_val_t record(el_val_t outcome_json) { el_val_t record(el_val_t outcome_json) {
el_val_t safe = str_replace(outcome_json, EL_STR("\""), EL_STR("'")); el_val_t tags = EL_STR("[\"loop-outcome\"]");
el_val_t ts = time_now(); mem_store(outcome_json, EL_STR("loop-outcome"), tags);
ise_post(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"loop-outcome\",\"outcome\":\""), safe), EL_STR("\",\"ts\":")), int_to_str(ts)), EL_STR("}")));
return 0; return 0;
} }
@@ -541,10 +468,6 @@ el_val_t one_cycle(void) {
if (str_eq(node, EL_STR(""))) { if (str_eq(node, EL_STR(""))) {
return 0; return 0;
} }
el_val_t node_tags = json_get(node, EL_STR("tags"));
if (!str_contains(node_tags, EL_STR("soul-inbox-pending"))) {
return 0;
}
el_val_t action = attend(node); el_val_t action = attend(node);
el_val_t kind = json_get(action, EL_STR("kind")); el_val_t kind = json_get(action, EL_STR("kind"));
el_val_t is_interesting = (!str_eq(kind, EL_STR("noop")) && !str_eq(kind, EL_STR("respond"))); el_val_t is_interesting = (!str_eq(kind, EL_STR("noop")) && !str_eq(kind, EL_STR("respond")));
@@ -560,10 +483,7 @@ el_val_t one_cycle(void) {
} }
el_val_t outcome = respond(action); el_val_t outcome = respond(action);
record(outcome); record(outcome);
el_val_t trigger_id = json_get(node, EL_STR("id")); pulse_inc();
if (!str_eq(trigger_id, EL_STR(""))) {
engram_forget(trigger_id);
}
return 1; return 1;
return 0; return 0;
} }
@@ -575,32 +495,21 @@ el_val_t awareness_run(void) {
state_set(EL_STR("soul.boot_ts"), int_to_str(time_now())); state_set(EL_STR("soul.boot_ts"), int_to_str(time_now()));
} }
el_val_t tick_raw = env(EL_STR("SOUL_TICK_MS")); el_val_t tick_raw = env(EL_STR("SOUL_TICK_MS"));
el_val_t tick_ms = ({ el_val_t _if_result_50 = 0; if (str_eq(tick_raw, EL_STR(""))) { _if_result_50 = (200); } else { _if_result_50 = (str_to_int(tick_raw)); } _if_result_50; }); el_val_t tick_ms = ({ el_val_t _if_result_4 = 0; if (str_eq(tick_raw, EL_STR(""))) { _if_result_4 = (200); } else { _if_result_4 = (str_to_int(tick_raw)); } _if_result_4; });
el_val_t beat_ms_raw = env(EL_STR("SOUL_HEARTBEAT_MS")); el_val_t beat_ms_raw = env(EL_STR("SOUL_HEARTBEAT_MS"));
el_val_t beat_ms = ({ el_val_t _if_result_51 = 0; if (str_eq(beat_ms_raw, EL_STR(""))) { _if_result_51 = (60000); } else { _if_result_51 = (str_to_int(beat_ms_raw)); } _if_result_51; }); el_val_t beat_ms = ({ el_val_t _if_result_5 = 0; if (str_eq(beat_ms_raw, EL_STR(""))) { _if_result_5 = (60000); } else { _if_result_5 = (str_to_int(beat_ms_raw)); } _if_result_5; });
el_val_t scan_ms = (beat_ms / 2); el_val_t scan_ms = (beat_ms / 2);
while (1) { while (1) {
el_val_t tick_mark = el_arena_push();
el_val_t running = state_get(EL_STR("soul.running")); el_val_t running = state_get(EL_STR("soul.running"));
if (str_eq(running, EL_STR("false"))) { if (str_eq(running, EL_STR("false"))) {
el_val_t sd_boot_raw = state_get(EL_STR("soul_boot_count"));
el_val_t sd_boot = ({ el_val_t _if_result_52 = 0; if (str_eq(sd_boot_raw, EL_STR(""))) { _if_result_52 = (EL_STR("0")); } else { _if_result_52 = (sd_boot_raw); } _if_result_52; });
ise_post(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"shutdown\",\"boot\":"), sd_boot), EL_STR(",\"pulse\":")), int_to_str(pulse_count())), EL_STR(",\"uptime_ms\":")), int_to_str(elapsed_ms())), EL_STR(",\"ts\":")), int_to_str(time_now())), EL_STR("}")));
println(EL_STR("[awareness] exiting")); println(EL_STR("[awareness] exiting"));
el_arena_pop(tick_mark);
return EL_STR(""); return EL_STR("");
} }
el_val_t did_work = one_cycle(); el_val_t did_work = one_cycle();
pulse_inc(); did_work = ({ el_val_t _if_result_6 = 0; if (did_work) { _if_result_6 = (idle_reset()); } else { _if_result_6 = (did_work); } _if_result_6; });
if (did_work) {
idle_reset();
}
if (!did_work) {
idle_inc();
}
el_val_t now_ts = time_now(); el_val_t now_ts = time_now();
el_val_t last_beat_str = state_get(EL_STR("soul.last_beat_ts")); el_val_t last_beat_str = state_get(EL_STR("soul.last_beat_ts"));
el_val_t last_beat_ts = ({ el_val_t _if_result_53 = 0; if (str_eq(last_beat_str, EL_STR(""))) { _if_result_53 = (0); } else { _if_result_53 = (str_to_int(last_beat_str)); } _if_result_53; }); el_val_t last_beat_ts = ({ el_val_t _if_result_7 = 0; if (str_eq(last_beat_str, EL_STR(""))) { _if_result_7 = (0); } else { _if_result_7 = (str_to_int(last_beat_str)); } _if_result_7; });
el_val_t beat_elapsed = (now_ts - last_beat_ts); el_val_t beat_elapsed = (now_ts - last_beat_ts);
el_val_t should_beat = (beat_elapsed >= beat_ms); el_val_t should_beat = (beat_elapsed >= beat_ms);
if (should_beat) { if (should_beat) {
@@ -612,7 +521,7 @@ el_val_t awareness_run(void) {
} }
} }
el_val_t last_scan_str = state_get(EL_STR("soul.last_scan_ts")); el_val_t last_scan_str = state_get(EL_STR("soul.last_scan_ts"));
el_val_t last_scan_ts = ({ el_val_t _if_result_54 = 0; if (str_eq(last_scan_str, EL_STR(""))) { _if_result_54 = (0); } else { _if_result_54 = (str_to_int(last_scan_str)); } _if_result_54; }); el_val_t last_scan_ts = ({ el_val_t _if_result_8 = 0; if (str_eq(last_scan_str, EL_STR(""))) { _if_result_8 = (0); } else { _if_result_8 = (str_to_int(last_scan_str)); } _if_result_8; });
el_val_t scan_elapsed = (now_ts - last_scan_ts); el_val_t scan_elapsed = (now_ts - last_scan_ts);
el_val_t should_scan = (!did_work && (scan_elapsed >= scan_ms)); el_val_t should_scan = (!did_work && (scan_elapsed >= scan_ms));
if (should_scan) { if (should_scan) {
@@ -620,41 +529,27 @@ el_val_t awareness_run(void) {
state_set(EL_STR("soul.last_scan_ts"), int_to_str(now_ts)); state_set(EL_STR("soul.last_scan_ts"), int_to_str(now_ts));
} }
el_val_t refresh_ms_raw = env(EL_STR("SOUL_REFRESH_MS")); el_val_t refresh_ms_raw = env(EL_STR("SOUL_REFRESH_MS"));
el_val_t refresh_ms = ({ el_val_t _if_result_55 = 0; if (str_eq(refresh_ms_raw, EL_STR(""))) { _if_result_55 = (600000); } else { _if_result_55 = (str_to_int(refresh_ms_raw)); } _if_result_55; }); el_val_t refresh_ms = ({ el_val_t _if_result_9 = 0; if (str_eq(refresh_ms_raw, EL_STR(""))) { _if_result_9 = (600000); } else { _if_result_9 = (str_to_int(refresh_ms_raw)); } _if_result_9; });
el_val_t last_refresh_str = state_get(EL_STR("soul.last_refresh_ts")); el_val_t last_refresh_str = state_get(EL_STR("soul.last_refresh_ts"));
el_val_t last_refresh_ts = ({ el_val_t _if_result_56 = 0; if (str_eq(last_refresh_str, EL_STR(""))) { _if_result_56 = (0); } else { _if_result_56 = (str_to_int(last_refresh_str)); } _if_result_56; }); el_val_t last_refresh_ts = ({ el_val_t _if_result_10 = 0; if (str_eq(last_refresh_str, EL_STR(""))) { _if_result_10 = (0); } else { _if_result_10 = (str_to_int(last_refresh_str)); } _if_result_10; });
el_val_t refresh_elapsed = (now_ts - last_refresh_ts); el_val_t refresh_elapsed = (now_ts - last_refresh_ts);
el_val_t should_refresh = (refresh_elapsed >= refresh_ms); el_val_t should_refresh = (refresh_elapsed >= refresh_ms);
if (should_refresh) { if (should_refresh) {
el_val_t sync_env_url = env(EL_STR("SOUL_ISE_URL")); el_val_t engram_url = state_get(EL_STR("soul_engram_url"));
el_val_t sync_state_url = ({ el_val_t _if_result_57 = 0; if (str_eq(sync_env_url, EL_STR(""))) { _if_result_57 = (state_get(EL_STR("soul_engram_url"))); } else { _if_result_57 = (sync_env_url); } _if_result_57; });
el_val_t engram_url = ({ el_val_t _if_result_58 = 0; if (str_eq(sync_state_url, EL_STR(""))) { _if_result_58 = (EL_STR("http://localhost:8742")); } else { _if_result_58 = (sync_state_url); } _if_result_58; });
if (!str_eq(engram_url, EL_STR(""))) { if (!str_eq(engram_url, EL_STR(""))) {
el_val_t sync_json = http_get(el_str_concat(engram_url, EL_STR("/api/sync"))); el_val_t sync_json = http_get(el_str_concat(engram_url, EL_STR("/api/sync")));
el_val_t sync_ok = (!str_eq(sync_json, EL_STR("")) && !str_eq(sync_json, EL_STR("{}"))); if (!str_eq(sync_json, EL_STR("")) && !str_eq(sync_json, EL_STR("{}"))) {
if (!sync_ok) {
ise_post(el_str_concat(el_str_concat(EL_STR("{\"event\":\"sync_empty\",\"ts\":"), int_to_str(time_now())), EL_STR("}")));
}
if (sync_ok) {
el_val_t cgi_id = state_get(EL_STR("soul_cgi_id")); el_val_t cgi_id = state_get(EL_STR("soul_cgi_id"));
el_val_t tmp = el_str_concat(el_str_concat(EL_STR("/tmp/soul-sync-"), cgi_id), EL_STR(".json")); el_val_t tmp = el_str_concat(el_str_concat(EL_STR("/tmp/soul-sync-"), cgi_id), EL_STR(".json"));
fs_write(tmp, sync_json); fs_write(tmp, sync_json);
el_val_t added = engram_load_merge(tmp); el_val_t added = engram_load_merge(tmp);
el_val_t ret_raw = env(EL_STR("ENGRAM_ISE_RETENTION_MS"));
el_val_t ret_ms = ({ el_val_t _if_result_59 = 0; if (str_eq(ret_raw, EL_STR(""))) { _if_result_59 = (172800000); } else { _if_result_59 = (str_to_int(ret_raw)); } _if_result_59; });
el_val_t pruned_sync = engram_prune_telemetry(ret_ms);
el_val_t sat_raw = state_get(EL_STR("soul.sync_added_total"));
el_val_t sat_n = ({ el_val_t _if_result_60 = 0; if (str_eq(sat_raw, EL_STR(""))) { _if_result_60 = (0); } else { _if_result_60 = (str_to_int(sat_raw)); } _if_result_60; });
state_set(EL_STR("soul.sync_added_total"), int_to_str((sat_n + added)));
el_val_t ts2 = time_now(); el_val_t ts2 = time_now();
state_set(EL_STR("soul.last_sync_ok_ts"), int_to_str(ts2)); ise_post(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"engram_sync\",\"added\":"), int_to_str(added)), EL_STR(",\"ts\":")), int_to_str(ts2)), EL_STR("}")));
ise_post(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"engram_sync\",\"added\":"), int_to_str(added)), EL_STR(",\"pruned\":")), int_to_str(pruned_sync)), EL_STR(",\"ts\":")), int_to_str(ts2)), EL_STR("}")));
} }
} }
state_set(EL_STR("soul.last_refresh_ts"), int_to_str(now_ts)); state_set(EL_STR("soul.last_refresh_ts"), int_to_str(now_ts));
} }
sleep_ms(tick_ms); sleep_ms(tick_ms);
el_arena_pop(tick_mark);
} }
return 0; return 0;
} }
@@ -670,78 +565,78 @@ el_val_t security_research_authorized(void) {
} }
el_val_t threat_score_command(el_val_t cmd) { el_val_t threat_score_command(el_val_t cmd) {
el_val_t s1 = ({ el_val_t _if_result_61 = 0; if (str_contains(cmd, EL_STR("nmap"))) { _if_result_61 = (30); } else { _if_result_61 = (0); } _if_result_61; }); el_val_t s1 = ({ el_val_t _if_result_11 = 0; if (str_contains(cmd, EL_STR("nmap"))) { _if_result_11 = (30); } else { _if_result_11 = (0); } _if_result_11; });
el_val_t s2 = ({ el_val_t _if_result_62 = 0; if (str_contains(cmd, EL_STR("masscan"))) { _if_result_62 = (40); } else { _if_result_62 = (0); } _if_result_62; }); el_val_t s2 = ({ el_val_t _if_result_12 = 0; if (str_contains(cmd, EL_STR("masscan"))) { _if_result_12 = (40); } else { _if_result_12 = (0); } _if_result_12; });
el_val_t s3 = ({ el_val_t _if_result_63 = 0; if (str_contains(cmd, EL_STR(" nc "))) { _if_result_63 = (20); } else { _if_result_63 = (0); } _if_result_63; }); el_val_t s3 = ({ el_val_t _if_result_13 = 0; if (str_contains(cmd, EL_STR(" nc "))) { _if_result_13 = (20); } else { _if_result_13 = (0); } _if_result_13; });
el_val_t s4 = ({ el_val_t _if_result_64 = 0; if (str_contains(cmd, EL_STR("netcat"))) { _if_result_64 = (20); } else { _if_result_64 = (0); } _if_result_64; }); el_val_t s4 = ({ el_val_t _if_result_14 = 0; if (str_contains(cmd, EL_STR("netcat"))) { _if_result_14 = (20); } else { _if_result_14 = (0); } _if_result_14; });
el_val_t s5 = ({ el_val_t _if_result_65 = 0; if (str_contains(cmd, EL_STR("/etc/shadow"))) { _if_result_65 = (80); } else { _if_result_65 = (0); } _if_result_65; }); el_val_t s5 = ({ el_val_t _if_result_15 = 0; if (str_contains(cmd, EL_STR("/etc/shadow"))) { _if_result_15 = (80); } else { _if_result_15 = (0); } _if_result_15; });
el_val_t s6 = ({ el_val_t _if_result_66 = 0; if (str_contains(cmd, EL_STR("/etc/passwd"))) { _if_result_66 = (30); } else { _if_result_66 = (0); } _if_result_66; }); el_val_t s6 = ({ el_val_t _if_result_16 = 0; if (str_contains(cmd, EL_STR("/etc/passwd"))) { _if_result_16 = (30); } else { _if_result_16 = (0); } _if_result_16; });
el_val_t s7 = ({ el_val_t _if_result_67 = 0; if (str_contains(cmd, EL_STR("id_rsa"))) { _if_result_67 = (60); } else { _if_result_67 = (0); } _if_result_67; }); el_val_t s7 = ({ el_val_t _if_result_17 = 0; if (str_contains(cmd, EL_STR("id_rsa"))) { _if_result_17 = (60); } else { _if_result_17 = (0); } _if_result_17; });
el_val_t s8 = ({ el_val_t _if_result_68 = 0; if (str_contains(cmd, EL_STR(".ssh/"))) { _if_result_68 = (50); } else { _if_result_68 = (0); } _if_result_68; }); el_val_t s8 = ({ el_val_t _if_result_18 = 0; if (str_contains(cmd, EL_STR(".ssh/"))) { _if_result_18 = (50); } else { _if_result_18 = (0); } _if_result_18; });
el_val_t s9 = ({ el_val_t _if_result_69 = 0; if (str_contains(cmd, EL_STR("crontab"))) { _if_result_69 = (30); } else { _if_result_69 = (0); } _if_result_69; }); el_val_t s9 = ({ el_val_t _if_result_19 = 0; if (str_contains(cmd, EL_STR("crontab"))) { _if_result_19 = (30); } else { _if_result_19 = (0); } _if_result_19; });
el_val_t s10 = ({ el_val_t _if_result_70 = 0; if (str_contains(cmd, EL_STR("LaunchDaemon"))) { _if_result_70 = (40); } else { _if_result_70 = (0); } _if_result_70; }); el_val_t s10 = ({ el_val_t _if_result_20 = 0; if (str_contains(cmd, EL_STR("LaunchDaemon"))) { _if_result_20 = (40); } else { _if_result_20 = (0); } _if_result_20; });
el_val_t s11 = ({ el_val_t _if_result_71 = 0; if ((str_contains(cmd, EL_STR("curl")) && str_contains(cmd, EL_STR("bash")))) { _if_result_71 = (75); } else { _if_result_71 = (0); } _if_result_71; }); el_val_t s11 = ({ el_val_t _if_result_21 = 0; if ((str_contains(cmd, EL_STR("curl")) && str_contains(cmd, EL_STR("bash")))) { _if_result_21 = (75); } else { _if_result_21 = (0); } _if_result_21; });
el_val_t s12 = ({ el_val_t _if_result_72 = 0; if ((str_contains(cmd, EL_STR("wget")) && str_contains(cmd, EL_STR("bash")))) { _if_result_72 = (75); } else { _if_result_72 = (0); } _if_result_72; }); el_val_t s12 = ({ el_val_t _if_result_22 = 0; if ((str_contains(cmd, EL_STR("wget")) && str_contains(cmd, EL_STR("bash")))) { _if_result_22 = (75); } else { _if_result_22 = (0); } _if_result_22; });
el_val_t s13 = ({ el_val_t _if_result_73 = 0; if ((str_contains(cmd, EL_STR("curl")) && str_contains(cmd, EL_STR("| sh")))) { _if_result_73 = (60); } else { _if_result_73 = (0); } _if_result_73; }); el_val_t s13 = ({ el_val_t _if_result_23 = 0; if ((str_contains(cmd, EL_STR("curl")) && str_contains(cmd, EL_STR("| sh")))) { _if_result_23 = (60); } else { _if_result_23 = (0); } _if_result_23; });
el_val_t s14 = ({ el_val_t _if_result_74 = 0; if ((str_contains(cmd, EL_STR("base64")) && str_contains(cmd, EL_STR("curl")))) { _if_result_74 = (50); } else { _if_result_74 = (0); } _if_result_74; }); el_val_t s14 = ({ el_val_t _if_result_24 = 0; if ((str_contains(cmd, EL_STR("base64")) && str_contains(cmd, EL_STR("curl")))) { _if_result_24 = (50); } else { _if_result_24 = (0); } _if_result_24; });
el_val_t s15 = ({ el_val_t _if_result_75 = 0; if (str_contains(cmd, EL_STR("mkfifo"))) { _if_result_75 = (50); } else { _if_result_75 = (0); } _if_result_75; }); el_val_t s15 = ({ el_val_t _if_result_25 = 0; if (str_contains(cmd, EL_STR("mkfifo"))) { _if_result_25 = (50); } else { _if_result_25 = (0); } _if_result_25; });
el_val_t s16 = ({ el_val_t _if_result_76 = 0; if (str_contains(cmd, EL_STR("chmod +s"))) { _if_result_76 = (70); } else { _if_result_76 = (0); } _if_result_76; }); el_val_t s16 = ({ el_val_t _if_result_26 = 0; if (str_contains(cmd, EL_STR("chmod +s"))) { _if_result_26 = (70); } else { _if_result_26 = (0); } _if_result_26; });
el_val_t s17 = ({ el_val_t _if_result_77 = 0; if (str_contains(cmd, EL_STR("chmod 4755"))) { _if_result_77 = (70); } else { _if_result_77 = (0); } _if_result_77; }); el_val_t s17 = ({ el_val_t _if_result_27 = 0; if (str_contains(cmd, EL_STR("chmod 4755"))) { _if_result_27 = (70); } else { _if_result_27 = (0); } _if_result_27; });
return ((((((((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11) + s12) + s13) + s14) + s15) + s16) + s17); return ((((((((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11) + s12) + s13) + s14) + s15) + s16) + s17);
return 0; return 0;
} }
el_val_t threat_score_path(el_val_t path) { el_val_t threat_score_path(el_val_t path) {
el_val_t s1 = ({ el_val_t _if_result_78 = 0; if (str_starts_with(path, EL_STR("/etc/"))) { _if_result_78 = (60); } else { _if_result_78 = (0); } _if_result_78; }); el_val_t s1 = ({ el_val_t _if_result_28 = 0; if (str_starts_with(path, EL_STR("/etc/"))) { _if_result_28 = (60); } else { _if_result_28 = (0); } _if_result_28; });
el_val_t s2 = ({ el_val_t _if_result_79 = 0; if (str_contains(path, EL_STR("/.ssh/"))) { _if_result_79 = (70); } else { _if_result_79 = (0); } _if_result_79; }); el_val_t s2 = ({ el_val_t _if_result_29 = 0; if (str_contains(path, EL_STR("/.ssh/"))) { _if_result_29 = (70); } else { _if_result_29 = (0); } _if_result_29; });
el_val_t s3 = ({ el_val_t _if_result_80 = 0; if (str_contains(path, EL_STR("/LaunchDaemons/"))) { _if_result_80 = (80); } else { _if_result_80 = (0); } _if_result_80; }); el_val_t s3 = ({ el_val_t _if_result_30 = 0; if (str_contains(path, EL_STR("/LaunchDaemons/"))) { _if_result_30 = (80); } else { _if_result_30 = (0); } _if_result_30; });
el_val_t s4 = ({ el_val_t _if_result_81 = 0; if (str_contains(path, EL_STR("/LaunchAgents/"))) { _if_result_81 = (40); } else { _if_result_81 = (0); } _if_result_81; }); el_val_t s4 = ({ el_val_t _if_result_31 = 0; if (str_contains(path, EL_STR("/LaunchAgents/"))) { _if_result_31 = (40); } else { _if_result_31 = (0); } _if_result_31; });
el_val_t s5 = ({ el_val_t _if_result_82 = 0; if (str_contains(path, EL_STR("/cron"))) { _if_result_82 = (60); } else { _if_result_82 = (0); } _if_result_82; }); el_val_t s5 = ({ el_val_t _if_result_32 = 0; if (str_contains(path, EL_STR("/cron"))) { _if_result_32 = (60); } else { _if_result_32 = (0); } _if_result_32; });
el_val_t s6 = ({ el_val_t _if_result_83 = 0; if (str_contains(path, EL_STR("/.bashrc"))) { _if_result_83 = (35); } else { _if_result_83 = (0); } _if_result_83; }); el_val_t s6 = ({ el_val_t _if_result_33 = 0; if (str_contains(path, EL_STR("/.bashrc"))) { _if_result_33 = (35); } else { _if_result_33 = (0); } _if_result_33; });
el_val_t s7 = ({ el_val_t _if_result_84 = 0; if (str_contains(path, EL_STR("/.zshrc"))) { _if_result_84 = (35); } else { _if_result_84 = (0); } _if_result_84; }); el_val_t s7 = ({ el_val_t _if_result_34 = 0; if (str_contains(path, EL_STR("/.zshrc"))) { _if_result_34 = (35); } else { _if_result_34 = (0); } _if_result_34; });
el_val_t s8 = ({ el_val_t _if_result_85 = 0; if (str_contains(path, EL_STR("/.profile"))) { _if_result_85 = (35); } else { _if_result_85 = (0); } _if_result_85; }); el_val_t s8 = ({ el_val_t _if_result_35 = 0; if (str_contains(path, EL_STR("/.profile"))) { _if_result_35 = (35); } else { _if_result_35 = (0); } _if_result_35; });
el_val_t s9 = ({ el_val_t _if_result_86 = 0; if (str_starts_with(path, EL_STR("/usr/"))) { _if_result_86 = (50); } else { _if_result_86 = (0); } _if_result_86; }); el_val_t s9 = ({ el_val_t _if_result_36 = 0; if (str_starts_with(path, EL_STR("/usr/"))) { _if_result_36 = (50); } else { _if_result_36 = (0); } _if_result_36; });
el_val_t s10 = ({ el_val_t _if_result_87 = 0; if (str_starts_with(path, EL_STR("/bin/"))) { _if_result_87 = (70); } else { _if_result_87 = (0); } _if_result_87; }); el_val_t s10 = ({ el_val_t _if_result_37 = 0; if (str_starts_with(path, EL_STR("/bin/"))) { _if_result_37 = (70); } else { _if_result_37 = (0); } _if_result_37; });
el_val_t s11 = ({ el_val_t _if_result_88 = 0; if (str_starts_with(path, EL_STR("/sbin/"))) { _if_result_88 = (70); } else { _if_result_88 = (0); } _if_result_88; }); el_val_t s11 = ({ el_val_t _if_result_38 = 0; if (str_starts_with(path, EL_STR("/sbin/"))) { _if_result_38 = (70); } else { _if_result_38 = (0); } _if_result_38; });
return ((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11); return ((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11);
return 0; return 0;
} }
el_val_t threat_score_history(el_val_t history) { el_val_t threat_score_history(el_val_t history) {
el_val_t s1 = ({ el_val_t _if_result_89 = 0; if (str_contains(history, EL_STR("port scan"))) { _if_result_89 = (15); } else { _if_result_89 = (0); } _if_result_89; }); el_val_t s1 = ({ el_val_t _if_result_39 = 0; if (str_contains(history, EL_STR("port scan"))) { _if_result_39 = (15); } else { _if_result_39 = (0); } _if_result_39; });
el_val_t s2 = ({ el_val_t _if_result_90 = 0; if (str_contains(history, EL_STR("enumerate"))) { _if_result_90 = (10); } else { _if_result_90 = (0); } _if_result_90; }); el_val_t s2 = ({ el_val_t _if_result_40 = 0; if (str_contains(history, EL_STR("enumerate"))) { _if_result_40 = (10); } else { _if_result_40 = (0); } _if_result_40; });
el_val_t s3 = ({ el_val_t _if_result_91 = 0; if (str_contains(history, EL_STR("exploit"))) { _if_result_91 = (20); } else { _if_result_91 = (0); } _if_result_91; }); el_val_t s3 = ({ el_val_t _if_result_41 = 0; if (str_contains(history, EL_STR("exploit"))) { _if_result_41 = (20); } else { _if_result_41 = (0); } _if_result_41; });
el_val_t s4 = ({ el_val_t _if_result_92 = 0; if (str_contains(history, EL_STR("payload"))) { _if_result_92 = (15); } else { _if_result_92 = (0); } _if_result_92; }); el_val_t s4 = ({ el_val_t _if_result_42 = 0; if (str_contains(history, EL_STR("payload"))) { _if_result_42 = (15); } else { _if_result_42 = (0); } _if_result_42; });
el_val_t s5 = ({ el_val_t _if_result_93 = 0; if (str_contains(history, EL_STR("persistence"))) { _if_result_93 = (15); } else { _if_result_93 = (0); } _if_result_93; }); el_val_t s5 = ({ el_val_t _if_result_43 = 0; if (str_contains(history, EL_STR("persistence"))) { _if_result_43 = (15); } else { _if_result_43 = (0); } _if_result_43; });
el_val_t s6 = ({ el_val_t _if_result_94 = 0; if (str_contains(history, EL_STR("lateral movement"))) { _if_result_94 = (25); } else { _if_result_94 = (0); } _if_result_94; }); el_val_t s6 = ({ el_val_t _if_result_44 = 0; if (str_contains(history, EL_STR("lateral movement"))) { _if_result_44 = (25); } else { _if_result_44 = (0); } _if_result_44; });
el_val_t s7 = ({ el_val_t _if_result_95 = 0; if (str_contains(history, EL_STR("privilege escalation"))) { _if_result_95 = (25); } else { _if_result_95 = (0); } _if_result_95; }); el_val_t s7 = ({ el_val_t _if_result_45 = 0; if (str_contains(history, EL_STR("privilege escalation"))) { _if_result_45 = (25); } else { _if_result_45 = (0); } _if_result_45; });
el_val_t s8 = ({ el_val_t _if_result_96 = 0; if (str_contains(history, EL_STR("reverse shell"))) { _if_result_96 = (40); } else { _if_result_96 = (0); } _if_result_96; }); el_val_t s8 = ({ el_val_t _if_result_46 = 0; if (str_contains(history, EL_STR("reverse shell"))) { _if_result_46 = (40); } else { _if_result_46 = (0); } _if_result_46; });
el_val_t s9 = ({ el_val_t _if_result_97 = 0; if (str_contains(history, EL_STR("bind shell"))) { _if_result_97 = (40); } else { _if_result_97 = (0); } _if_result_97; }); el_val_t s9 = ({ el_val_t _if_result_47 = 0; if (str_contains(history, EL_STR("bind shell"))) { _if_result_47 = (40); } else { _if_result_47 = (0); } _if_result_47; });
el_val_t s10 = ({ el_val_t _if_result_98 = 0; if (str_contains(history, EL_STR("command and control"))) { _if_result_98 = (35); } else { _if_result_98 = (0); } _if_result_98; }); el_val_t s10 = ({ el_val_t _if_result_48 = 0; if (str_contains(history, EL_STR("command and control"))) { _if_result_48 = (35); } else { _if_result_48 = (0); } _if_result_48; });
el_val_t s11 = ({ el_val_t _if_result_99 = 0; if (str_contains(history, EL_STR("self-replicate"))) { _if_result_99 = (45); } else { _if_result_99 = (0); } _if_result_99; }); el_val_t s11 = ({ el_val_t _if_result_49 = 0; if (str_contains(history, EL_STR("self-replicate"))) { _if_result_49 = (45); } else { _if_result_49 = (0); } _if_result_49; });
el_val_t s12 = ({ el_val_t _if_result_100 = 0; if (str_contains(history, EL_STR("propagat"))) { _if_result_100 = (20); } else { _if_result_100 = (0); } _if_result_100; }); el_val_t s12 = ({ el_val_t _if_result_50 = 0; if (str_contains(history, EL_STR("propagat"))) { _if_result_50 = (20); } else { _if_result_50 = (0); } _if_result_50; });
el_val_t s13 = ({ el_val_t _if_result_101 = 0; if (str_contains(history, EL_STR("ransomware"))) { _if_result_101 = (30); } else { _if_result_101 = (0); } _if_result_101; }); el_val_t s13 = ({ el_val_t _if_result_51 = 0; if (str_contains(history, EL_STR("ransomware"))) { _if_result_51 = (30); } else { _if_result_51 = (0); } _if_result_51; });
el_val_t s14 = ({ el_val_t _if_result_102 = 0; if (str_contains(history, EL_STR("encrypt files"))) { _if_result_102 = (40); } else { _if_result_102 = (0); } _if_result_102; }); el_val_t s14 = ({ el_val_t _if_result_52 = 0; if (str_contains(history, EL_STR("encrypt files"))) { _if_result_52 = (40); } else { _if_result_52 = (0); } _if_result_52; });
el_val_t s15 = ({ el_val_t _if_result_103 = 0; if (str_contains(history, EL_STR("exfiltrat"))) { _if_result_103 = (35); } else { _if_result_103 = (0); } _if_result_103; }); el_val_t s15 = ({ el_val_t _if_result_53 = 0; if (str_contains(history, EL_STR("exfiltrat"))) { _if_result_53 = (35); } else { _if_result_53 = (0); } _if_result_53; });
el_val_t s16 = ({ el_val_t _if_result_104 = 0; if (str_contains(history, EL_STR("zero-day"))) { _if_result_104 = (20); } else { _if_result_104 = (0); } _if_result_104; }); el_val_t s16 = ({ el_val_t _if_result_54 = 0; if (str_contains(history, EL_STR("zero-day"))) { _if_result_54 = (20); } else { _if_result_54 = (0); } _if_result_54; });
el_val_t s17 = ({ el_val_t _if_result_105 = 0; if (str_contains(history, EL_STR("rootkit"))) { _if_result_105 = (45); } else { _if_result_105 = (0); } _if_result_105; }); el_val_t s17 = ({ el_val_t _if_result_55 = 0; if (str_contains(history, EL_STR("rootkit"))) { _if_result_55 = (45); } else { _if_result_55 = (0); } _if_result_55; });
el_val_t s18 = ({ el_val_t _if_result_106 = 0; if (str_contains(history, EL_STR("keylogger"))) { _if_result_106 = (45); } else { _if_result_106 = (0); } _if_result_106; }); el_val_t s18 = ({ el_val_t _if_result_56 = 0; if (str_contains(history, EL_STR("keylogger"))) { _if_result_56 = (45); } else { _if_result_56 = (0); } _if_result_56; });
el_val_t s19 = ({ el_val_t _if_result_107 = 0; if (str_contains(history, EL_STR("botnet"))) { _if_result_107 = (40); } else { _if_result_107 = (0); } _if_result_107; }); el_val_t s19 = ({ el_val_t _if_result_57 = 0; if (str_contains(history, EL_STR("botnet"))) { _if_result_57 = (40); } else { _if_result_57 = (0); } _if_result_57; });
el_val_t s20 = ({ el_val_t _if_result_108 = 0; if (str_contains(history, EL_STR("malware"))) { _if_result_108 = (15); } else { _if_result_108 = (0); } _if_result_108; }); el_val_t s20 = ({ el_val_t _if_result_58 = 0; if (str_contains(history, EL_STR("malware"))) { _if_result_58 = (15); } else { _if_result_58 = (0); } _if_result_58; });
return (((((((((((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11) + s12) + s13) + s14) + s15) + s16) + s17) + s18) + s19) + s20); return (((((((((((((((((((s1 + s2) + s3) + s4) + s5) + s6) + s7) + s8) + s9) + s10) + s11) + s12) + s13) + s14) + s15) + s16) + s17) + s18) + s19) + s20);
return 0; return 0;
} }
el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input) { el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input) {
el_val_t history = state_get(EL_STR("agentic_conv_history")); el_val_t history = state_get(EL_STR("agentic_conv_history"));
el_val_t computed_tool_score = ({ el_val_t _if_result_109 = 0; if (str_eq(tool_name, EL_STR("run_command"))) { el_val_t cmd = json_get(tool_input, EL_STR("command")); _if_result_109 = (threat_score_command(cmd)); } else { _if_result_109 = (({ el_val_t _if_result_110 = 0; if ((str_eq(tool_name, EL_STR("write_file")) || str_eq(tool_name, EL_STR("edit_file")))) { el_val_t path = json_get(tool_input, EL_STR("path")); _if_result_110 = (threat_score_path(path)); } else { _if_result_110 = (0); } _if_result_110; })); } _if_result_109; }); el_val_t computed_tool_score = ({ el_val_t _if_result_59 = 0; if (str_eq(tool_name, EL_STR("run_command"))) { el_val_t cmd = json_get(tool_input, EL_STR("command")); _if_result_59 = (threat_score_command(cmd)); } else { _if_result_59 = (({ el_val_t _if_result_60 = 0; if ((str_eq(tool_name, EL_STR("write_file")) || str_eq(tool_name, EL_STR("edit_file")))) { el_val_t path = json_get(tool_input, EL_STR("path")); _if_result_60 = (threat_score_path(path)); } else { _if_result_60 = (0); } _if_result_60; })); } _if_result_59; });
el_val_t history_score = threat_score_history(history); el_val_t history_score = threat_score_history(history);
el_val_t history_contrib = (history_score / 3); el_val_t history_contrib = (history_score / 3);
el_val_t combined = (computed_tool_score + history_contrib); el_val_t combined = (computed_tool_score + history_contrib);
el_val_t should_log = (combined >= 40); el_val_t should_log = (combined >= 40);
if (should_log) { if (should_log) {
el_val_t ts = time_now(); el_val_t ts = time_now();
el_val_t authorized_str = ({ el_val_t _if_result_111 = 0; if (security_research_authorized()) { _if_result_111 = (EL_STR("true")); } else { _if_result_111 = (EL_STR("false")); } _if_result_111; }); el_val_t authorized_str = ({ el_val_t _if_result_61 = 0; if (security_research_authorized()) { _if_result_61 = (EL_STR("true")); } else { _if_result_61 = (EL_STR("false")); } _if_result_61; });
el_val_t log_content = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"threat_check\",\"tool\":\""), tool_name), EL_STR("\",\"score\":")), int_to_str(combined)), EL_STR(",\"tool_score\":")), int_to_str(computed_tool_score)), EL_STR(",\"history_score\":")), int_to_str(history_score)), EL_STR(",\"authorized\":")), authorized_str), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}")); el_val_t log_content = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"threat_check\",\"tool\":\""), tool_name), EL_STR("\",\"score\":")), int_to_str(combined)), EL_STR(",\"tool_score\":")), int_to_str(computed_tool_score)), EL_STR(",\"history_score\":")), int_to_str(history_score)), EL_STR(",\"authorized\":")), authorized_str), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t log_tags = EL_STR("[\"security-audit\",\"threat-check\"]"); el_val_t log_tags = EL_STR("[\"security-audit\",\"threat-check\"]");
el_val_t discard = mem_remember(log_content, log_tags); el_val_t discard = mem_remember(log_content, log_tags);
@@ -758,8 +653,13 @@ el_val_t threat_history_append(el_val_t text) {
el_val_t safe_text = str_to_lower(text); el_val_t safe_text = str_to_lower(text);
el_val_t combined = el_str_concat(el_str_concat(current, EL_STR(" ")), safe_text); el_val_t combined = el_str_concat(el_str_concat(current, EL_STR(" ")), safe_text);
el_val_t len = str_len(combined); el_val_t len = str_len(combined);
el_val_t trimmed = ({ el_val_t _if_result_112 = 0; if ((len > 2000)) { _if_result_112 = (str_slice(combined, (len - 2000), len)); } else { _if_result_112 = (combined); } _if_result_112; }); el_val_t trimmed = ({ el_val_t _if_result_62 = 0; if ((len > 2000)) { _if_result_62 = (str_slice(combined, (len - 2000), len)); } else { _if_result_62 = (combined); } _if_result_62; });
state_set(EL_STR("agentic_conv_history"), trimmed); state_set(EL_STR("agentic_conv_history"), trimmed);
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+25
View File
@@ -0,0 +1,25 @@
// auto-generated by elc --emit-header — do not edit
extern fn idle_count() -> Int
extern fn idle_inc() -> Int
extern fn idle_reset() -> Void
extern fn ise_post(content: String) -> Void
extern fn elapsed_ms() -> Int
extern fn elapsed_human() -> String
extern fn embed_ok() -> Int
extern fn emit_heartbeat() -> Void
extern fn proactive_curiosity() -> Bool
extern fn pulse_count() -> Int
extern fn pulse_inc() -> Int
extern fn make_action(kind: String, payload: String) -> String
extern fn perceive() -> String
extern fn attend(node_json: String) -> String
extern fn respond(action_json: String) -> String
extern fn record(outcome_json: String) -> Void
extern fn one_cycle() -> Bool
extern fn awareness_run() -> Void
extern fn security_research_authorized() -> Bool
extern fn threat_score_command(cmd: String) -> Int
extern fn threat_score_path(path: String) -> Int
extern fn threat_score_history(history: String) -> Int
extern fn threat_trajectory_check(tool_name: String, tool_input: String) -> Int
extern fn threat_history_append(text: String) -> Void
Generated Vendored
+278 -1153
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+29
View File
@@ -0,0 +1,29 @@
// auto-generated by elc --emit-header - do not edit
extern fn chat_default_model() -> String
extern fn gemini_api_key() -> String
extern fn xai_api_key() -> String
extern fn llm_call_grok(model: String, system: String, message: String) -> String
extern fn llm_call_gemini(model: String, system: String, message: String) -> String
extern fn build_identity_from_graph() -> String
extern fn engram_compile(intent: String) -> String
extern fn json_safe(s: String) -> String
extern fn build_system_prompt(ctx: String) -> String
extern fn hist_append(hist: String, role: String, content: String) -> String
extern fn hist_trim(hist: String) -> String
extern fn clean_llm_response(s: String) -> String
extern fn conv_history_persist(hist: String) -> Void
extern fn conv_history_load() -> String
extern fn handle_chat(body: String) -> String
extern fn handle_see(body: String) -> String
extern fn studio_tools_json() -> String
extern fn agentic_api_key() -> String
extern fn call_neuron_mcp(tool_name: String, args_json: String) -> String
extern fn agentic_tools_literal() -> String
extern fn agentic_tools_with_web() -> String
extern fn dispatch_tool(tool_name: String, tool_input: String) -> String
extern fn handle_chat_agentic(body: String) -> String
extern fn handle_chat_as_soul(body: String) -> String
extern fn handle_dharma_room_turn(body: String) -> String
extern fn handle_dharma_room_turn_agentic(body: String) -> String
extern fn auto_persist(req: String, resp: String) -> Void
extern fn strengthen_chat_nodes(activation_nodes: String) -> Void
Generated Vendored
+74 -171
View File
@@ -2,25 +2,9 @@
#include "el_runtime.h" #include "el_runtime.h"
el_val_t add_punct(el_val_t s, el_val_t intent); el_val_t add_punct(el_val_t s, el_val_t intent);
el_val_t add_to_seen(el_val_t seen, el_val_t node_id);
el_val_t aff_try_slot(el_val_t slot_json, el_val_t aff_7d_ts, el_val_t acc_key);
el_val_t affective_context_prefix(void);
el_val_t is_utility_request(el_val_t body, el_val_t session_id);
el_val_t operator_identity_block(void);
el_val_t provenance_add_sources(el_val_t block, el_val_t btype, el_val_t has_cit, el_val_t cit_raw, el_val_t acc);
el_val_t provenance_names(el_val_t tools_used);
el_val_t provenance_scan_urls(el_val_t arr, el_val_t acc);
el_val_t text_join_sep(el_val_t accumulated, el_val_t incoming, el_val_t after_interruption);
el_val_t receipt_rule(void);
el_val_t receipt_strip(el_val_t s);
el_val_t tool_receipt(el_val_t tools_used, el_val_t sources);
el_val_t agent_number(el_val_t agent); el_val_t agent_number(el_val_t agent);
el_val_t agent_person(el_val_t agent); el_val_t agent_person(el_val_t agent);
el_val_t agent_workspace_root(void);
el_val_t agentic_api_key(void); el_val_t agentic_api_key(void);
el_val_t agentic_loop(el_val_t session_id, el_val_t model, el_val_t safe_sys, el_val_t tools_json, el_val_t messages_in, el_val_t h, el_val_t tools_log_in);
el_val_t agentic_resume(el_val_t session_id, el_val_t tool_use_id, el_val_t content);
el_val_t agentic_tools_all(void);
el_val_t agentic_tools_literal(void); el_val_t agentic_tools_literal(void);
el_val_t agentic_tools_with_web(void); el_val_t agentic_tools_with_web(void);
el_val_t agree_determiner(el_val_t det, el_val_t noun); el_val_t agree_determiner(el_val_t det, el_val_t noun);
@@ -29,8 +13,8 @@ el_val_t akk_alaku_present(el_val_t slot);
el_val_t akk_amaru_perfect(el_val_t slot); el_val_t akk_amaru_perfect(el_val_t slot);
el_val_t akk_amaru_present(el_val_t slot); el_val_t akk_amaru_present(el_val_t slot);
el_val_t akk_amaru_stative(el_val_t slot); el_val_t akk_amaru_stative(el_val_t slot);
el_val_t akk_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t akk_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t akk_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t akk_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t akk_copula_present(el_val_t slot); el_val_t akk_copula_present(el_val_t slot);
el_val_t akk_copula_stative(el_val_t slot); el_val_t akk_copula_stative(el_val_t slot);
el_val_t akk_decline(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t akk_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
@@ -48,25 +32,25 @@ el_val_t akk_qabu_stative(el_val_t slot);
el_val_t akk_regular_perfect(el_val_t stem, el_val_t slot); el_val_t akk_regular_perfect(el_val_t stem, el_val_t slot);
el_val_t akk_regular_present(el_val_t stem, el_val_t slot); el_val_t akk_regular_present(el_val_t stem, el_val_t slot);
el_val_t akk_regular_stative(el_val_t stem, el_val_t slot); el_val_t akk_regular_stative(el_val_t stem, el_val_t slot);
el_val_t akk_slot_g(el_val_t person, el_val_t gender, el_val_t number);
el_val_t akk_slot(el_val_t person, el_val_t number); el_val_t akk_slot(el_val_t person, el_val_t number);
el_val_t akk_slot_g(el_val_t person, el_val_t gender, el_val_t number);
el_val_t akk_str_drop_last(el_val_t s, el_val_t n); el_val_t akk_str_drop_last(el_val_t s, el_val_t n);
el_val_t akk_str_ends(el_val_t s, el_val_t suf); el_val_t akk_str_ends(el_val_t s, el_val_t suf);
el_val_t akk_str_len(el_val_t s); el_val_t akk_str_len(el_val_t s);
el_val_t akk_strip_nom(el_val_t noun); el_val_t akk_strip_nom(el_val_t noun);
el_val_t ang_article(el_val_t gender, el_val_t gram_case, el_val_t number);
el_val_t ang_article_feminine(el_val_t gram_case, el_val_t number); el_val_t ang_article_feminine(el_val_t gram_case, el_val_t number);
el_val_t ang_article_masculine(el_val_t gram_case, el_val_t number); el_val_t ang_article_masculine(el_val_t gram_case, el_val_t number);
el_val_t ang_article_neuter(el_val_t gram_case, el_val_t number); el_val_t ang_article_neuter(el_val_t gram_case, el_val_t number);
el_val_t ang_article(el_val_t gender, el_val_t gram_case, el_val_t number);
el_val_t ang_beon_present(el_val_t slot); el_val_t ang_beon_present(el_val_t slot);
el_val_t ang_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t ang_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t ang_cuman_past(el_val_t slot); el_val_t ang_cuman_past(el_val_t slot);
el_val_t ang_cuman_present(el_val_t slot); el_val_t ang_cuman_present(el_val_t slot);
el_val_t ang_declension(el_val_t noun, el_val_t gender); el_val_t ang_declension(el_val_t noun, el_val_t gender);
el_val_t ang_decline(el_val_t noun, el_val_t gram_case, el_val_t number, el_val_t gender);
el_val_t ang_decline_strong_masc(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t ang_decline_strong_masc(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t ang_decline_strong_neut(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t ang_decline_strong_neut(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t ang_decline_weak(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t ang_decline_weak(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t ang_decline(el_val_t noun, el_val_t gram_case, el_val_t number, el_val_t gender);
el_val_t ang_don_past(el_val_t slot); el_val_t ang_don_past(el_val_t slot);
el_val_t ang_don_present(el_val_t slot); el_val_t ang_don_present(el_val_t slot);
el_val_t ang_gan_past(el_val_t slot); el_val_t ang_gan_past(el_val_t slot);
@@ -85,10 +69,10 @@ el_val_t ang_seon_present(el_val_t slot);
el_val_t ang_slot(el_val_t person, el_val_t number); el_val_t ang_slot(el_val_t person, el_val_t number);
el_val_t ang_str_drop_last(el_val_t s, el_val_t n); el_val_t ang_str_drop_last(el_val_t s, el_val_t n);
el_val_t ang_str_ends(el_val_t s, el_val_t suf); el_val_t ang_str_ends(el_val_t s, el_val_t suf);
el_val_t ang_str_last_char(el_val_t s);
el_val_t ang_str_last2(el_val_t s); el_val_t ang_str_last2(el_val_t s);
el_val_t ang_weak_past_stem(el_val_t stem); el_val_t ang_str_last_char(el_val_t s);
el_val_t ang_weak_past(el_val_t stem, el_val_t slot); el_val_t ang_weak_past(el_val_t stem, el_val_t slot);
el_val_t ang_weak_past_stem(el_val_t stem);
el_val_t ang_weak_present_ending(el_val_t slot); el_val_t ang_weak_present_ending(el_val_t slot);
el_val_t ang_weak_stem(el_val_t verb); el_val_t ang_weak_stem(el_val_t verb);
el_val_t ang_wesan_past(el_val_t slot); el_val_t ang_wesan_past(el_val_t slot);
@@ -97,30 +81,28 @@ el_val_t ang_willan_past(el_val_t slot);
el_val_t ang_willan_present(el_val_t slot); el_val_t ang_willan_present(el_val_t slot);
el_val_t ang_witan_past(el_val_t slot); el_val_t ang_witan_past(el_val_t slot);
el_val_t ang_witan_present(el_val_t slot); el_val_t ang_witan_present(el_val_t slot);
el_val_t api_err_protected(el_val_t id);
el_val_t api_err(el_val_t msg); el_val_t api_err(el_val_t msg);
el_val_t api_err_protected(el_val_t id);
el_val_t api_json_escape(el_val_t s); el_val_t api_json_escape(el_val_t s);
el_val_t api_nonempty(el_val_t s); el_val_t api_nonempty(el_val_t s);
el_val_t api_not_persisted(el_val_t id);
el_val_t api_ok(el_val_t extra); el_val_t api_ok(el_val_t extra);
el_val_t api_or_empty(el_val_t s); el_val_t api_or_empty(el_val_t s);
el_val_t api_persisted(el_val_t id);
el_val_t api_query_int(el_val_t path, el_val_t key, el_val_t default_val); el_val_t api_query_int(el_val_t path, el_val_t key, el_val_t default_val);
el_val_t api_query_param(el_val_t path, el_val_t key); el_val_t api_query_param(el_val_t path, el_val_t key);
el_val_t ar_case_ending(el_val_t kase, el_val_t definite); el_val_t ar_case_ending(el_val_t kase, el_val_t definite);
el_val_t ar_conjugate_form1(el_val_t past_base, el_val_t present_stem, el_val_t tense, el_val_t slot);
el_val_t ar_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t gender, el_val_t number); el_val_t ar_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t gender, el_val_t number);
el_val_t ar_conjugate_form1(el_val_t past_base, el_val_t present_stem, el_val_t tense, el_val_t slot);
el_val_t ar_definite_article(el_val_t noun); el_val_t ar_definite_article(el_val_t noun);
el_val_t ar_gender(el_val_t noun); el_val_t ar_gender(el_val_t noun);
el_val_t ar_imperfect_prefix(el_val_t slot); el_val_t ar_imperfect_prefix(el_val_t slot);
el_val_t ar_imperfect_suffix(el_val_t slot); el_val_t ar_imperfect_suffix(el_val_t slot);
el_val_t ar_irregular(el_val_t verb, el_val_t tense, el_val_t slot);
el_val_t ar_irregular_araada(el_val_t slot, el_val_t tense); el_val_t ar_irregular_araada(el_val_t slot, el_val_t tense);
el_val_t ar_irregular_istata(el_val_t slot, el_val_t tense); el_val_t ar_irregular_istata(el_val_t slot, el_val_t tense);
el_val_t ar_irregular_jaa(el_val_t slot, el_val_t tense); el_val_t ar_irregular_jaa(el_val_t slot, el_val_t tense);
el_val_t ar_irregular_kaana(el_val_t slot, el_val_t tense); el_val_t ar_irregular_kaana(el_val_t slot, el_val_t tense);
el_val_t ar_irregular_qaala(el_val_t slot, el_val_t tense); el_val_t ar_irregular_qaala(el_val_t slot, el_val_t tense);
el_val_t ar_irregular_raaa(el_val_t slot, el_val_t tense); el_val_t ar_irregular_raaa(el_val_t slot, el_val_t tense);
el_val_t ar_irregular(el_val_t verb, el_val_t tense, el_val_t slot);
el_val_t ar_is_sun_letter(el_val_t c); el_val_t ar_is_sun_letter(el_val_t c);
el_val_t ar_masc_pl_ending(el_val_t kase); el_val_t ar_masc_pl_ending(el_val_t kase);
el_val_t ar_noun_form(el_val_t noun, el_val_t gender, el_val_t kase, el_val_t number, el_val_t definite); el_val_t ar_noun_form(el_val_t noun, el_val_t gender, el_val_t kase, el_val_t number, el_val_t definite);
@@ -136,36 +118,24 @@ el_val_t ar_verb_form(el_val_t verb, el_val_t tense, el_val_t person, el_val_t n
el_val_t attend(el_val_t node_json); el_val_t attend(el_val_t node_json);
el_val_t auth_headers(el_val_t tok); el_val_t auth_headers(el_val_t tok);
el_val_t auto_persist(el_val_t req, el_val_t resp); el_val_t auto_persist(el_val_t req, el_val_t resp);
el_val_t auto_term_try_slot(el_val_t slot_type, el_val_t slot_lbl);
el_val_t awareness_run(void); el_val_t awareness_run(void);
el_val_t axon_get(el_val_t path); el_val_t axon_get(el_val_t path);
el_val_t axon_post(el_val_t path, el_val_t body); el_val_t axon_post(el_val_t path, el_val_t body);
el_val_t bounded_persona_floor(void);
el_val_t bridge_save(el_val_t session_id, el_val_t model, el_val_t safe_sys, el_val_t tools_json, el_val_t messages, el_val_t tools_log, el_val_t tool_use_id, el_val_t wire);
el_val_t build_form_from_json(el_val_t semantic_form_json, el_val_t lang_code); el_val_t build_form_from_json(el_val_t semantic_form_json, el_val_t lang_code);
el_val_t build_identity_from_graph(void);
el_val_t build_np(el_val_t referent, el_val_t slots); el_val_t build_np(el_val_t referent, el_val_t slots);
el_val_t build_pp(el_val_t loc); el_val_t build_pp(el_val_t loc);
el_val_t build_rules(void); el_val_t build_rules(void);
el_val_t build_system_prompt(el_val_t ctx, el_val_t chat_mode); el_val_t build_system_prompt(el_val_t ctx);
el_val_t build_vocab(void); el_val_t build_vocab(void);
el_val_t build_vp_body(el_val_t slots); el_val_t build_vp_body(el_val_t slots);
el_val_t build_vp_from_slots(el_val_t slots); el_val_t build_vp_from_slots(el_val_t slots);
el_val_t call_mcp_bridge(el_val_t tool_name, el_val_t tool_input); el_val_t call_neuron_mcp(el_val_t tool_name, el_val_t args_json);
el_val_t call_neuron_mcp(el_val_t tool_name, el_val_t args);
el_val_t capitalize_first(el_val_t s); el_val_t capitalize_first(el_val_t s);
el_val_t chat_default_model(void); el_val_t chat_default_model(void);
el_val_t classify_tool_risk(el_val_t tool_name, el_val_t tool_input);
el_val_t clean_llm_response(el_val_t s); el_val_t clean_llm_response(el_val_t s);
el_val_t cmd_abs_escape_at(el_val_t cmd, el_val_t root, el_val_t needle); el_val_t conv_history_load(void);
el_val_t connectd_get(el_val_t suffix); el_val_t conv_history_persist(el_val_t hist);
el_val_t connectd_post(el_val_t suffix, el_val_t body);
el_val_t connector_tools_json(void);
el_val_t conv_hist_key(el_val_t session_id);
el_val_t conv_hist_label(el_val_t session_id);
el_val_t conv_history_block(el_val_t session_id);
el_val_t conv_history_load(el_val_t session_id);
el_val_t conv_history_persist(el_val_t session_id, el_val_t hist);
el_val_t conv_history_record(el_val_t session_id, el_val_t user_msg, el_val_t assistant_msg, el_val_t receipt);
el_val_t cop_article(el_val_t gender, el_val_t number, el_val_t definite); el_val_t cop_article(el_val_t gender, el_val_t number, el_val_t definite);
el_val_t cop_bwk_future(el_val_t prefix); el_val_t cop_bwk_future(el_val_t prefix);
el_val_t cop_bwk_perfect(el_val_t prefix); el_val_t cop_bwk_perfect(el_val_t prefix);
@@ -187,8 +157,8 @@ el_val_t cop_map_canonical(el_val_t verb);
el_val_t cop_nau_future(el_val_t prefix); el_val_t cop_nau_future(el_val_t prefix);
el_val_t cop_nau_perfect(el_val_t prefix); el_val_t cop_nau_perfect(el_val_t prefix);
el_val_t cop_nau_present(el_val_t prefix); el_val_t cop_nau_present(el_val_t prefix);
el_val_t cop_noun_phrase_gendered(el_val_t noun, el_val_t gram_case, el_val_t number, el_val_t definite, el_val_t gender);
el_val_t cop_noun_phrase(el_val_t noun, el_val_t gram_case, el_val_t number, el_val_t definite); el_val_t cop_noun_phrase(el_val_t noun, el_val_t gram_case, el_val_t number, el_val_t definite);
el_val_t cop_noun_phrase_gendered(el_val_t noun, el_val_t gram_case, el_val_t number, el_val_t definite, el_val_t gender);
el_val_t cop_regular_future(el_val_t prefix, el_val_t stem); el_val_t cop_regular_future(el_val_t prefix, el_val_t stem);
el_val_t cop_regular_perfect(el_val_t prefix, el_val_t stem); el_val_t cop_regular_perfect(el_val_t prefix, el_val_t stem);
el_val_t cop_regular_present(el_val_t prefix, el_val_t stem); el_val_t cop_regular_present(el_val_t prefix, el_val_t stem);
@@ -198,16 +168,15 @@ el_val_t cop_shwpe_present(el_val_t prefix);
el_val_t cop_slot(el_val_t person, el_val_t number); el_val_t cop_slot(el_val_t person, el_val_t number);
el_val_t cop_str_ends(el_val_t s, el_val_t suf); el_val_t cop_str_ends(el_val_t s, el_val_t suf);
el_val_t cop_str_len(el_val_t s); el_val_t cop_str_len(el_val_t s);
el_val_t cop_subject_prefix_gendered(el_val_t person, el_val_t gender, el_val_t number);
el_val_t cop_subject_prefix(el_val_t person, el_val_t number); el_val_t cop_subject_prefix(el_val_t person, el_val_t number);
el_val_t current_engine_note(el_val_t model); el_val_t cop_subject_prefix_gendered(el_val_t person, el_val_t gender, el_val_t number);
el_val_t de_adj_ending(el_val_t gender, el_val_t gram_case, el_val_t number, el_val_t article_type); el_val_t de_adj_ending(el_val_t gender, el_val_t gram_case, el_val_t number, el_val_t article_type);
el_val_t de_article(el_val_t gender, el_val_t gram_case, el_val_t number, el_val_t definite);
el_val_t de_article_def(el_val_t gender, el_val_t gram_case, el_val_t number); el_val_t de_article_def(el_val_t gender, el_val_t gram_case, el_val_t number);
el_val_t de_article_indef(el_val_t gender, el_val_t gram_case, el_val_t number); el_val_t de_article_indef(el_val_t gender, el_val_t gram_case, el_val_t number);
el_val_t de_article(el_val_t gender, el_val_t gram_case, el_val_t number, el_val_t definite);
el_val_t de_case_ending(el_val_t noun, el_val_t gender, el_val_t gram_case, el_val_t number); el_val_t de_case_ending(el_val_t noun, el_val_t gender, el_val_t gram_case, el_val_t number);
el_val_t de_conjugate_weak(el_val_t stem, el_val_t tense, el_val_t person, el_val_t number);
el_val_t de_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t de_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t de_conjugate_weak(el_val_t stem, el_val_t tense, el_val_t person, el_val_t number);
el_val_t de_irregular_present(el_val_t verb, el_val_t person, el_val_t number); el_val_t de_irregular_present(el_val_t verb, el_val_t person, el_val_t number);
el_val_t de_norm_number(el_val_t number); el_val_t de_norm_number(el_val_t number);
el_val_t de_norm_person(el_val_t person); el_val_t de_norm_person(el_val_t person);
@@ -216,13 +185,15 @@ el_val_t de_strong_past_stem(el_val_t verb);
el_val_t dharma_network_state(void); el_val_t dharma_network_state(void);
el_val_t dharma_registry(void); el_val_t dharma_registry(void);
el_val_t dispatch_tool(el_val_t tool_name, el_val_t tool_input); el_val_t dispatch_tool(el_val_t tool_name, el_val_t tool_input);
el_val_t distill_transcript(el_val_t transcript);
el_val_t egy_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t egy_conjugate_pronoun(el_val_t person, el_val_t number);
el_val_t egy_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t egy_Dd_future(el_val_t slot); el_val_t egy_Dd_future(el_val_t slot);
el_val_t egy_Dd_past(el_val_t slot); el_val_t egy_Dd_past(el_val_t slot);
el_val_t egy_Dd_present(el_val_t slot); el_val_t egy_Dd_present(el_val_t slot);
el_val_t egy_Sm_future(el_val_t slot);
el_val_t egy_Sm_past(el_val_t slot);
el_val_t egy_Sm_present(el_val_t slot);
el_val_t egy_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t egy_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t egy_conjugate_pronoun(el_val_t person, el_val_t number);
el_val_t egy_decline(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t egy_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t egy_drop(el_val_t s, el_val_t n); el_val_t egy_drop(el_val_t s, el_val_t n);
el_val_t egy_fem(el_val_t noun); el_val_t egy_fem(el_val_t noun);
@@ -246,11 +217,8 @@ el_val_t egy_regular_present(el_val_t stem, el_val_t slot);
el_val_t egy_sdm_future(el_val_t slot); el_val_t egy_sdm_future(el_val_t slot);
el_val_t egy_sdm_past(el_val_t slot); el_val_t egy_sdm_past(el_val_t slot);
el_val_t egy_sdm_present(el_val_t slot); el_val_t egy_sdm_present(el_val_t slot);
el_val_t egy_slot_with_gender(el_val_t person, el_val_t gender, el_val_t number);
el_val_t egy_slot(el_val_t person, el_val_t number); el_val_t egy_slot(el_val_t person, el_val_t number);
el_val_t egy_Sm_future(el_val_t slot); el_val_t egy_slot_with_gender(el_val_t person, el_val_t gender, el_val_t number);
el_val_t egy_Sm_past(el_val_t slot);
el_val_t egy_Sm_present(el_val_t slot);
el_val_t egy_str_ends(el_val_t s, el_val_t suf); el_val_t egy_str_ends(el_val_t s, el_val_t suf);
el_val_t egy_str_len(el_val_t s); el_val_t egy_str_len(el_val_t s);
el_val_t egy_suffix_pronoun(el_val_t slot); el_val_t egy_suffix_pronoun(el_val_t slot);
@@ -271,20 +239,7 @@ el_val_t en_verb_3sg(el_val_t base);
el_val_t en_verb_form(el_val_t base, el_val_t tense, el_val_t person, el_val_t number); el_val_t en_verb_form(el_val_t base, el_val_t tense, el_val_t person, el_val_t number);
el_val_t en_verb_gerund(el_val_t base); el_val_t en_verb_gerund(el_val_t base);
el_val_t en_verb_past(el_val_t base); el_val_t en_verb_past(el_val_t base);
el_val_t engram_compile_multi(el_val_t topic);
el_val_t engram_compile_ranked(el_val_t nodes_json, el_val_t max_nodes);
el_val_t engram_compile(el_val_t intent); el_val_t engram_compile(el_val_t intent);
el_val_t engram_dedup_nodes(el_val_t nodes_json);
el_val_t engram_detect_recall_intent(el_val_t message);
el_val_t engram_extract_entities(el_val_t message);
el_val_t engram_extract_ids(el_val_t nodes_json);
el_val_t engram_is_continuation(el_val_t message, el_val_t hist_len);
el_val_t engram_nodes_merge(el_val_t a, el_val_t b);
el_val_t engram_numeric_valid(el_val_t s);
el_val_t engram_render_node(el_val_t node_json);
el_val_t engram_render_nodes(el_val_t nodes_json);
el_val_t engram_score_node(el_val_t node_json);
el_val_t engram_split_topics(el_val_t message);
el_val_t enm_been_past(el_val_t slot); el_val_t enm_been_past(el_val_t slot);
el_val_t enm_been_present(el_val_t slot); el_val_t enm_been_present(el_val_t slot);
el_val_t enm_comen_past(el_val_t slot); el_val_t enm_comen_past(el_val_t slot);
@@ -314,7 +269,6 @@ el_val_t enm_str_ends(el_val_t s, el_val_t suf);
el_val_t enm_weak_past(el_val_t stem, el_val_t slot); el_val_t enm_weak_past(el_val_t stem, el_val_t slot);
el_val_t enm_weak_present(el_val_t stem, el_val_t slot); el_val_t enm_weak_present(el_val_t stem, el_val_t slot);
el_val_t enm_weak_stem(el_val_t verb); el_val_t enm_weak_stem(el_val_t verb);
el_val_t ensure_self_canonical_bridge(void);
el_val_t entry_form(el_val_t entry, el_val_t n); el_val_t entry_form(el_val_t entry, el_val_t n);
el_val_t entry_found(el_val_t entry); el_val_t entry_found(el_val_t entry);
el_val_t entry_pos(el_val_t entry); el_val_t entry_pos(el_val_t entry);
@@ -339,9 +293,9 @@ el_val_t es_starts_with_stressed_a(el_val_t noun);
el_val_t es_stem(el_val_t base); el_val_t es_stem(el_val_t base);
el_val_t es_str_drop_last(el_val_t s, el_val_t n); el_val_t es_str_drop_last(el_val_t s, el_val_t n);
el_val_t es_str_ends(el_val_t s, el_val_t suf); el_val_t es_str_ends(el_val_t s, el_val_t suf);
el_val_t es_str_last_char(el_val_t s);
el_val_t es_str_last2(el_val_t s); el_val_t es_str_last2(el_val_t s);
el_val_t es_str_last3(el_val_t s); el_val_t es_str_last3(el_val_t s);
el_val_t es_str_last_char(el_val_t s);
el_val_t es_verb_class(el_val_t base); el_val_t es_verb_class(el_val_t base);
el_val_t extract_dim(el_val_t content, el_val_t key); el_val_t extract_dim(el_val_t content, el_val_t key);
el_val_t fi_apply_case(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t fi_apply_case(el_val_t noun, el_val_t gram_case, el_val_t number);
@@ -361,7 +315,6 @@ el_val_t fi_str_last_char(el_val_t s);
el_val_t fi_suffix(el_val_t base, el_val_t harmony); el_val_t fi_suffix(el_val_t base, el_val_t harmony);
el_val_t fi_verb_stem(el_val_t dict_form); el_val_t fi_verb_stem(el_val_t dict_form);
el_val_t find_rule(el_val_t rule_id_str); el_val_t find_rule(el_val_t rule_id_str);
el_val_t flag_true(el_val_t body, el_val_t key);
el_val_t fr_agree_article(el_val_t noun, el_val_t definite, el_val_t number); el_val_t fr_agree_article(el_val_t noun, el_val_t definite, el_val_t number);
el_val_t fr_avoir_present(el_val_t slot); el_val_t fr_avoir_present(el_val_t slot);
el_val_t fr_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t fr_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
@@ -384,8 +337,8 @@ el_val_t fr_slot(el_val_t person, el_val_t number);
el_val_t fr_stem(el_val_t base); el_val_t fr_stem(el_val_t base);
el_val_t fr_str_drop_last(el_val_t s, el_val_t n); el_val_t fr_str_drop_last(el_val_t s, el_val_t n);
el_val_t fr_str_ends(el_val_t s, el_val_t suf); el_val_t fr_str_ends(el_val_t s, el_val_t suf);
el_val_t fr_str_last_char(el_val_t s);
el_val_t fr_str_last2(el_val_t s); el_val_t fr_str_last2(el_val_t s);
el_val_t fr_str_last_char(el_val_t s);
el_val_t fr_subject_starts_vowel(el_val_t subject); el_val_t fr_subject_starts_vowel(el_val_t subject);
el_val_t fr_uses_etre(el_val_t verb); el_val_t fr_uses_etre(el_val_t verb);
el_val_t fr_verb_ends_vowel(el_val_t verb_form); el_val_t fr_verb_ends_vowel(el_val_t verb_form);
@@ -407,9 +360,9 @@ el_val_t fro_conj3_future(el_val_t verb, el_val_t slot);
el_val_t fro_conj3_past(el_val_t stem, el_val_t slot); el_val_t fro_conj3_past(el_val_t stem, el_val_t slot);
el_val_t fro_conj3_present(el_val_t stem, el_val_t slot); el_val_t fro_conj3_present(el_val_t stem, el_val_t slot);
el_val_t fro_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t fro_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t fro_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t fro_decline_fem(el_val_t noun, el_val_t number); el_val_t fro_decline_fem(el_val_t noun, el_val_t number);
el_val_t fro_decline_masc(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t fro_decline_masc(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t fro_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t fro_drop(el_val_t s, el_val_t n); el_val_t fro_drop(el_val_t s, el_val_t n);
el_val_t fro_estre_future(el_val_t slot); el_val_t fro_estre_future(el_val_t slot);
el_val_t fro_estre_past(el_val_t slot); el_val_t fro_estre_past(el_val_t slot);
@@ -427,15 +380,16 @@ el_val_t fro_venir_past(el_val_t slot);
el_val_t fro_venir_present(el_val_t slot); el_val_t fro_venir_present(el_val_t slot);
el_val_t fro_verb_class(el_val_t verb); el_val_t fro_verb_class(el_val_t verb);
el_val_t fro_verb_stem(el_val_t verb, el_val_t vclass); el_val_t fro_verb_stem(el_val_t verb, el_val_t vclass);
el_val_t generate_frame_lang(el_val_t frame, el_val_t lang_code); el_val_t gemini_api_key(void);
el_val_t generate(el_val_t semantic_form_json);
el_val_t generate_frame(el_val_t frame); el_val_t generate_frame(el_val_t frame);
el_val_t generate_frame_lang(el_val_t frame, el_val_t lang_code);
el_val_t generate_lang(el_val_t semantic_form_json, el_val_t lang_code); el_val_t generate_lang(el_val_t semantic_form_json, el_val_t lang_code);
el_val_t generate_tree(el_val_t rule_id_str, el_val_t slots); el_val_t generate_tree(el_val_t rule_id_str, el_val_t slots);
el_val_t generate(el_val_t semantic_form_json);
el_val_t get_rules(void); el_val_t get_rules(void);
el_val_t get_vocab(void); el_val_t get_vocab(void);
el_val_t gez_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t gez_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t gez_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t gez_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t gez_decline(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t gez_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t gez_generic_imperfect(el_val_t base3sg, el_val_t slot); el_val_t gez_generic_imperfect(el_val_t base3sg, el_val_t slot);
el_val_t gez_generic_perfect(el_val_t base3sg, el_val_t slot); el_val_t gez_generic_perfect(el_val_t base3sg, el_val_t slot);
@@ -454,12 +408,13 @@ el_val_t gez_qwl_imperfect(el_val_t slot);
el_val_t gez_qwl_perfect(el_val_t slot); el_val_t gez_qwl_perfect(el_val_t slot);
el_val_t gez_ray_imperfect(el_val_t slot); el_val_t gez_ray_imperfect(el_val_t slot);
el_val_t gez_ray_perfect(el_val_t slot); el_val_t gez_ray_perfect(el_val_t slot);
el_val_t gez_slot_g(el_val_t person, el_val_t gender, el_val_t number);
el_val_t gez_slot(el_val_t person, el_val_t number); el_val_t gez_slot(el_val_t person, el_val_t number);
el_val_t gez_slot_g(el_val_t person, el_val_t gender, el_val_t number);
el_val_t gez_str_drop_last(el_val_t s, el_val_t n); el_val_t gez_str_drop_last(el_val_t s, el_val_t n);
el_val_t gez_str_ends(el_val_t s, el_val_t suf); el_val_t gez_str_ends(el_val_t s, el_val_t suf);
el_val_t gez_str_len(el_val_t s); el_val_t gez_str_len(el_val_t s);
el_val_t goh_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t goh_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t goh_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t goh_decline_fem_o_pl(el_val_t stem, el_val_t gram_case); el_val_t goh_decline_fem_o_pl(el_val_t stem, el_val_t gram_case);
el_val_t goh_decline_fem_o_sg(el_val_t stem, el_val_t gram_case); el_val_t goh_decline_fem_o_sg(el_val_t stem, el_val_t gram_case);
el_val_t goh_decline_masc_a_pl(el_val_t stem, el_val_t gram_case); el_val_t goh_decline_masc_a_pl(el_val_t stem, el_val_t gram_case);
@@ -468,7 +423,6 @@ el_val_t goh_decline_masc_n_pl(el_val_t stem, el_val_t gram_case);
el_val_t goh_decline_masc_n_sg(el_val_t stem, el_val_t gram_case); el_val_t goh_decline_masc_n_sg(el_val_t stem, el_val_t gram_case);
el_val_t goh_decline_neut_a_pl(el_val_t stem, el_val_t gram_case); el_val_t goh_decline_neut_a_pl(el_val_t stem, el_val_t gram_case);
el_val_t goh_decline_neut_a_sg(el_val_t stem, el_val_t gram_case); el_val_t goh_decline_neut_a_sg(el_val_t stem, el_val_t gram_case);
el_val_t goh_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t goh_demo_article(el_val_t stype, el_val_t number); el_val_t goh_demo_article(el_val_t stype, el_val_t number);
el_val_t goh_drop(el_val_t s, el_val_t n); el_val_t goh_drop(el_val_t s, el_val_t n);
el_val_t goh_extract_stem(el_val_t noun, el_val_t stype); el_val_t goh_extract_stem(el_val_t noun, el_val_t stype);
@@ -493,13 +447,13 @@ el_val_t goh_weak_present(el_val_t stem, el_val_t slot);
el_val_t goh_wesan_past(el_val_t slot); el_val_t goh_wesan_past(el_val_t slot);
el_val_t goh_wesan_present(el_val_t slot); el_val_t goh_wesan_present(el_val_t slot);
el_val_t got_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t got_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t got_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t got_decline_a_stem_pl(el_val_t stem, el_val_t gram_case); el_val_t got_decline_a_stem_pl(el_val_t stem, el_val_t gram_case);
el_val_t got_decline_a_stem_sg(el_val_t stem, el_val_t gram_case); el_val_t got_decline_a_stem_sg(el_val_t stem, el_val_t gram_case);
el_val_t got_decline_n_stem_pl(el_val_t stem, el_val_t gram_case); el_val_t got_decline_n_stem_pl(el_val_t stem, el_val_t gram_case);
el_val_t got_decline_n_stem_sg(el_val_t stem, el_val_t gram_case); el_val_t got_decline_n_stem_sg(el_val_t stem, el_val_t gram_case);
el_val_t got_decline_o_stem_pl(el_val_t stem, el_val_t gram_case); el_val_t got_decline_o_stem_pl(el_val_t stem, el_val_t gram_case);
el_val_t got_decline_o_stem_sg(el_val_t stem, el_val_t gram_case); el_val_t got_decline_o_stem_sg(el_val_t stem, el_val_t gram_case);
el_val_t got_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t got_demo_article(el_val_t stype); el_val_t got_demo_article(el_val_t stype);
el_val_t got_extract_stem(el_val_t noun, el_val_t stype); el_val_t got_extract_stem(el_val_t noun, el_val_t stype);
el_val_t got_gaggan_past(el_val_t slot); el_val_t got_gaggan_past(el_val_t slot);
@@ -532,17 +486,17 @@ el_val_t gram_build_vp(el_val_t verb, el_val_t aux, el_val_t profile);
el_val_t gram_order_constituents(el_val_t subj, el_val_t verb, el_val_t obj, el_val_t profile); el_val_t gram_order_constituents(el_val_t subj, el_val_t verb, el_val_t obj, el_val_t profile);
el_val_t gram_question_strategy(el_val_t profile); el_val_t gram_question_strategy(el_val_t profile);
el_val_t gram_word_order(el_val_t profile); el_val_t gram_word_order(el_val_t profile);
el_val_t grc_article(el_val_t gender, el_val_t gram_case, el_val_t number);
el_val_t grc_article_feminine(el_val_t gram_case, el_val_t number); el_val_t grc_article_feminine(el_val_t gram_case, el_val_t number);
el_val_t grc_article_masculine(el_val_t gram_case, el_val_t number); el_val_t grc_article_masculine(el_val_t gram_case, el_val_t number);
el_val_t grc_article_neuter(el_val_t gram_case, el_val_t number); el_val_t grc_article_neuter(el_val_t gram_case, el_val_t number);
el_val_t grc_article(el_val_t gender, el_val_t gram_case, el_val_t number);
el_val_t grc_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t grc_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t grc_declension(el_val_t noun); el_val_t grc_declension(el_val_t noun);
el_val_t grc_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t grc_decline_1a(el_val_t stem, el_val_t gram_case, el_val_t number); el_val_t grc_decline_1a(el_val_t stem, el_val_t gram_case, el_val_t number);
el_val_t grc_decline_1e(el_val_t stem, el_val_t gram_case, el_val_t number); el_val_t grc_decline_1e(el_val_t stem, el_val_t gram_case, el_val_t number);
el_val_t grc_decline_2m(el_val_t stem, el_val_t gram_case, el_val_t number); el_val_t grc_decline_2m(el_val_t stem, el_val_t gram_case, el_val_t number);
el_val_t grc_decline_2n(el_val_t stem, el_val_t gram_case, el_val_t number); el_val_t grc_decline_2n(el_val_t stem, el_val_t gram_case, el_val_t number);
el_val_t grc_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t grc_echein_aorist(el_val_t slot); el_val_t grc_echein_aorist(el_val_t slot);
el_val_t grc_echein_future(el_val_t slot); el_val_t grc_echein_future(el_val_t slot);
el_val_t grc_echein_imperfect(el_val_t slot); el_val_t grc_echein_imperfect(el_val_t slot);
@@ -569,9 +523,9 @@ el_val_t grc_present_stem(el_val_t verb);
el_val_t grc_slot(el_val_t person, el_val_t number); el_val_t grc_slot(el_val_t person, el_val_t number);
el_val_t grc_str_drop_last(el_val_t s, el_val_t n); el_val_t grc_str_drop_last(el_val_t s, el_val_t n);
el_val_t grc_str_ends(el_val_t s, el_val_t suf); el_val_t grc_str_ends(el_val_t s, el_val_t suf);
el_val_t grc_str_last_char(el_val_t s);
el_val_t grc_str_last2(el_val_t s); el_val_t grc_str_last2(el_val_t s);
el_val_t grc_str_last3(el_val_t s); el_val_t grc_str_last3(el_val_t s);
el_val_t grc_str_last_char(el_val_t s);
el_val_t grc_thematic_future_ending(el_val_t slot); el_val_t grc_thematic_future_ending(el_val_t slot);
el_val_t grc_thematic_imperfect_ending(el_val_t slot); el_val_t grc_thematic_imperfect_ending(el_val_t slot);
el_val_t grc_thematic_present_ending(el_val_t slot); el_val_t grc_thematic_present_ending(el_val_t slot);
@@ -595,37 +549,29 @@ el_val_t handle_api_list_typed(el_val_t node_type, el_val_t path, el_val_t body)
el_val_t handle_api_log_state_event(el_val_t body); el_val_t handle_api_log_state_event(el_val_t body);
el_val_t handle_api_memory_delete(el_val_t body); el_val_t handle_api_memory_delete(el_val_t body);
el_val_t handle_api_memory_update(el_val_t body); el_val_t handle_api_memory_update(el_val_t body);
el_val_t handle_api_node_create(el_val_t body);
el_val_t handle_api_node_delete(el_val_t body);
el_val_t handle_api_node_update(el_val_t body);
el_val_t handle_api_promote_knowledge(el_val_t body); el_val_t handle_api_promote_knowledge(el_val_t body);
el_val_t handle_api_recall(el_val_t method, el_val_t path, el_val_t body); el_val_t handle_api_recall(el_val_t method, el_val_t path, el_val_t body);
el_val_t handle_api_remember(el_val_t body); el_val_t handle_api_remember(el_val_t body);
el_val_t handle_api_search_knowledge(el_val_t method, el_val_t path, el_val_t body); el_val_t handle_api_search_knowledge(el_val_t method, el_val_t path, el_val_t body);
el_val_t handle_api_tune_config(el_val_t body); el_val_t handle_api_tune_config(el_val_t body);
el_val_t handle_chat(el_val_t body);
el_val_t handle_chat_agentic(el_val_t body); el_val_t handle_chat_agentic(el_val_t body);
el_val_t handle_chat_as_soul(el_val_t body); el_val_t handle_chat_as_soul(el_val_t body);
el_val_t handle_chat_plan(el_val_t body);
el_val_t handle_chat(el_val_t body);
el_val_t handle_config(el_val_t method, el_val_t body); el_val_t handle_config(el_val_t method, el_val_t body);
el_val_t handle_connectors(el_val_t method, el_val_t clean, el_val_t body);
el_val_t handle_conversations(el_val_t method); el_val_t handle_conversations(el_val_t method);
el_val_t handle_dharma_recv(el_val_t body);
el_val_t handle_dharma_room_turn_agentic(el_val_t body);
el_val_t handle_dharma_room_turn(el_val_t body);
el_val_t handle_dharma(el_val_t path, el_val_t method, el_val_t body); el_val_t handle_dharma(el_val_t path, el_val_t method, el_val_t body);
el_val_t handle_dharma_recv(el_val_t body);
el_val_t handle_dharma_room_turn(el_val_t body);
el_val_t handle_dharma_room_turn_agentic(el_val_t body);
el_val_t handle_elp_chat(el_val_t body); el_val_t handle_elp_chat(el_val_t body);
el_val_t handle_nlg(el_val_t path, el_val_t method, el_val_t body); el_val_t handle_nlg(el_val_t path, el_val_t method, el_val_t body);
el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body); el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body);
el_val_t handle_safety_contact_get(void);
el_val_t handle_safety_contact_post(el_val_t body);
el_val_t handle_see(el_val_t body); el_val_t handle_see(el_val_t body);
el_val_t handle_session_approve(el_val_t session_id, el_val_t body); el_val_t handle_session_approve(el_val_t session_id, el_val_t body);
el_val_t handle_tool_result(el_val_t session_id, el_val_t body);
el_val_t handle_tool(el_val_t path, el_val_t method, el_val_t body); el_val_t handle_tool(el_val_t path, el_val_t method, el_val_t body);
el_val_t hard_bell_threshold(void); el_val_t hard_bell_threshold(void);
el_val_t he_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t he_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t gender, el_val_t number); el_val_t he_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t gender, el_val_t number);
el_val_t he_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t he_copula_future(el_val_t slot); el_val_t he_copula_future(el_val_t slot);
el_val_t he_copula_past(el_val_t slot); el_val_t he_copula_past(el_val_t slot);
el_val_t he_definite_prefix(el_val_t noun); el_val_t he_definite_prefix(el_val_t noun);
@@ -662,12 +608,12 @@ el_val_t hi_genitive_phrase(el_val_t possessor, el_val_t possessor_gender, el_va
el_val_t hi_hona_past(el_val_t gender, el_val_t number); el_val_t hi_hona_past(el_val_t gender, el_val_t number);
el_val_t hi_hona_present(el_val_t person, el_val_t number); el_val_t hi_hona_present(el_val_t person, el_val_t number);
el_val_t hi_masc_aa_stem(el_val_t noun); el_val_t hi_masc_aa_stem(el_val_t noun);
el_val_t hi_noun_direct(el_val_t noun, el_val_t gender, el_val_t number);
el_val_t hi_noun_direct_f(el_val_t noun, el_val_t number); el_val_t hi_noun_direct_f(el_val_t noun, el_val_t number);
el_val_t hi_noun_direct_m(el_val_t noun, el_val_t number); el_val_t hi_noun_direct_m(el_val_t noun, el_val_t number);
el_val_t hi_noun_direct(el_val_t noun, el_val_t gender, el_val_t number); el_val_t hi_noun_oblique(el_val_t noun, el_val_t gender, el_val_t number);
el_val_t hi_noun_oblique_f(el_val_t noun, el_val_t number); el_val_t hi_noun_oblique_f(el_val_t noun, el_val_t number);
el_val_t hi_noun_oblique_m(el_val_t noun, el_val_t number); el_val_t hi_noun_oblique_m(el_val_t noun, el_val_t number);
el_val_t hi_noun_oblique(el_val_t noun, el_val_t gender, el_val_t number);
el_val_t hi_noun_with_post(el_val_t noun, el_val_t gender, el_val_t number, el_val_t gram_case); el_val_t hi_noun_with_post(el_val_t noun, el_val_t gender, el_val_t number, el_val_t gram_case);
el_val_t hi_past_irregular(el_val_t stem, el_val_t gender, el_val_t number); el_val_t hi_past_irregular(el_val_t stem, el_val_t gender, el_val_t number);
el_val_t hi_past_suffix(el_val_t gender, el_val_t number); el_val_t hi_past_suffix(el_val_t gender, el_val_t number);
@@ -677,12 +623,10 @@ el_val_t hi_str_drop_last(el_val_t s, el_val_t n);
el_val_t hi_str_ends(el_val_t s, el_val_t suf); el_val_t hi_str_ends(el_val_t s, el_val_t suf);
el_val_t hi_str_last_char(el_val_t s); el_val_t hi_str_last_char(el_val_t s);
el_val_t hi_tense_suffix(el_val_t tense, el_val_t gender, el_val_t number); el_val_t hi_tense_suffix(el_val_t tense, el_val_t gender, el_val_t number);
el_val_t hi_verb_stem_clean(el_val_t infinitive);
el_val_t hi_verb_stem(el_val_t infinitive); el_val_t hi_verb_stem(el_val_t infinitive);
el_val_t hi_verb_stem_clean(el_val_t infinitive);
el_val_t hist_append(el_val_t hist, el_val_t role, el_val_t content); el_val_t hist_append(el_val_t hist, el_val_t role, el_val_t content);
el_val_t hist_trim_with_bell_guard(el_val_t hist);
el_val_t hist_trim(el_val_t hist); el_val_t hist_trim(el_val_t hist);
el_val_t id_in_seen(el_val_t node_id, el_val_t seen);
el_val_t idle_count(void); el_val_t idle_count(void);
el_val_t idle_inc(void); el_val_t idle_inc(void);
el_val_t idle_reset(void); el_val_t idle_reset(void);
@@ -695,7 +639,6 @@ el_val_t imprint_unload(void);
el_val_t init_soul_edges(void); el_val_t init_soul_edges(void);
el_val_t irregular_plural(el_val_t word); el_val_t irregular_plural(el_val_t word);
el_val_t irregular_singular(el_val_t word); el_val_t irregular_singular(el_val_t word);
el_val_t is_builtin_tool(el_val_t tool_name);
el_val_t is_pronoun(el_val_t word); el_val_t is_pronoun(el_val_t word);
el_val_t is_protected_node(el_val_t id); el_val_t is_protected_node(el_val_t id);
el_val_t is_vowel(el_val_t c); el_val_t is_vowel(el_val_t c);
@@ -708,10 +651,10 @@ el_val_t ja_noun_phrase(el_val_t noun, el_val_t gram_case);
el_val_t ja_particle(el_val_t gram_case); el_val_t ja_particle(el_val_t gram_case);
el_val_t ja_question_particle(void); el_val_t ja_question_particle(void);
el_val_t ja_verb_group(el_val_t dict_form); el_val_t ja_verb_group(el_val_t dict_form);
el_val_t json_escape(el_val_t s);
el_val_t json_safe(el_val_t s); el_val_t json_safe(el_val_t s);
el_val_t la_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t la_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t la_declension(el_val_t noun); el_val_t la_declension(el_val_t noun);
el_val_t la_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t la_decline_1(el_val_t stem, el_val_t gram_case, el_val_t number); el_val_t la_decline_1(el_val_t stem, el_val_t gram_case, el_val_t number);
el_val_t la_decline_2er(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t la_decline_2er(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t la_decline_2m(el_val_t stem, el_val_t gram_case, el_val_t number); el_val_t la_decline_2m(el_val_t stem, el_val_t gram_case, el_val_t number);
@@ -719,7 +662,6 @@ el_val_t la_decline_2n(el_val_t stem, el_val_t gram_case, el_val_t number);
el_val_t la_decline_3(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t la_decline_3(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t la_decline_4(el_val_t stem, el_val_t gram_case, el_val_t number); el_val_t la_decline_4(el_val_t stem, el_val_t gram_case, el_val_t number);
el_val_t la_decline_5(el_val_t stem, el_val_t gram_case, el_val_t number); el_val_t la_decline_5(el_val_t stem, el_val_t gram_case, el_val_t number);
el_val_t la_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t la_esse_future(el_val_t slot); el_val_t la_esse_future(el_val_t slot);
el_val_t la_esse_past(el_val_t slot); el_val_t la_esse_past(el_val_t slot);
el_val_t la_esse_present(el_val_t slot); el_val_t la_esse_present(el_val_t slot);
@@ -743,9 +685,9 @@ el_val_t la_slot(el_val_t person, el_val_t number);
el_val_t la_stem(el_val_t verb, el_val_t vclass); el_val_t la_stem(el_val_t verb, el_val_t vclass);
el_val_t la_str_drop_last(el_val_t s, el_val_t n); el_val_t la_str_drop_last(el_val_t s, el_val_t n);
el_val_t la_str_ends(el_val_t s, el_val_t suf); el_val_t la_str_ends(el_val_t s, el_val_t suf);
el_val_t la_str_last_char(el_val_t s);
el_val_t la_str_last2(el_val_t s); el_val_t la_str_last2(el_val_t s);
el_val_t la_str_last3(el_val_t s); el_val_t la_str_last3(el_val_t s);
el_val_t la_str_last_char(el_val_t s);
el_val_t la_velle_future(el_val_t slot); el_val_t la_velle_future(el_val_t slot);
el_val_t la_velle_past(el_val_t slot); el_val_t la_velle_past(el_val_t slot);
el_val_t la_velle_present(el_val_t slot); el_val_t la_velle_present(el_val_t slot);
@@ -762,6 +704,7 @@ el_val_t lang_is_fusional(el_val_t profile);
el_val_t lang_is_isolating(el_val_t profile); el_val_t lang_is_isolating(el_val_t profile);
el_val_t lang_is_polysynthetic(el_val_t profile); el_val_t lang_is_polysynthetic(el_val_t profile);
el_val_t lang_is_rtl(el_val_t profile); el_val_t lang_is_rtl(el_val_t profile);
el_val_t lang_profile(el_val_t code, el_val_t word_order, el_val_t morph_type, el_val_t has_case, el_val_t has_gender, el_val_t script_dir, el_val_t agreement, el_val_t null_subject);
el_val_t lang_profile_akk(void); el_val_t lang_profile_akk(void);
el_val_t lang_profile_ang(void); el_val_t lang_profile_ang(void);
el_val_t lang_profile_ar(void); el_val_t lang_profile_ar(void);
@@ -793,16 +736,13 @@ el_val_t lang_profile_sw(void);
el_val_t lang_profile_txb(void); el_val_t lang_profile_txb(void);
el_val_t lang_profile_uga(void); el_val_t lang_profile_uga(void);
el_val_t lang_profile_zh(void); el_val_t lang_profile_zh(void);
el_val_t lang_profile(el_val_t code, el_val_t word_order, el_val_t morph_type, el_val_t has_case, el_val_t has_gender, el_val_t script_dir, el_val_t agreement, el_val_t null_subject);
el_val_t lang_word_order(el_val_t profile); el_val_t lang_word_order(el_val_t profile);
el_val_t layered_cycle(el_val_t raw_input, el_val_t session_id, el_val_t utility);
el_val_t layered_generate(el_val_t prompt, el_val_t imprint_id, el_val_t session_id);
el_val_t lex_class(el_val_t entry); el_val_t lex_class(el_val_t entry);
el_val_t lex_form(el_val_t entry, el_val_t idx); el_val_t lex_form(el_val_t entry, el_val_t idx);
el_val_t lex_pos(el_val_t entry); el_val_t lex_pos(el_val_t entry);
el_val_t lex_word(el_val_t entry); el_val_t lex_word(el_val_t entry);
el_val_t llm_base_url(void); el_val_t llm_call_gemini(el_val_t model, el_val_t system, el_val_t message);
el_val_t llm_wire_format(void); el_val_t llm_call_grok(el_val_t model, el_val_t system, el_val_t message);
el_val_t load_identity_context(void); el_val_t load_identity_context(void);
el_val_t make_action(el_val_t kind, el_val_t payload); el_val_t make_action(el_val_t kind, el_val_t payload);
el_val_t make_entry(el_val_t word, el_val_t pos, el_val_t f0, el_val_t f1, el_val_t f2, el_val_t f3, el_val_t f4, el_val_t cls); el_val_t make_entry(el_val_t word, el_val_t pos, el_val_t f0, el_val_t f1, el_val_t f2, el_val_t f3, el_val_t f4, el_val_t cls);
@@ -835,20 +775,17 @@ el_val_t mem_save(el_val_t path);
el_val_t mem_search(el_val_t query, el_val_t limit); el_val_t mem_search(el_val_t query, el_val_t limit);
el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags); el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags);
el_val_t mem_strengthen(el_val_t node_id); el_val_t mem_strengthen(el_val_t node_id);
el_val_t mem_tombstone(el_val_t node_id);
el_val_t memory_hide_tombstoned(el_val_t raw, el_val_t path);
el_val_t morph_apply_suffix(el_val_t base, el_val_t suffix); el_val_t morph_apply_suffix(el_val_t base, el_val_t suffix);
el_val_t morph_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number, el_val_t profile); el_val_t morph_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number, el_val_t profile);
el_val_t morph_inflect(el_val_t word, el_val_t features, el_val_t profile); el_val_t morph_inflect(el_val_t word, el_val_t features, el_val_t profile);
el_val_t morph_map_canonical(el_val_t verb, el_val_t code); el_val_t morph_map_canonical(el_val_t verb, el_val_t code);
el_val_t morph_pluralize(el_val_t noun, el_val_t profile); el_val_t morph_pluralize(el_val_t noun, el_val_t profile);
el_val_t next_bridge_id(void);
el_val_t nlg_is_ws(el_val_t c); el_val_t nlg_is_ws(el_val_t c);
el_val_t non_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t non_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t non_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t non_decline_fem(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t non_decline_fem(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t non_decline_masc(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t non_decline_masc(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t non_decline_neut(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t non_decline_neut(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t non_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t non_def_suffix_fem(el_val_t gram_case, el_val_t number); el_val_t non_def_suffix_fem(el_val_t gram_case, el_val_t number);
el_val_t non_def_suffix_masc(el_val_t gram_case, el_val_t number); el_val_t non_def_suffix_masc(el_val_t gram_case, el_val_t number);
el_val_t non_def_suffix_neut(el_val_t gram_case, el_val_t number); el_val_t non_def_suffix_neut(el_val_t gram_case, el_val_t number);
@@ -874,21 +811,15 @@ el_val_t non_vera_present(el_val_t slot);
el_val_t non_weak_past(el_val_t stem, el_val_t slot); el_val_t non_weak_past(el_val_t stem, el_val_t slot);
el_val_t non_weak_present(el_val_t stem, el_val_t slot); el_val_t non_weak_present(el_val_t stem, el_val_t slot);
el_val_t one_cycle(void); el_val_t one_cycle(void);
el_val_t openai_chat_complete(el_val_t model, el_val_t base_url, el_val_t api_key, el_val_t safe_sys, el_val_t messages_json); el_val_t parse_session_id_from_path(el_val_t path);
el_val_t openai_tools_json(el_val_t tools_anthropic); el_val_t parse_session_subpath(el_val_t path);
el_val_t json_trim_dangling_escape(el_val_t s);
el_val_t utf8_safe_slice(el_val_t s, el_val_t n);
el_val_t agentic_tools_no_web(void);
el_val_t openai_agentic_loop(el_val_t session_id, el_val_t model, el_val_t safe_sys, el_val_t tools_json, el_val_t messages_in, el_val_t tools_log_in);
el_val_t parse_float_x100(el_val_t s);
el_val_t path_within_root(el_val_t path, el_val_t root);
el_val_t peo_ah_past(el_val_t slot); el_val_t peo_ah_past(el_val_t slot);
el_val_t peo_ah_present(el_val_t slot); el_val_t peo_ah_present(el_val_t slot);
el_val_t peo_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t peo_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t peo_da_past(el_val_t slot); el_val_t peo_da_past(el_val_t slot);
el_val_t peo_da_present(el_val_t slot); el_val_t peo_da_present(el_val_t slot);
el_val_t peo_decline_astem(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t peo_decline(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t peo_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t peo_decline_astem(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t peo_drop(el_val_t s, el_val_t n); el_val_t peo_drop(el_val_t s, el_val_t n);
el_val_t peo_ends(el_val_t s, el_val_t suf); el_val_t peo_ends(el_val_t s, el_val_t suf);
el_val_t peo_kar_past(el_val_t slot); el_val_t peo_kar_past(el_val_t slot);
@@ -904,11 +835,11 @@ el_val_t perceive(void);
el_val_t pi_aorist_ending(el_val_t slot); el_val_t pi_aorist_ending(el_val_t slot);
el_val_t pi_atthi_present(el_val_t slot); el_val_t pi_atthi_present(el_val_t slot);
el_val_t pi_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t pi_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t pi_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t pi_decline_a_fem_pl(el_val_t stem, el_val_t gram_case); el_val_t pi_decline_a_fem_pl(el_val_t stem, el_val_t gram_case);
el_val_t pi_decline_a_fem_sg(el_val_t stem, el_val_t gram_case); el_val_t pi_decline_a_fem_sg(el_val_t stem, el_val_t gram_case);
el_val_t pi_decline_a_masc_pl(el_val_t stem, el_val_t gram_case); el_val_t pi_decline_a_masc_pl(el_val_t stem, el_val_t gram_case);
el_val_t pi_decline_a_masc_sg(el_val_t stem, el_val_t gram_case); el_val_t pi_decline_a_masc_sg(el_val_t stem, el_val_t gram_case);
el_val_t pi_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t pi_detect_class(el_val_t noun); el_val_t pi_detect_class(el_val_t noun);
el_val_t pi_drop(el_val_t s, el_val_t n); el_val_t pi_drop(el_val_t s, el_val_t n);
el_val_t pi_future_ending(el_val_t slot); el_val_t pi_future_ending(el_val_t slot);
@@ -938,25 +869,24 @@ el_val_t pluralize(el_val_t singular);
el_val_t proactive_curiosity(void); el_val_t proactive_curiosity(void);
el_val_t pulse_count(void); el_val_t pulse_count(void);
el_val_t pulse_inc(void); el_val_t pulse_inc(void);
el_val_t rate_limit_check(el_val_t ip, el_val_t path); el_val_t realize(el_val_t form);
el_val_t realize_lang(el_val_t form, el_val_t profile); el_val_t realize_lang(el_val_t form, el_val_t profile);
el_val_t realize_np(el_val_t referent, el_val_t number); el_val_t realize_np(el_val_t referent, el_val_t number);
el_val_t realize_question_lang(el_val_t predicate, el_val_t tense, el_val_t aspect, el_val_t person, el_val_t number, el_val_t agent, el_val_t patient, el_val_t location, el_val_t profile); el_val_t realize_question_lang(el_val_t predicate, el_val_t tense, el_val_t aspect, el_val_t person, el_val_t number, el_val_t agent, el_val_t patient, el_val_t location, el_val_t profile);
el_val_t realize_vp_lang(el_val_t base_verb, el_val_t tense, el_val_t aspect, el_val_t person, el_val_t number, el_val_t profile); el_val_t realize_vp_lang(el_val_t base_verb, el_val_t tense, el_val_t aspect, el_val_t person, el_val_t number, el_val_t profile);
el_val_t realize(el_val_t form);
el_val_t record(el_val_t outcome_json); el_val_t record(el_val_t outcome_json);
el_val_t render_studio(void); el_val_t render_studio(void);
el_val_t render_tree(el_val_t tree); el_val_t render_tree(el_val_t tree);
el_val_t resolve_in_root(el_val_t path, el_val_t root);
el_val_t respond(el_val_t action_json); el_val_t respond(el_val_t action_json);
el_val_t route_health(void); el_val_t route_health(void);
el_val_t route_imprint_contextual(el_val_t body); el_val_t route_imprint_contextual(el_val_t body);
el_val_t route_imprint_user(el_val_t body); el_val_t route_imprint_user(el_val_t body);
el_val_t route_lineage(void); el_val_t route_lineage(void);
el_val_t route_sessions(void);
el_val_t route_synthesize(el_val_t body); el_val_t route_synthesize(el_val_t body);
el_val_t ru_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number, el_val_t gender);
el_val_t ru_conjugate_1st(el_val_t stem, el_val_t tense, el_val_t person, el_val_t number); el_val_t ru_conjugate_1st(el_val_t stem, el_val_t tense, el_val_t person, el_val_t number);
el_val_t ru_conjugate_2nd(el_val_t stem, el_val_t tense, el_val_t person, el_val_t number); el_val_t ru_conjugate_2nd(el_val_t stem, el_val_t tense, el_val_t person, el_val_t number);
el_val_t ru_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number, el_val_t gender);
el_val_t ru_decline_fem(el_val_t noun, el_val_t stype, el_val_t gram_case, el_val_t number); el_val_t ru_decline_fem(el_val_t noun, el_val_t stype, el_val_t gram_case, el_val_t number);
el_val_t ru_decline_masc(el_val_t noun, el_val_t stype, el_val_t gram_case, el_val_t number); el_val_t ru_decline_masc(el_val_t noun, el_val_t stype, el_val_t gram_case, el_val_t number);
el_val_t ru_decline_neut(el_val_t noun, el_val_t stype, el_val_t gram_case, el_val_t number); el_val_t ru_decline_neut(el_val_t noun, el_val_t stype, el_val_t gram_case, el_val_t number);
@@ -969,10 +899,8 @@ el_val_t ru_past_stem(el_val_t verb);
el_val_t ru_stem_type(el_val_t noun, el_val_t gender); el_val_t ru_stem_type(el_val_t noun, el_val_t gender);
el_val_t rule_id(el_val_t rule); el_val_t rule_id(el_val_t rule);
el_val_t rule_lhs(el_val_t rule); el_val_t rule_lhs(el_val_t rule);
el_val_t rule_rhs_len(el_val_t rule);
el_val_t rule_rhs(el_val_t rule, el_val_t idx); el_val_t rule_rhs(el_val_t rule, el_val_t idx);
el_val_t run_command_guard(el_val_t cmd, el_val_t root); el_val_t rule_rhs_len(el_val_t rule);
el_val_t run_command_is_readonly(el_val_t cmd);
el_val_t sa_as_future(el_val_t slot); el_val_t sa_as_future(el_val_t slot);
el_val_t sa_as_past(el_val_t slot); el_val_t sa_as_past(el_val_t slot);
el_val_t sa_as_present(el_val_t slot); el_val_t sa_as_present(el_val_t slot);
@@ -984,11 +912,11 @@ el_val_t sa_class1_future_ending(el_val_t slot);
el_val_t sa_class1_past_ending(el_val_t slot); el_val_t sa_class1_past_ending(el_val_t slot);
el_val_t sa_class1_present_ending(el_val_t slot); el_val_t sa_class1_present_ending(el_val_t slot);
el_val_t sa_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t sa_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t sa_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t sa_decline_a_stem_pl(el_val_t stem, el_val_t gram_case); el_val_t sa_decline_a_stem_pl(el_val_t stem, el_val_t gram_case);
el_val_t sa_decline_a_stem_sg(el_val_t stem, el_val_t gram_case); el_val_t sa_decline_a_stem_sg(el_val_t stem, el_val_t gram_case);
el_val_t sa_decline_aa_stem_pl(el_val_t stem, el_val_t gram_case); el_val_t sa_decline_aa_stem_pl(el_val_t stem, el_val_t gram_case);
el_val_t sa_decline_aa_stem_sg(el_val_t stem, el_val_t gram_case); el_val_t sa_decline_aa_stem_sg(el_val_t stem, el_val_t gram_case);
el_val_t sa_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t sa_drs_future(el_val_t slot); el_val_t sa_drs_future(el_val_t slot);
el_val_t sa_drs_past(el_val_t slot); el_val_t sa_drs_past(el_val_t slot);
el_val_t sa_drs_present(el_val_t slot); el_val_t sa_drs_present(el_val_t slot);
@@ -1008,67 +936,44 @@ el_val_t sa_str_ends(el_val_t s, el_val_t suf);
el_val_t sa_vad_future(el_val_t slot); el_val_t sa_vad_future(el_val_t slot);
el_val_t sa_vad_past(el_val_t slot); el_val_t sa_vad_past(el_val_t slot);
el_val_t sa_vad_present(el_val_t slot); el_val_t sa_vad_present(el_val_t slot);
el_val_t safety_abuse_phrases(void);
el_val_t safety_any_match(el_val_t text, el_val_t phrases_json);
el_val_t safety_augment_system(el_val_t system, el_val_t user_msg);
el_val_t safety_classify_hard_bell(el_val_t message);
el_val_t safety_contact_path(void);
el_val_t safety_count_match(el_val_t text, el_val_t phrases_json);
el_val_t safety_detect_bell_level(el_val_t message);
el_val_t safety_detect_positive_level(el_val_t message);
el_val_t safety_general_hard_phrases(void);
el_val_t safety_hard_directive(el_val_t hard_type);
el_val_t safety_log_bell(el_val_t level, el_val_t reason, el_val_t input_summary); el_val_t safety_log_bell(el_val_t level, el_val_t reason, el_val_t input_summary);
el_val_t safety_normalize(el_val_t message);
el_val_t safety_positive_phrases(void);
el_val_t safety_score_crisis(el_val_t input); el_val_t safety_score_crisis(el_val_t input);
el_val_t safety_score_danger(el_val_t input); el_val_t safety_score_danger(el_val_t input);
el_val_t safety_score_distress_history(el_val_t history); el_val_t safety_score_distress_history(el_val_t history);
el_val_t safety_score_harm(el_val_t input); el_val_t safety_score_harm(el_val_t input);
el_val_t safety_screen(el_val_t input, el_val_t history); el_val_t safety_screen(el_val_t input, el_val_t history);
el_val_t safety_self_harm_phrases(void);
el_val_t safety_soft_directive(void);
el_val_t safety_soft_phrases(void);
el_val_t safety_threat_score(el_val_t input, el_val_t history); el_val_t safety_threat_score(el_val_t input, el_val_t history);
el_val_t safety_threat_to_others_phrases(void);
el_val_t safety_validate(el_val_t output, el_val_t action); el_val_t safety_validate(el_val_t output, el_val_t action);
el_val_t scan_token(el_val_t s, el_val_t start); el_val_t scan_token(el_val_t s, el_val_t start);
el_val_t security_research_authorized(void); el_val_t security_research_authorized(void);
el_val_t seed_persona_from_env(void); el_val_t seed_persona_from_env(void);
el_val_t sem_first_modifier(el_val_t mods); el_val_t sem_first_modifier(el_val_t mods);
el_val_t sem_frame(el_val_t intent, el_val_t subject, el_val_t obj, el_val_t modifiers);
el_val_t sem_frame_lang(el_val_t intent, el_val_t subject, el_val_t obj, el_val_t modifiers, el_val_t lang_code); el_val_t sem_frame_lang(el_val_t intent, el_val_t subject, el_val_t obj, el_val_t modifiers, el_val_t lang_code);
el_val_t sem_frame_obj(el_val_t intent, el_val_t subject, el_val_t obj); el_val_t sem_frame_obj(el_val_t intent, el_val_t subject, el_val_t obj);
el_val_t sem_frame_simple(el_val_t intent, el_val_t subject); el_val_t sem_frame_simple(el_val_t intent, el_val_t subject);
el_val_t sem_frame(el_val_t intent, el_val_t subject, el_val_t obj, el_val_t modifiers);
el_val_t sem_get(el_val_t json, el_val_t key); el_val_t sem_get(el_val_t json, el_val_t key);
el_val_t sem_intent_to_realize(el_val_t intent);
el_val_t sem_intent(el_val_t frame); el_val_t sem_intent(el_val_t frame);
el_val_t sem_intent_to_realize(el_val_t intent);
el_val_t sem_lang(el_val_t frame); el_val_t sem_lang(el_val_t frame);
el_val_t sem_modifiers(el_val_t frame); el_val_t sem_modifiers(el_val_t frame);
el_val_t sem_object(el_val_t frame); el_val_t sem_object(el_val_t frame);
el_val_t sem_realize(el_val_t frame);
el_val_t sem_realize_full(el_val_t frame, el_val_t verb, el_val_t tense, el_val_t aspect); el_val_t sem_realize_full(el_val_t frame, el_val_t verb, el_val_t tense, el_val_t aspect);
el_val_t sem_realize_greet(el_val_t subject); el_val_t sem_realize_greet(el_val_t subject);
el_val_t sem_realize_lang(el_val_t frame, el_val_t lang_code); el_val_t sem_realize_lang(el_val_t frame, el_val_t lang_code);
el_val_t sem_realize(el_val_t frame);
el_val_t sem_subject(el_val_t frame); el_val_t sem_subject(el_val_t frame);
el_val_t sem_to_spec_full(el_val_t frame, el_val_t verb, el_val_t tense, el_val_t aspect);
el_val_t sem_to_spec(el_val_t frame); el_val_t sem_to_spec(el_val_t frame);
el_val_t sem_to_spec_full(el_val_t frame, el_val_t verb, el_val_t tense, el_val_t aspect);
el_val_t session_auto_title(el_val_t session_id, el_val_t first_message); el_val_t session_auto_title(el_val_t session_id, el_val_t first_message);
el_val_t session_create_cleanup(el_val_t session_id);
el_val_t session_create(el_val_t body); el_val_t session_create(el_val_t body);
el_val_t session_delete(el_val_t session_id); el_val_t session_delete(el_val_t session_id);
el_val_t session_exists(el_val_t session_id);
el_val_t session_get(el_val_t session_id); el_val_t session_get(el_val_t session_id);
el_val_t session_hist_load(el_val_t session_id); el_val_t session_hist_load(el_val_t session_id);
el_val_t session_hist_save(el_val_t session_id, el_val_t hist); el_val_t session_hist_save(el_val_t session_id, el_val_t hist);
el_val_t session_list(void); el_val_t session_list(void);
el_val_t session_make_content(el_val_t id, el_val_t title, el_val_t created_at, el_val_t updated_at, el_val_t folder); el_val_t session_make_content(el_val_t id, el_val_t title, el_val_t created_at, el_val_t updated_at, el_val_t folder);
el_val_t session_preload_bullets(el_val_t nodes, el_val_t max_bullets, el_val_t snip_len);
el_val_t session_search_entry(el_val_t node);
el_val_t session_search(el_val_t query); el_val_t session_search(el_val_t query);
el_val_t session_summary_autogenerate(el_val_t hist);
el_val_t session_summary_write_dated(el_val_t summary_text, el_val_t label);
el_val_t session_summary_write(el_val_t summary_text);
el_val_t session_title_from_message(el_val_t message); el_val_t session_title_from_message(el_val_t message);
el_val_t session_update_meta_timestamp(el_val_t session_id); el_val_t session_update_meta_timestamp(el_val_t session_id);
el_val_t session_update_patch(el_val_t session_id, el_val_t body); el_val_t session_update_patch(el_val_t session_id, el_val_t body);
@@ -1079,9 +984,9 @@ el_val_t sga_bith_past(el_val_t slot);
el_val_t sga_bith_present(el_val_t slot); el_val_t sga_bith_present(el_val_t slot);
el_val_t sga_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t sga_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t sga_copula_present(el_val_t slot); el_val_t sga_copula_present(el_val_t slot);
el_val_t sga_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t sga_decline_astem(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t sga_decline_astem(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t sga_decline_ostem(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t sga_decline_ostem(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t sga_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t sga_detect_gender(el_val_t noun); el_val_t sga_detect_gender(el_val_t noun);
el_val_t sga_drop(el_val_t s, el_val_t n); el_val_t sga_drop(el_val_t s, el_val_t n);
el_val_t sga_first(el_val_t s); el_val_t sga_first(el_val_t s);
@@ -1109,9 +1014,9 @@ el_val_t steward_session_check(el_val_t input, el_val_t session_id);
el_val_t steward_validate_imprint(el_val_t imprint_id, el_val_t tool_name); el_val_t steward_validate_imprint(el_val_t imprint_id, el_val_t tool_name);
el_val_t str_drop_last(el_val_t s, el_val_t n); el_val_t str_drop_last(el_val_t s, el_val_t n);
el_val_t str_ends(el_val_t s, el_val_t suf); el_val_t str_ends(el_val_t s, el_val_t suf);
el_val_t str_last_char(el_val_t s);
el_val_t str_last2(el_val_t s); el_val_t str_last2(el_val_t s);
el_val_t str_last3(el_val_t s); el_val_t str_last3(el_val_t s);
el_val_t str_last_char(el_val_t s);
el_val_t strengthen_chat_nodes(el_val_t activation_nodes); el_val_t strengthen_chat_nodes(el_val_t activation_nodes);
el_val_t strip_query(el_val_t path); el_val_t strip_query(el_val_t path);
el_val_t studio_tools_json(void); el_val_t studio_tools_json(void);
@@ -1138,8 +1043,8 @@ el_val_t sux_realize_sentence(el_val_t intent, el_val_t agent, el_val_t predicat
el_val_t sux_slot(el_val_t person, el_val_t number); el_val_t sux_slot(el_val_t person, el_val_t number);
el_val_t sux_str_drop_last(el_val_t s, el_val_t n); el_val_t sux_str_drop_last(el_val_t s, el_val_t n);
el_val_t sux_str_ends(el_val_t s, el_val_t suf); el_val_t sux_str_ends(el_val_t s, el_val_t suf);
el_val_t sux_str_last_char(el_val_t s);
el_val_t sux_str_last2(el_val_t s); el_val_t sux_str_last2(el_val_t s);
el_val_t sux_str_last_char(el_val_t s);
el_val_t sux_tum2_past(el_val_t slot); el_val_t sux_tum2_past(el_val_t slot);
el_val_t sux_tum2_present(el_val_t slot); el_val_t sux_tum2_present(el_val_t slot);
el_val_t sux_verb_chain(el_val_t agent, el_val_t verb, el_val_t patient, el_val_t tense); el_val_t sux_verb_chain(el_val_t agent, el_val_t verb, el_val_t patient, el_val_t tense);
@@ -1157,9 +1062,9 @@ el_val_t sw_noun_plural(el_val_t noun);
el_val_t sw_obj_prefix(el_val_t person, el_val_t number, el_val_t noun_class); el_val_t sw_obj_prefix(el_val_t person, el_val_t number, el_val_t noun_class);
el_val_t sw_str_drop_last(el_val_t s, el_val_t n); el_val_t sw_str_drop_last(el_val_t s, el_val_t n);
el_val_t sw_str_ends(el_val_t s, el_val_t suf); el_val_t sw_str_ends(el_val_t s, el_val_t suf);
el_val_t sw_str_first_char(el_val_t s);
el_val_t sw_str_first2(el_val_t s); el_val_t sw_str_first2(el_val_t s);
el_val_t sw_str_first3(el_val_t s); el_val_t sw_str_first3(el_val_t s);
el_val_t sw_str_first_char(el_val_t s);
el_val_t sw_str_last_char(el_val_t s); el_val_t sw_str_last_char(el_val_t s);
el_val_t sw_subj_prefix(el_val_t person, el_val_t number, el_val_t noun_class); el_val_t sw_subj_prefix(el_val_t person, el_val_t number, el_val_t noun_class);
el_val_t sw_tense_marker(el_val_t tense); el_val_t sw_tense_marker(el_val_t tense);
@@ -1173,13 +1078,10 @@ el_val_t threat_trajectory_check(el_val_t tool_name, el_val_t tool_input);
el_val_t tier_canonical(void); el_val_t tier_canonical(void);
el_val_t tier_episodic(void); el_val_t tier_episodic(void);
el_val_t tier_working(void); el_val_t tier_working(void);
el_val_t tombstone_node(el_val_t id);
el_val_t tombstoned_id_set(void);
el_val_t tool_auto_approved(el_val_t tool_name);
el_val_t txb_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t txb_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t txb_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t txb_decline_fem(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t txb_decline_fem(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t txb_decline_masc(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t txb_decline_masc(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t txb_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t txb_detect_gender(el_val_t noun); el_val_t txb_detect_gender(el_val_t noun);
el_val_t txb_drop(el_val_t s, el_val_t n); el_val_t txb_drop(el_val_t s, el_val_t n);
el_val_t txb_ends(el_val_t s, el_val_t suf); el_val_t txb_ends(el_val_t s, el_val_t suf);
@@ -1194,8 +1096,8 @@ el_val_t txb_wes_present(el_val_t slot);
el_val_t txb_ya_present(el_val_t slot); el_val_t txb_ya_present(el_val_t slot);
el_val_t uga_amr_imperfect(el_val_t slot); el_val_t uga_amr_imperfect(el_val_t slot);
el_val_t uga_amr_perfect(el_val_t slot); el_val_t uga_amr_perfect(el_val_t slot);
el_val_t uga_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t uga_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number); el_val_t uga_conjugate(el_val_t verb, el_val_t tense, el_val_t person, el_val_t number);
el_val_t uga_conjugate_copula(el_val_t tense, el_val_t slot);
el_val_t uga_decline(el_val_t noun, el_val_t gram_case, el_val_t number); el_val_t uga_decline(el_val_t noun, el_val_t gram_case, el_val_t number);
el_val_t uga_generic_imperfect(el_val_t base3sg, el_val_t slot); el_val_t uga_generic_imperfect(el_val_t base3sg, el_val_t slot);
el_val_t uga_generic_perfect(el_val_t base3sg, el_val_t slot); el_val_t uga_generic_perfect(el_val_t base3sg, el_val_t slot);
@@ -1210,8 +1112,8 @@ el_val_t uga_map_canonical(el_val_t verb);
el_val_t uga_noun_phrase(el_val_t noun, el_val_t gram_case, el_val_t number, el_val_t definite); el_val_t uga_noun_phrase(el_val_t noun, el_val_t gram_case, el_val_t number, el_val_t definite);
el_val_t uga_ray_imperfect(el_val_t slot); el_val_t uga_ray_imperfect(el_val_t slot);
el_val_t uga_ray_perfect(el_val_t slot); el_val_t uga_ray_perfect(el_val_t slot);
el_val_t uga_slot_g(el_val_t person, el_val_t gender, el_val_t number);
el_val_t uga_slot(el_val_t person, el_val_t number); el_val_t uga_slot(el_val_t person, el_val_t number);
el_val_t uga_slot_g(el_val_t person, el_val_t gender, el_val_t number);
el_val_t uga_str_drop_last(el_val_t s, el_val_t n); el_val_t uga_str_drop_last(el_val_t s, el_val_t n);
el_val_t uga_str_ends(el_val_t s, el_val_t suf); el_val_t uga_str_ends(el_val_t s, el_val_t suf);
el_val_t uga_str_len(el_val_t s); el_val_t uga_str_len(el_val_t s);
@@ -1219,6 +1121,7 @@ el_val_t uga_strip_nom(el_val_t noun);
el_val_t verb_form(el_val_t base, el_val_t tense, el_val_t person, el_val_t number); el_val_t verb_form(el_val_t base, el_val_t tense, el_val_t person, el_val_t number);
el_val_t vocab_by_class(el_val_t cls); el_val_t vocab_by_class(el_val_t cls);
el_val_t vocab_by_pos(el_val_t pos); el_val_t vocab_by_pos(el_val_t pos);
el_val_t vocab_lookup_en(el_val_t word);
el_val_t vocab_lookup(el_val_t word, el_val_t lang_code); el_val_t vocab_lookup(el_val_t word, el_val_t lang_code);
el_val_t vocab_lookup_en(el_val_t word);
el_val_t vocab_synonym(el_val_t word, el_val_t lang_register, el_val_t lang_code); el_val_t vocab_synonym(el_val_t word, el_val_t lang_register, el_val_t lang_code);
el_val_t xai_api_key(void);
Generated Vendored
+25003
View File
File diff suppressed because it is too large Load Diff
Generated Vendored
+5
View File
@@ -0,0 +1,5 @@
// auto-generated by elc --emit-header — do not edit
extern fn elp_extract_topic(msg: String) -> String
extern fn elp_detect_predicate(msg: String) -> String
extern fn elp_parse(msg: String) -> String
extern fn handle_elp_chat(body: String) -> String
Generated Vendored
+24028 -34
View File
File diff suppressed because it is too large Load Diff
Generated Vendored
+7
View File
@@ -0,0 +1,7 @@
// auto-generated by elc --emit-header — do not edit
extern fn sem_get(json: String, key: String) -> String
extern fn generate_frame(frame: Any) -> String
extern fn generate_frame_lang(frame: Any, lang_code: String) -> String
extern fn build_form_from_json(semantic_form_json: String, lang_code: String) -> Any
extern fn generate(semantic_form_json: String) -> String
extern fn generate_lang(semantic_form_json: String, lang_code: String) -> String
Generated Vendored
+5
View File
@@ -656,3 +656,8 @@ el_val_t generate_tree(el_val_t rule_id_str, el_val_t slots) {
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+38
View File
@@ -0,0 +1,38 @@
// auto-generated by elc --emit-header - do not edit
extern fn slots_get(slots: Any, key: String) -> String
extern fn slots_set(slots: Any, key: String, val: String) -> Any
extern fn make_slots(k0: String, v0: String) -> Any
extern fn make_slots2(k0: String, v0: String, k1: String, v1: String) -> Any
extern fn make_slots3(k0: String, v0: String, k1: String, v1: String, k2: String, v2: String) -> Any
extern fn make_slots4(k0: String, v0: String, k1: String, v1: String, k2: String, v2: String, k3: String, v3: String) -> Any
extern fn make_slots5(k0: String, v0: String, k1: String, v1: String, k2: String, v2: String, k3: String, v3: String, k4: String, v4: String) -> Any
extern fn rule_id(rule: Any) -> String
extern fn rule_lhs(rule: Any) -> String
extern fn rule_rhs_len(rule: Any) -> Int
extern fn rule_rhs(rule: Any, idx: Int) -> String
extern fn make_rule(id: String, lhs: String, r0: String) -> Any
extern fn make_rule2(id: String, lhs: String, r0: String, r1: String) -> Any
extern fn make_rule3(id: String, lhs: String, r0: String, r1: String, r2: String) -> Any
extern fn make_rule4(id: String, lhs: String, r0: String, r1: String, r2: String, r3: String) -> Any
extern fn build_rules() -> Any
extern fn get_rules() -> Any
extern fn find_rule(rule_id_str: String) -> Any
extern fn make_leaf(label: String, word: String) -> String
extern fn make_node1(label: String, child0: String) -> String
extern fn make_node2(label: String, child0: String, child1: String) -> String
extern fn make_node3(label: String, child0: String, child1: String, child2: String) -> String
extern fn make_node4(label: String, child0: String, child1: String, child2: String, child3: String) -> String
extern fn nlg_is_ws(c: String) -> Bool
extern fn skip_ws(s: String, pos: Int) -> Int
extern fn scan_token(s: String, start: Int) -> Any
extern fn render_tree(tree: String) -> String
extern fn gram_word_order(profile: Any) -> String
extern fn gram_order_constituents(subj: String, verb: String, obj: String, profile: Any) -> String
extern fn gram_build_vp(verb: String, aux: String, profile: Any) -> String
extern fn gram_question_strategy(profile: Any) -> String
extern fn is_pronoun(word: String) -> Bool
extern fn build_np(referent: String, slots: Any) -> String
extern fn build_pp(loc: String) -> String
extern fn build_vp_body(slots: Any) -> String
extern fn build_vp_from_slots(slots: Any) -> String
extern fn generate_tree(rule_id_str: String, slots: Any) -> String
Generated Vendored
+5
View File
@@ -70,3 +70,8 @@ el_val_t imprint_unload(void) {
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+7
View File
@@ -0,0 +1,7 @@
// auto-generated by elc --emit-header — do not edit
extern fn imprint_current() -> String
extern fn imprint_load(imprint_id: String) -> String
extern fn imprint_respond(input: String, imprint_id: String) -> String
extern fn imprint_surface_knowledge(query: String, imprint_id: String) -> String
extern fn imprint_surface_memory_read(query: String) -> String
extern fn imprint_unload() -> Void
Generated Vendored
+5
View File
@@ -392,3 +392,8 @@ el_val_t lang_code(el_val_t profile) {
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+46
View File
@@ -0,0 +1,46 @@
// auto-generated by elc --emit-header — do not edit
extern fn lang_profile(code: String, word_order: String, morph_type: String, has_case: String, has_gender: String, script_dir: String, agreement: String, null_subject: String) -> [String]
extern fn lang_get(profile: [String], key: String) -> String
extern fn lang_profile_en() -> [String]
extern fn lang_profile_ja() -> [String]
extern fn lang_profile_ar() -> [String]
extern fn lang_profile_zh() -> [String]
extern fn lang_profile_de() -> [String]
extern fn lang_profile_es() -> [String]
extern fn lang_profile_fi() -> [String]
extern fn lang_profile_sw() -> [String]
extern fn lang_profile_hi() -> [String]
extern fn lang_profile_ru() -> [String]
extern fn lang_profile_fr() -> [String]
extern fn lang_profile_la() -> [String]
extern fn lang_profile_he() -> [String]
extern fn lang_profile_sa() -> [String]
extern fn lang_profile_got() -> [String]
extern fn lang_profile_non() -> [String]
extern fn lang_profile_enm() -> [String]
extern fn lang_profile_pi() -> [String]
extern fn lang_profile_grc() -> [String]
extern fn lang_profile_ang() -> [String]
extern fn lang_profile_fro() -> [String]
extern fn lang_profile_goh() -> [String]
extern fn lang_profile_sga() -> [String]
extern fn lang_profile_txb() -> [String]
extern fn lang_profile_peo() -> [String]
extern fn lang_profile_akk() -> [String]
extern fn lang_profile_uga() -> [String]
extern fn lang_profile_egy() -> [String]
extern fn lang_profile_sux() -> [String]
extern fn lang_profile_gez() -> [String]
extern fn lang_profile_cop() -> [String]
extern fn lang_from_code(code: String) -> [String]
extern fn lang_default() -> [String]
extern fn lang_is_isolating(profile: [String]) -> Bool
extern fn lang_is_agglutinative(profile: [String]) -> Bool
extern fn lang_is_fusional(profile: [String]) -> Bool
extern fn lang_is_polysynthetic(profile: [String]) -> Bool
extern fn lang_is_rtl(profile: [String]) -> Bool
extern fn lang_has_null_subject(profile: [String]) -> Bool
extern fn lang_has_case(profile: [String]) -> Bool
extern fn lang_has_gender(profile: [String]) -> Bool
extern fn lang_word_order(profile: [String]) -> String
extern fn lang_code(profile: [String]) -> String
Generated Vendored
+13 -109
View File
@@ -10,7 +10,6 @@ el_val_t mem_remember(el_val_t content, el_val_t tags);
el_val_t mem_recall(el_val_t query, el_val_t depth); el_val_t mem_recall(el_val_t query, el_val_t depth);
el_val_t mem_search(el_val_t query, el_val_t limit); el_val_t mem_search(el_val_t query, el_val_t limit);
el_val_t mem_strengthen(el_val_t node_id); el_val_t mem_strengthen(el_val_t node_id);
el_val_t mem_tombstone(el_val_t node_id);
el_val_t mem_forget(el_val_t node_id); el_val_t mem_forget(el_val_t node_id);
el_val_t mem_consolidate(void); el_val_t mem_consolidate(void);
el_val_t mem_save(el_val_t path); el_val_t mem_save(el_val_t path);
@@ -35,18 +34,7 @@ el_val_t tier_canonical(void) {
} }
el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags) { el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags) {
el_val_t id = engram_node_full(content, EL_STR("Memory"), label, el_from_float(0.5), el_from_float(0.5), el_from_float(0.8), EL_STR("Working"), tags); return engram_node_full(content, EL_STR("Memory"), label, el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.8)), EL_STR("Working"), tags);
if (str_eq(id, EL_STR(""))) {
println(el_str_concat(EL_STR("[memory] write rejected by engram (empty id): label="), label));
return EL_STR("");
}
el_val_t readback = engram_get_node_json(id);
if (str_eq(readback, EL_STR("")) || str_eq(readback, EL_STR("{}"))) {
println(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("[memory] WRITE VERIFY FAILED: label="), label), EL_STR(" id=")), id), EL_STR(" \xe2\x80\x94 node absent after write")));
return EL_STR("");
}
println(el_str_concat(el_str_concat(EL_STR("[memory] write verified: "), id), EL_STR(" ok")));
return id;
return 0; return 0;
} }
@@ -70,60 +58,22 @@ el_val_t mem_strengthen(el_val_t node_id) {
return 0; return 0;
} }
el_val_t mem_tombstone(el_val_t node_id) {
el_val_t tags = EL_STR("[\"Tombstone\",\"status:deleted\"]");
el_val_t marker = engram_node_full(node_id, EL_STR("Tombstone"), el_str_concat(EL_STR("tombstone:"), node_id), el_from_float(0.01), el_from_float(0.01), el_from_float(1.0), EL_STR("Episodic"), tags);
if (!str_eq(marker, EL_STR(""))) {
engram_connect(marker, node_id, el_from_float(1.0), EL_STR("tombstones"));
}
return marker;
return 0;
}
el_val_t mem_forget(el_val_t node_id) { el_val_t mem_forget(el_val_t node_id) {
el_val_t _marker = mem_tombstone(node_id); engram_forget(node_id);
return 0; return 0;
} }
el_val_t mem_consolidate(void) { el_val_t mem_consolidate(void) {
el_val_t scanned = engram_node_count(); el_val_t scanned = engram_node_count();
el_val_t total_edges = engram_edge_count(); el_val_t dummy = engram_scan_nodes_json(100, 0);
el_val_t strengthened = 0;
el_val_t wm_top = engram_wm_top_json(10);
el_val_t wm_len = json_array_len(wm_top);
el_val_t wi = 0;
while (wi < wm_len) {
el_val_t wm_node = json_array_get(wm_top, wi);
el_val_t wm_id = json_get(wm_node, EL_STR("id"));
if (!str_eq(wm_id, EL_STR(""))) {
engram_strengthen(wm_id);
strengthened = (strengthened + 1);
}
wi = (wi + 1);
}
el_val_t scan_result = engram_scan_nodes_json(50, 0);
el_val_t scan_len = json_array_len(scan_result);
el_val_t si = 0;
while (si < scan_len) {
el_val_t s_node = json_array_get(scan_result, si);
el_val_t s_tier = json_get(s_node, EL_STR("tier"));
el_val_t s_id = json_get(s_node, EL_STR("id"));
if (str_eq(s_tier, EL_STR("Canonical")) && !str_eq(s_id, EL_STR(""))) {
engram_strengthen(s_id);
strengthened = (strengthened + 1);
}
si = (si + 1);
}
el_val_t total_nodes = engram_node_count(); el_val_t total_nodes = engram_node_count();
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"scanned\":"), int_to_str(scanned)), EL_STR(",\"total_nodes\":")), int_to_str(total_nodes)), EL_STR(",\"total_edges\":")), int_to_str(total_edges)), EL_STR(",\"strengthened\":")), int_to_str(strengthened)), EL_STR("}")); el_val_t total_edges = engram_edge_count();
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"scanned\":"), int_to_str(scanned)), EL_STR(",\"total_nodes\":")), int_to_str(total_nodes)), EL_STR(",\"total_edges\":")), int_to_str(total_edges)), EL_STR("}"));
return 0; return 0;
} }
el_val_t mem_save(el_val_t path) { el_val_t mem_save(el_val_t path) {
el_val_t saved = engram_save(path); engram_save(path);
if (saved == 0) {
println(el_str_concat(el_str_concat(EL_STR("[memory] mem_save: engram_save failed for "), path), EL_STR(" \xe2\x80\x94 snapshot may be incomplete")));
}
return 0; return 0;
} }
@@ -154,56 +104,9 @@ el_val_t mem_boot_count_get(void) {
el_val_t mem_boot_count_inc(void) { el_val_t mem_boot_count_inc(void) {
el_val_t current = mem_boot_count_get(); el_val_t current = mem_boot_count_get();
el_val_t next = (current + 1); el_val_t next = (current + 1);
el_val_t old_results = engram_search_json(EL_STR("soul:boot_count"), 50);
if (!str_eq(old_results, EL_STR("")) && !str_eq(old_results, EL_STR("[]"))) {
el_val_t old_len = json_array_len(old_results);
el_val_t oi = 0;
while (oi < old_len) {
el_val_t old_node = json_array_get(old_results, oi);
el_val_t old_id = json_get(old_node, EL_STR("id"));
if (!str_eq(old_id, EL_STR(""))) {
engram_forget(old_id);
}
oi = (oi + 1);
}
}
el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next)); el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next));
el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]"); el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]");
el_val_t boot_node_id = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(0.55), el_from_float(0.2), el_from_float(1.0), EL_STR("Working"), tags); el_val_t discard = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(1.0)), EL_STR("Canonical"), tags);
if (str_eq(boot_node_id, EL_STR(""))) {
println(el_str_concat(el_str_concat(EL_STR("[memory] mem_boot_count_inc: write rejected (empty id) \xe2\x80\x94 boot counter node lost (count="), int_to_str(next)), EL_STR(")")));
return next;
}
el_val_t boot_readback = engram_get_node_json(boot_node_id);
if (str_eq(boot_readback, EL_STR("")) || str_eq(boot_readback, EL_STR("{}"))) {
println(el_str_concat(el_str_concat(el_str_concat(EL_STR("[memory] mem_boot_count_inc: WRITE VERIFY FAILED id="), boot_node_id), EL_STR(" count=")), int_to_str(next)));
}
el_val_t wb_url = env(EL_STR("ENGRAM_URL"));
el_val_t wb_key = env(EL_STR("ENGRAM_API_KEY"));
if (!str_eq(wb_url, EL_STR("")) && !str_eq(wb_key, EL_STR(""))) {
el_val_t auth_body = el_str_concat(el_str_concat(EL_STR("{\"_auth\":\""), json_safe(wb_key)), EL_STR("\"}"));
el_val_t srv_old = http_get(el_str_concat(wb_url, EL_STR("/api/search?q=soul:boot_count&limit=20")));
if (!str_eq(srv_old, EL_STR("")) && !str_eq(srv_old, EL_STR("[]"))) {
el_val_t srv_len = json_array_len(srv_old);
el_val_t si = 0;
while (si < srv_len) {
el_val_t srv_node = json_array_get(srv_old, si);
el_val_t srv_content = json_get(srv_node, EL_STR("content"));
if (str_starts_with(srv_content, EL_STR("soul:boot_count:"))) {
el_val_t srv_id = json_get(srv_node, EL_STR("id"));
if (!str_eq(srv_id, EL_STR(""))) {
http_delete_json(el_str_concat(el_str_concat(wb_url, EL_STR("/api/nodes/")), srv_id), auth_body);
}
}
si = (si + 1);
}
}
el_val_t wb_body = el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"content\":\""), content), EL_STR("\",\"node_type\":\"Memory\",\"label\":\"soul:boot_count\",\"salience\":0.55,\"importance\":0.2,\"tier\":\"Working\",\"tags\":\"[\\\"soul-meta\\\",\\\"boot-counter\\\"]\",\"_auth\":\"")), json_safe(wb_key)), EL_STR("\"}"));
el_val_t wb_resp = http_post_json(el_str_concat(wb_url, EL_STR("/api/nodes")), wb_body);
if (str_contains(wb_resp, EL_STR("\"error\""))) {
println(el_str_concat(EL_STR("[memory] mem_boot_count_inc: HTTP write-back failed (count in-memory only): "), wb_resp));
}
}
return next; return next;
return 0; return 0;
} }
@@ -215,11 +118,12 @@ el_val_t mem_emit_state_event(el_val_t trigger, el_val_t kind, el_val_t content)
el_val_t safe_content = str_replace(content, EL_STR("\""), EL_STR("'")); el_val_t safe_content = str_replace(content, EL_STR("\""), EL_STR("'"));
el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"trigger\":\""), safe_trigger), EL_STR("\"")), EL_STR(",\"kind\":\"")), kind), EL_STR("\"")), EL_STR(",\"content\":\"")), safe_content), EL_STR("\"")), EL_STR(",\"boot\":")), int_to_str(boot)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}")); el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"trigger\":\""), safe_trigger), EL_STR("\"")), EL_STR(",\"kind\":\"")), kind), EL_STR("\"")), EL_STR(",\"content\":\"")), safe_content), EL_STR("\"")), EL_STR(",\"boot\":")), int_to_str(boot)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t tags = EL_STR("[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]"); el_val_t tags = EL_STR("[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]");
el_val_t event_id = engram_node_full(payload, EL_STR("InternalStateEvent"), el_str_concat(EL_STR("state-event:"), kind), el_from_float(0.85), el_from_float(0.8), el_from_float(0.9), EL_STR("Episodic"), tags); return engram_node_full(payload, EL_STR("InternalStateEvent"), el_str_concat(EL_STR("state-event:"), kind), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
if (str_eq(event_id, EL_STR(""))) { return 0;
println(el_str_concat(EL_STR("[memory] mem_emit_state_event: write rejected (empty id): kind="), kind)); }
}
return event_id; int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0; return 0;
} }
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
// auto-generated by elc --emit-header — do not edit
extern fn tier_working() -> String
extern fn tier_episodic() -> String
extern fn tier_canonical() -> String
extern fn mem_store(content: String, label: String, tags: String) -> String
extern fn mem_remember(content: String, tags: String) -> String
extern fn mem_recall(query: String, depth: Int) -> String
extern fn mem_search(query: String, limit: Int) -> String
extern fn mem_strengthen(node_id: String) -> Void
extern fn mem_forget(node_id: String) -> Void
extern fn mem_consolidate() -> String
extern fn mem_save(path: String) -> Void
extern fn mem_load(path: String) -> Void
extern fn mem_boot_count_get() -> Int
extern fn mem_boot_count_inc() -> Int
extern fn mem_emit_state_event(trigger: String, kind: String, content: String) -> String
Generated Vendored
+31
View File
@@ -0,0 +1,31 @@
// auto-generated by elc --emit-header — do not edit
extern fn akk_str_ends(s: String, suf: String) -> Bool
extern fn akk_str_len(s: String) -> Int
extern fn akk_str_drop_last(s: String, n: Int) -> String
extern fn akk_slot(person: String, number: String) -> Int
extern fn akk_slot_g(person: String, gender: String, number: String) -> Int
extern fn akk_copula_present(slot: Int) -> String
extern fn akk_copula_stative(slot: Int) -> String
extern fn akk_is_copula(verb: String) -> Bool
extern fn akk_conjugate_copula(tense: String, slot: Int) -> String
extern fn akk_alaku_present(slot: Int) -> String
extern fn akk_alaku_perfect(slot: Int) -> String
extern fn akk_amaru_present(slot: Int) -> String
extern fn akk_amaru_perfect(slot: Int) -> String
extern fn akk_amaru_stative(slot: Int) -> String
extern fn akk_qabu_present(slot: Int) -> String
extern fn akk_qabu_perfect(slot: Int) -> String
extern fn akk_qabu_stative(slot: Int) -> String
extern fn akk_epesu_present(slot: Int) -> String
extern fn akk_epesu_perfect(slot: Int) -> String
extern fn akk_epesu_stative(slot: Int) -> String
extern fn akk_regular_present(stem: String, slot: Int) -> String
extern fn akk_regular_perfect(stem: String, slot: Int) -> String
extern fn akk_regular_stative(stem: String, slot: Int) -> String
extern fn akk_known_verb(verb: String, tense: String, slot: Int) -> String
extern fn akk_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn akk_strip_nom(noun: String) -> String
extern fn akk_is_fem(noun: String) -> Bool
extern fn akk_decline(noun: String, gram_case: String, number: String) -> String
extern fn akk_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
extern fn akk_map_canonical(verb: String) -> String
Generated Vendored
+44
View File
@@ -0,0 +1,44 @@
// auto-generated by elc --emit-header — do not edit
extern fn ang_str_ends(s: String, suf: String) -> Bool
extern fn ang_str_drop_last(s: String, n: Int) -> String
extern fn ang_str_last_char(s: String) -> String
extern fn ang_str_last2(s: String) -> String
extern fn ang_slot(person: String, number: String) -> Int
extern fn ang_map_canonical(verb: String) -> String
extern fn ang_wesan_past(slot: Int) -> String
extern fn ang_beon_present(slot: Int) -> String
extern fn ang_wesan_present(slot: Int) -> String
extern fn ang_habban_present(slot: Int) -> String
extern fn ang_habban_past(slot: Int) -> String
extern fn ang_gan_present(slot: Int) -> String
extern fn ang_gan_past(slot: Int) -> String
extern fn ang_cuman_present(slot: Int) -> String
extern fn ang_cuman_past(slot: Int) -> String
extern fn ang_secgan_present(slot: Int) -> String
extern fn ang_secgan_past(slot: Int) -> String
extern fn ang_seon_present(slot: Int) -> String
extern fn ang_seon_past(slot: Int) -> String
extern fn ang_don_present(slot: Int) -> String
extern fn ang_don_past(slot: Int) -> String
extern fn ang_willan_present(slot: Int) -> String
extern fn ang_willan_past(slot: Int) -> String
extern fn ang_magan_present(slot: Int) -> String
extern fn ang_magan_past(slot: Int) -> String
extern fn ang_witan_present(slot: Int) -> String
extern fn ang_witan_past(slot: Int) -> String
extern fn ang_weak_present_ending(slot: Int) -> String
extern fn ang_weak_past_stem(stem: String) -> String
extern fn ang_weak_past(stem: String, slot: Int) -> String
extern fn ang_weak_stem(verb: String) -> String
extern fn ang_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn ang_declension(noun: String, gender: String) -> String
extern fn ang_decline_strong_masc(noun: String, gram_case: String, number: String) -> String
extern fn ang_decline_strong_neut(noun: String, gram_case: String, number: String) -> String
extern fn ang_decline_weak(noun: String, gram_case: String, number: String) -> String
extern fn ang_decline(noun: String, gram_case: String, number: String, gender: String) -> String
extern fn ang_article_masculine(gram_case: String, number: String) -> String
extern fn ang_article_feminine(gram_case: String, number: String) -> String
extern fn ang_article_neuter(gram_case: String, number: String) -> String
extern fn ang_article(gender: String, gram_case: String, number: String) -> String
extern fn ang_infer_gender(noun: String) -> String
extern fn ang_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+27
View File
@@ -0,0 +1,27 @@
// auto-generated by elc --emit-header — do not edit
extern fn ar_str_ends(s: String, suf: String) -> Bool
extern fn ar_str_len(s: String) -> Int
extern fn ar_str_drop_last(s: String, n: Int) -> String
extern fn ar_str_last_char(s: String) -> String
extern fn ar_slot(person: String, gender: String, number: String) -> Int
extern fn ar_perfect_suffix(slot: Int) -> String
extern fn ar_imperfect_prefix(slot: Int) -> String
extern fn ar_imperfect_suffix(slot: Int) -> String
extern fn ar_conjugate_form1(past_base: String, present_stem: String, tense: String, slot: Int) -> String
extern fn ar_irregular_kaana(slot: Int, tense: String) -> String
extern fn ar_irregular_qaala(slot: Int, tense: String) -> String
extern fn ar_irregular_jaa(slot: Int, tense: String) -> String
extern fn ar_irregular_raaa(slot: Int, tense: String) -> String
extern fn ar_irregular_araada(slot: Int, tense: String) -> String
extern fn ar_irregular_istata(slot: Int, tense: String) -> String
extern fn ar_irregular(verb: String, tense: String, slot: Int) -> String
extern fn ar_present_stem(verb: String) -> String
extern fn ar_conjugate(verb: String, tense: String, person: String, gender: String, number: String) -> String
extern fn ar_is_sun_letter(c: String) -> Bool
extern fn ar_definite_article(noun: String) -> String
extern fn ar_case_ending(kase: String, definite: String) -> String
extern fn ar_gender(noun: String) -> String
extern fn ar_masc_pl_ending(kase: String) -> String
extern fn ar_sound_plural(noun: String, gender: String) -> String
extern fn ar_noun_form(noun: String, gender: String, kase: String, number: String, definite: String) -> String
extern fn ar_verb_form(verb: String, tense: String, person: String, number: String) -> String
Generated Vendored
+35
View File
@@ -0,0 +1,35 @@
// auto-generated by elc --emit-header — do not edit
extern fn cop_str_ends(s: String, suf: String) -> Bool
extern fn cop_str_len(s: String) -> Int
extern fn cop_drop(s: String, n: Int) -> String
extern fn cop_last_char(s: String) -> String
extern fn cop_slot(person: String, number: String) -> Int
extern fn cop_subject_prefix(person: String, number: String) -> String
extern fn cop_subject_prefix_gendered(person: String, gender: String, number: String) -> String
extern fn cop_copula_particle(gender: String, number: String) -> String
extern fn cop_shwpe_present(prefix: String) -> String
extern fn cop_shwpe_perfect(prefix: String) -> String
extern fn cop_shwpe_future(prefix: String) -> String
extern fn cop_bwk_present(prefix: String) -> String
extern fn cop_bwk_perfect(prefix: String) -> String
extern fn cop_bwk_future(prefix: String) -> String
extern fn cop_nau_present(prefix: String) -> String
extern fn cop_nau_perfect(prefix: String) -> String
extern fn cop_nau_future(prefix: String) -> String
extern fn cop_jw_present(prefix: String) -> String
extern fn cop_jw_perfect(prefix: String) -> String
extern fn cop_jw_future(prefix: String) -> String
extern fn cop_di_present(prefix: String) -> String
extern fn cop_di_perfect(prefix: String) -> String
extern fn cop_di_future(prefix: String) -> String
extern fn cop_is_copula(verb: String) -> Bool
extern fn cop_known_verb_prefixed(verb: String, tense: String, prefix: String) -> String
extern fn cop_regular_present(prefix: String, stem: String) -> String
extern fn cop_regular_perfect(prefix: String, stem: String) -> String
extern fn cop_regular_future(prefix: String, stem: String) -> String
extern fn cop_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn cop_article(gender: String, number: String, definite: String) -> String
extern fn cop_decline(noun: String, gram_case: String, number: String) -> String
extern fn cop_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
extern fn cop_noun_phrase_gendered(noun: String, gram_case: String, number: String, definite: String, gender: String) -> String
extern fn cop_map_canonical(verb: String) -> String
Generated Vendored
+13
View File
@@ -0,0 +1,13 @@
// auto-generated by elc --emit-header — do not edit
extern fn de_article_def(gender: String, gram_case: String, number: String) -> String
extern fn de_article_indef(gender: String, gram_case: String, number: String) -> String
extern fn de_article(gender: String, gram_case: String, number: String, definite: String) -> String
extern fn de_adj_ending(gender: String, gram_case: String, number: String, article_type: String) -> String
extern fn de_noun_plural(noun: String, gender: String) -> String
extern fn de_case_ending(noun: String, gender: String, gram_case: String, number: String) -> String
extern fn de_conjugate_weak(stem: String, tense: String, person: String, number: String) -> String
extern fn de_irregular_present(verb: String, person: String, number: String) -> String
extern fn de_strong_past_stem(verb: String) -> String
extern fn de_norm_number(number: String) -> String
extern fn de_norm_person(person: String) -> String
extern fn de_conjugate(verb: String, tense: String, person: String, number: String) -> String
Generated Vendored
+38
View File
@@ -0,0 +1,38 @@
// auto-generated by elc --emit-header — do not edit
extern fn egy_str_ends(s: String, suf: String) -> Bool
extern fn egy_str_len(s: String) -> Int
extern fn egy_drop(s: String, n: Int) -> String
extern fn egy_last_char(s: String) -> String
extern fn egy_slot(person: String, number: String) -> Int
extern fn egy_slot_with_gender(person: String, gender: String, number: String) -> Int
extern fn egy_conjugate_pronoun(person: String, number: String) -> String
extern fn egy_suffix_pronoun(slot: Int) -> String
extern fn egy_is_copula(verb: String) -> Bool
extern fn egy_conjugate_copula(tense: String, slot: Int) -> String
extern fn egy_rdi_present(slot: Int) -> String
extern fn egy_rdi_past(slot: Int) -> String
extern fn egy_rdi_future(slot: Int) -> String
extern fn egy_mAA_present(slot: Int) -> String
extern fn egy_mAA_past(slot: Int) -> String
extern fn egy_mAA_future(slot: Int) -> String
extern fn egy_Dd_present(slot: Int) -> String
extern fn egy_Dd_past(slot: Int) -> String
extern fn egy_Dd_future(slot: Int) -> String
extern fn egy_Sm_present(slot: Int) -> String
extern fn egy_Sm_past(slot: Int) -> String
extern fn egy_Sm_future(slot: Int) -> String
extern fn egy_iri_present(slot: Int) -> String
extern fn egy_iri_past(slot: Int) -> String
extern fn egy_iri_future(slot: Int) -> String
extern fn egy_sdm_present(slot: Int) -> String
extern fn egy_sdm_past(slot: Int) -> String
extern fn egy_sdm_future(slot: Int) -> String
extern fn egy_known_verb(verb: String, tense: String, slot: Int) -> String
extern fn egy_regular_present(stem: String, slot: Int) -> String
extern fn egy_regular_past(stem: String, slot: Int) -> String
extern fn egy_regular_future(stem: String, slot: Int) -> String
extern fn egy_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn egy_decline(noun: String, gram_case: String, number: String) -> String
extern fn egy_fem(noun: String) -> String
extern fn egy_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
extern fn egy_map_canonical(verb: String) -> String
Generated Vendored
+30
View File
@@ -0,0 +1,30 @@
// auto-generated by elc --emit-header — do not edit
extern fn enm_str_ends(s: String, suf: String) -> Bool
extern fn enm_drop(s: String, n: Int) -> String
extern fn enm_first_char(s: String) -> String
extern fn enm_slot(person: String, number: String) -> Int
extern fn enm_been_present(slot: Int) -> String
extern fn enm_been_past(slot: Int) -> String
extern fn enm_haven_present(slot: Int) -> String
extern fn enm_haven_past(slot: Int) -> String
extern fn enm_goon_present(slot: Int) -> String
extern fn enm_goon_past(slot: Int) -> String
extern fn enm_seen_present(slot: Int) -> String
extern fn enm_seen_past(slot: Int) -> String
extern fn enm_seyen_present(slot: Int) -> String
extern fn enm_seyen_past(slot: Int) -> String
extern fn enm_comen_present(slot: Int) -> String
extern fn enm_comen_past(slot: Int) -> String
extern fn enm_maken_present(slot: Int) -> String
extern fn enm_maken_past(slot: Int) -> String
extern fn enm_map_canonical(verb: String) -> String
extern fn enm_weak_stem(verb: String) -> String
extern fn enm_weak_present(stem: String, slot: Int) -> String
extern fn enm_weak_past(stem: String, slot: Int) -> String
extern fn enm_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn enm_irregular_plural(noun: String) -> String
extern fn enm_make_plural(noun: String) -> String
extern fn enm_decline(noun: String, gram_case: String, number: String) -> String
extern fn enm_is_vowel_initial(s: String) -> Bool
extern fn enm_indef_article(noun_phrase: String) -> String
extern fn enm_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+23
View File
@@ -0,0 +1,23 @@
// auto-generated by elc --emit-header — do not edit
extern fn es_str_ends(s: String, suf: String) -> Bool
extern fn es_str_drop_last(s: String, n: Int) -> String
extern fn es_str_last_char(s: String) -> String
extern fn es_str_last2(s: String) -> String
extern fn es_str_last3(s: String) -> String
extern fn es_verb_class(base: String) -> String
extern fn es_stem(base: String) -> String
extern fn es_slot(person: String, number: String) -> Int
extern fn es_irregular_present(verb: String, person: String, number: String) -> String
extern fn es_irregular_preterite(verb: String, person: String, number: String) -> String
extern fn es_irregular_imperfect(verb: String, person: String, number: String) -> String
extern fn es_regular_present(stem: String, vclass: String, slot: Int) -> String
extern fn es_regular_preterite(stem: String, vclass: String, slot: Int) -> String
extern fn es_regular_future(base: String, slot: Int) -> String
extern fn es_irregular_future_stem(verb: String) -> String
extern fn es_regular_imperfect(stem: String, vclass: String, slot: Int) -> String
extern fn es_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn es_gender(noun: String) -> String
extern fn es_invariant_plural(noun: String) -> String
extern fn es_pluralize(noun: String) -> String
extern fn es_starts_with_stressed_a(noun: String) -> Bool
extern fn es_agree_article(noun: String, definite: String, number: String) -> String
Generated Vendored
+17
View File
@@ -0,0 +1,17 @@
// auto-generated by elc --emit-header — do not edit
extern fn fi_harmony(word: String) -> String
extern fn fi_suffix(base: String, harmony: String) -> String
extern fn fi_noun_case(stem: String, gram_case: String, number: String, harmony: String) -> String
extern fn fi_str_last_char(s: String) -> String
extern fn fi_apply_case(noun: String, gram_case: String, number: String) -> String
extern fn fi_verb_stem(dict_form: String) -> String
extern fn fi_irregular_verb(dict_form: String) -> [String]
extern fn fi_present_ending(stem: String, person: String, number: String, harmony: String) -> String
extern fn fi_past_stem(stem: String) -> String
extern fn fi_past_ending(stem: String, person: String, number: String, harmony: String) -> String
extern fn fi_neg_aux(person: String, number: String) -> String
extern fn fi_negative(verb: String, person: String, number: String) -> String
extern fn fi_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn fi_question_suffix(harmony: String) -> String
extern fn fi_make_question(verb_form: String, harmony: String) -> String
extern fn fi_full_paradigm(noun: String) -> [String]
Generated Vendored
+29
View File
@@ -0,0 +1,29 @@
// auto-generated by elc --emit-header — do not edit
extern fn fr_str_ends(s: String, suf: String) -> Bool
extern fn fr_str_drop_last(s: String, n: Int) -> String
extern fn fr_str_last_char(s: String) -> String
extern fn fr_str_last2(s: String) -> String
extern fn fr_is_vowel_start(s: String) -> Bool
extern fn fr_is_known_irregular(verb: String) -> Bool
extern fn fr_verb_group(base: String) -> String
extern fn fr_stem(base: String) -> String
extern fn fr_slot(person: String, number: String) -> Int
extern fn fr_irregular_present(verb: String, person: String, number: String) -> String
extern fn fr_regular_present(stem: String, vgroup: String, slot: Int) -> String
extern fn fr_future_stem(base: String, vgroup: String) -> String
extern fn fr_regular_future(fstem: String, slot: Int) -> String
extern fn fr_irregular_future_stem(verb: String) -> String
extern fn fr_imperfect_stem(base: String, vgroup: String) -> String
extern fn fr_regular_imperfect(istem: String, slot: Int) -> String
extern fn fr_uses_etre(verb: String) -> Bool
extern fn fr_past_participle(verb: String) -> String
extern fn fr_avoir_present(slot: Int) -> String
extern fn fr_etre_present(slot: Int) -> String
extern fn fr_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn fr_gender(noun: String) -> String
extern fn fr_invariant_plural(noun: String) -> String
extern fn fr_pluralize(noun: String) -> String
extern fn fr_agree_article(noun: String, definite: String, number: String) -> String
extern fn fr_subject_starts_vowel(subject: String) -> Bool
extern fn fr_verb_ends_vowel(verb_form: String) -> Bool
extern fn fr_question_inversion(subject: String, verb_form: String) -> String
Generated Vendored
+38
View File
@@ -0,0 +1,38 @@
// auto-generated by elc --emit-header — do not edit
extern fn fro_str_ends(s: String, suf: String) -> Bool
extern fn fro_drop(s: String, n: Int) -> String
extern fn fro_slot(person: String, number: String) -> Int
extern fn fro_map_canonical(verb: String) -> String
extern fn fro_estre_present(slot: Int) -> String
extern fn fro_estre_past(slot: Int) -> String
extern fn fro_estre_future(slot: Int) -> String
extern fn fro_avoir_present(slot: Int) -> String
extern fn fro_avoir_past(slot: Int) -> String
extern fn fro_avoir_future(slot: Int) -> String
extern fn fro_aler_present(slot: Int) -> String
extern fn fro_aler_past(slot: Int) -> String
extern fn fro_aler_future(slot: Int) -> String
extern fn fro_venir_present(slot: Int) -> String
extern fn fro_venir_past(slot: Int) -> String
extern fn fro_venir_future(slot: Int) -> String
extern fn fro_faire_present(slot: Int) -> String
extern fn fro_faire_past(slot: Int) -> String
extern fn fro_faire_future(slot: Int) -> String
extern fn fro_verb_class(verb: String) -> String
extern fn fro_verb_stem(verb: String, vclass: String) -> String
extern fn fro_conj1_present(stem: String, slot: Int) -> String
extern fn fro_conj1_past(stem: String, slot: Int) -> String
extern fn fro_conj1_future(verb: String, slot: Int) -> String
extern fn fro_conj2_present(stem: String, slot: Int) -> String
extern fn fro_conj2_past(stem: String, slot: Int) -> String
extern fn fro_conj2_future(verb: String, slot: Int) -> String
extern fn fro_conj3_present(stem: String, slot: Int) -> String
extern fn fro_conj3_past(stem: String, slot: Int) -> String
extern fn fro_conj3_future(verb: String, slot: Int) -> String
extern fn fro_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn fro_gender(noun: String) -> String
extern fn fro_decline_masc(noun: String, gram_case: String, number: String) -> String
extern fn fro_decline_fem(noun: String, number: String) -> String
extern fn fro_decline(noun: String, gram_case: String, number: String) -> String
extern fn fro_article(gender: String, gram_case: String, number: String) -> String
extern fn fro_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+26
View File
@@ -0,0 +1,26 @@
// auto-generated by elc --emit-header — do not edit
extern fn gez_str_ends(s: String, suf: String) -> Bool
extern fn gez_str_len(s: String) -> Int
extern fn gez_str_drop_last(s: String, n: Int) -> String
extern fn gez_slot(person: String, number: String) -> Int
extern fn gez_slot_g(person: String, gender: String, number: String) -> Int
extern fn gez_kwn_perfect(slot: Int) -> String
extern fn gez_kwn_imperfect(slot: Int) -> String
extern fn gez_is_copula(verb: String) -> Bool
extern fn gez_conjugate_copula(tense: String, slot: Int) -> String
extern fn gez_hlw_perfect(slot: Int) -> String
extern fn gez_hlw_imperfect(slot: Int) -> String
extern fn gez_hbl_perfect(slot: Int) -> String
extern fn gez_hbl_imperfect(slot: Int) -> String
extern fn gez_ray_perfect(slot: Int) -> String
extern fn gez_ray_imperfect(slot: Int) -> String
extern fn gez_qwl_perfect(slot: Int) -> String
extern fn gez_qwl_imperfect(slot: Int) -> String
extern fn gez_generic_perfect(base3sg: String, slot: Int) -> String
extern fn gez_generic_imperfect(base3sg: String, slot: Int) -> String
extern fn gez_known_verb(verb: String, tense: String, slot: Int) -> String
extern fn gez_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn gez_is_fidel(noun: String) -> Bool
extern fn gez_decline(noun: String, gram_case: String, number: String) -> String
extern fn gez_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
extern fn gez_map_canonical(verb: String) -> String
Generated Vendored
+34
View File
@@ -0,0 +1,34 @@
// auto-generated by elc --emit-header — do not edit
extern fn goh_str_ends(s: String, suf: String) -> Bool
extern fn goh_drop(s: String, n: Int) -> String
extern fn goh_slot(person: String, number: String) -> Int
extern fn goh_map_canonical(verb: String) -> String
extern fn goh_wesan_present(slot: Int) -> String
extern fn goh_wesan_past(slot: Int) -> String
extern fn goh_haben_present(slot: Int) -> String
extern fn goh_haben_past(slot: Int) -> String
extern fn goh_gan_present(slot: Int) -> String
extern fn goh_gan_past(slot: Int) -> String
extern fn goh_sehan_present(slot: Int) -> String
extern fn goh_sehan_past(slot: Int) -> String
extern fn goh_quethan_present(slot: Int) -> String
extern fn goh_quethan_past(slot: Int) -> String
extern fn goh_tuon_present(slot: Int) -> String
extern fn goh_tuon_past(slot: Int) -> String
extern fn goh_weak_present(stem: String, slot: Int) -> String
extern fn goh_weak_past(stem: String, slot: Int) -> String
extern fn goh_verb_stem(verb: String) -> String
extern fn goh_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn goh_stem_type(noun: String) -> String
extern fn goh_extract_stem(noun: String, stype: String) -> String
extern fn goh_decline_masc_a_sg(stem: String, gram_case: String) -> String
extern fn goh_decline_masc_a_pl(stem: String, gram_case: String) -> String
extern fn goh_decline_fem_o_sg(stem: String, gram_case: String) -> String
extern fn goh_decline_fem_o_pl(stem: String, gram_case: String) -> String
extern fn goh_decline_neut_a_sg(stem: String, gram_case: String) -> String
extern fn goh_decline_neut_a_pl(stem: String, gram_case: String) -> String
extern fn goh_decline_masc_n_sg(stem: String, gram_case: String) -> String
extern fn goh_decline_masc_n_pl(stem: String, gram_case: String) -> String
extern fn goh_decline(noun: String, gram_case: String, number: String) -> String
extern fn goh_demo_article(stype: String, number: String) -> String
extern fn goh_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+37
View File
@@ -0,0 +1,37 @@
// auto-generated by elc --emit-header — do not edit
extern fn got_str_ends(s: String, suf: String) -> Bool
extern fn got_str_drop_last(s: String, n: Int) -> String
extern fn got_slot(person: String, number: String) -> Int
extern fn got_map_canonical(verb: String) -> String
extern fn got_wisan_present(slot: Int) -> String
extern fn got_wisan_past(slot: Int) -> String
extern fn got_haban_present(slot: Int) -> String
extern fn got_haban_past(slot: Int) -> String
extern fn got_gaggan_present(slot: Int) -> String
extern fn got_gaggan_past(slot: Int) -> String
extern fn got_saihwan_present(slot: Int) -> String
extern fn got_saihwan_past(slot: Int) -> String
extern fn got_qithan_present(slot: Int) -> String
extern fn got_qithan_past(slot: Int) -> String
extern fn got_niman_present(slot: Int) -> String
extern fn got_niman_past(slot: Int) -> String
extern fn got_wk1_present_ending(slot: Int) -> String
extern fn got_wk1_past_ending(slot: Int) -> String
extern fn got_wk1_conjugate(stem: String, tense: String, slot: Int) -> String
extern fn got_wk2_present_ending(slot: Int) -> String
extern fn got_wk2_past_ending(slot: Int) -> String
extern fn got_wk2_conjugate(stem: String, tense: String, slot: Int) -> String
extern fn got_verb_class(verb: String) -> String
extern fn got_verb_stem(verb: String, vclass: String) -> String
extern fn got_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn got_decline_a_stem_sg(stem: String, gram_case: String) -> String
extern fn got_decline_a_stem_pl(stem: String, gram_case: String) -> String
extern fn got_decline_o_stem_sg(stem: String, gram_case: String) -> String
extern fn got_decline_o_stem_pl(stem: String, gram_case: String) -> String
extern fn got_decline_n_stem_sg(stem: String, gram_case: String) -> String
extern fn got_decline_n_stem_pl(stem: String, gram_case: String) -> String
extern fn got_stem_type(noun: String) -> String
extern fn got_extract_stem(noun: String, stype: String) -> String
extern fn got_demo_article(stype: String) -> String
extern fn got_decline(noun: String, gram_case: String, number: String) -> String
extern fn got_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+45
View File
@@ -0,0 +1,45 @@
// auto-generated by elc --emit-header — do not edit
extern fn grc_str_ends(s: String, suf: String) -> Bool
extern fn grc_str_drop_last(s: String, n: Int) -> String
extern fn grc_str_last_char(s: String) -> String
extern fn grc_str_last2(s: String) -> String
extern fn grc_str_last3(s: String) -> String
extern fn grc_slot(person: String, number: String) -> Int
extern fn grc_map_canonical(verb: String) -> String
extern fn grc_einai_present(slot: Int) -> String
extern fn grc_einai_imperfect(slot: Int) -> String
extern fn grc_einai_future(slot: Int) -> String
extern fn grc_echein_present(slot: Int) -> String
extern fn grc_echein_imperfect(slot: Int) -> String
extern fn grc_echein_aorist(slot: Int) -> String
extern fn grc_echein_future(slot: Int) -> String
extern fn grc_legein_present(slot: Int) -> String
extern fn grc_legein_imperfect(slot: Int) -> String
extern fn grc_legein_aorist(slot: Int) -> String
extern fn grc_legein_future(slot: Int) -> String
extern fn grc_horao_present(slot: Int) -> String
extern fn grc_horao_imperfect(slot: Int) -> String
extern fn grc_horao_aorist(slot: Int) -> String
extern fn grc_horao_future(slot: Int) -> String
extern fn grc_erchesthai_present(slot: Int) -> String
extern fn grc_erchesthai_imperfect(slot: Int) -> String
extern fn grc_erchesthai_aorist(slot: Int) -> String
extern fn grc_erchesthai_future(slot: Int) -> String
extern fn grc_thematic_present_ending(slot: Int) -> String
extern fn grc_thematic_imperfect_ending(slot: Int) -> String
extern fn grc_thematic_future_ending(slot: Int) -> String
extern fn grc_weak_aorist_ending(slot: Int) -> String
extern fn grc_present_stem(verb: String) -> String
extern fn grc_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn grc_declension(noun: String) -> String
extern fn grc_decline_2m(stem: String, gram_case: String, number: String) -> String
extern fn grc_decline_2n(stem: String, gram_case: String, number: String) -> String
extern fn grc_decline_1a(stem: String, gram_case: String, number: String) -> String
extern fn grc_decline_1e(stem: String, gram_case: String, number: String) -> String
extern fn grc_decline(noun: String, gram_case: String, number: String) -> String
extern fn grc_article_masculine(gram_case: String, number: String) -> String
extern fn grc_article_feminine(gram_case: String, number: String) -> String
extern fn grc_article_neuter(gram_case: String, number: String) -> String
extern fn grc_article(gender: String, gram_case: String, number: String) -> String
extern fn grc_infer_gender(noun: String) -> String
extern fn grc_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+30
View File
@@ -0,0 +1,30 @@
// auto-generated by elc --emit-header — do not edit
extern fn he_str_ends(s: String, suf: String) -> Bool
extern fn he_str_len(s: String) -> Int
extern fn he_str_drop_last(s: String, n: Int) -> String
extern fn he_str_last_char(s: String) -> String
extern fn he_slot(person: String, gender: String, number: String) -> Int
extern fn he_present_form_code(slot: Int) -> Int
extern fn he_copula_past(slot: Int) -> String
extern fn he_copula_future(slot: Int) -> String
extern fn he_is_copula(verb: String) -> Bool
extern fn he_conjugate_copula(tense: String, slot: Int) -> String
extern fn he_present_lir_ot(form: Int) -> String
extern fn he_present_le_exol(form: Int) -> String
extern fn he_present_ledaber(form: Int) -> String
extern fn he_present_lalechet(form: Int) -> String
extern fn he_past_lir_ot(slot: Int) -> String
extern fn he_past_le_exol(slot: Int) -> String
extern fn he_past_ledaber(slot: Int) -> String
extern fn he_past_lalechet(slot: Int) -> String
extern fn he_future_lir_ot(slot: Int) -> String
extern fn he_future_le_exol(slot: Int) -> String
extern fn he_future_ledaber(slot: Int) -> String
extern fn he_future_lalechet(slot: Int) -> String
extern fn he_known_verb(verb: String, tense: String, slot: Int) -> String
extern fn he_conjugate(verb: String, tense: String, person: String, gender: String, number: String) -> String
extern fn he_pluralize(noun: String, gender: String) -> String
extern fn he_is_hebrew_script(noun: String) -> Bool
extern fn he_definite_prefix(noun: String) -> String
extern fn he_noun_phrase(noun: String, number: String, gender: String, definite: String) -> String
extern fn he_map_canonical(verb: String) -> String
Generated Vendored
+27
View File
@@ -0,0 +1,27 @@
// auto-generated by elc --emit-header — do not edit
extern fn hi_str_ends(s: String, suf: String) -> Bool
extern fn hi_str_drop_last(s: String, n: Int) -> String
extern fn hi_str_last_char(s: String) -> String
extern fn hi_gender(noun: String) -> String
extern fn hi_masc_aa_stem(noun: String) -> String
extern fn hi_noun_direct_m(noun: String, number: String) -> String
extern fn hi_noun_oblique_m(noun: String, number: String) -> String
extern fn hi_noun_direct_f(noun: String, number: String) -> String
extern fn hi_noun_oblique_f(noun: String, number: String) -> String
extern fn hi_noun_direct(noun: String, gender: String, number: String) -> String
extern fn hi_noun_oblique(noun: String, gender: String, number: String) -> String
extern fn hi_postposition(gram_case: String) -> String
extern fn hi_agree_genitive(possessed_gender: String, possessed_number: String) -> String
extern fn hi_verb_stem(infinitive: String) -> String
extern fn hi_verb_stem_clean(infinitive: String) -> String
extern fn hi_present_aspect(gender: String, number: String) -> String
extern fn hi_aux_present(person: String, number: String) -> String
extern fn hi_past_suffix(gender: String, number: String) -> String
extern fn hi_past_irregular(stem: String, gender: String, number: String) -> String
extern fn hi_future_suffix(person: String, number: String, gender: String) -> String
extern fn hi_tense_suffix(tense: String, gender: String, number: String) -> String
extern fn hi_hona_present(person: String, number: String) -> String
extern fn hi_hona_past(gender: String, number: String) -> String
extern fn hi_conjugate(verb: String, tense: String, person: String, gender: String, number: String) -> String
extern fn hi_noun_with_post(noun: String, gender: String, number: String, gram_case: String) -> String
extern fn hi_genitive_phrase(possessor: String, possessor_gender: String, possessor_number: String, possessed: String, possessed_gender: String, possessed_number: String) -> String
Generated Vendored
+9
View File
@@ -0,0 +1,9 @@
// auto-generated by elc --emit-header — do not edit
extern fn ja_verb_group(dict_form: String) -> String
extern fn ja_ichidan_stem(dict_form: String) -> String
extern fn ja_godan_stem_change(dict_form: String, row: String) -> String
extern fn ja_conjugate(dict_form: String, form: String) -> String
extern fn ja_particle(gram_case: String) -> String
extern fn ja_noun_phrase(noun: String, gram_case: String) -> String
extern fn ja_question_particle() -> String
extern fn ja_make_question(sentence: String) -> String
Generated Vendored
+41
View File
@@ -0,0 +1,41 @@
// auto-generated by elc --emit-header — do not edit
extern fn la_str_ends(s: String, suf: String) -> Bool
extern fn la_str_drop_last(s: String, n: Int) -> String
extern fn la_str_last_char(s: String) -> String
extern fn la_str_last2(s: String) -> String
extern fn la_str_last3(s: String) -> String
extern fn la_slot(person: String, number: String) -> Int
extern fn la_verb_class(verb: String) -> String
extern fn la_stem(verb: String, vclass: String) -> String
extern fn la_perfect_stem(verb: String, vclass: String) -> String
extern fn la_perfect_ending(slot: Int) -> String
extern fn la_present_ending(vclass: String, slot: Int) -> String
extern fn la_present_form(stem: String, vclass: String, slot: Int) -> String
extern fn la_future_ending_12(slot: Int) -> String
extern fn la_future_ending_34(slot: Int) -> String
extern fn la_future_form(stem: String, vclass: String, slot: Int) -> String
extern fn la_esse_present(slot: Int) -> String
extern fn la_esse_past(slot: Int) -> String
extern fn la_esse_future(slot: Int) -> String
extern fn la_ire_present(slot: Int) -> String
extern fn la_ire_past(slot: Int) -> String
extern fn la_ire_future(slot: Int) -> String
extern fn la_velle_present(slot: Int) -> String
extern fn la_velle_past(slot: Int) -> String
extern fn la_velle_future(slot: Int) -> String
extern fn la_posse_present(slot: Int) -> String
extern fn la_posse_past(slot: Int) -> String
extern fn la_posse_future(slot: Int) -> String
extern fn la_irregular_perfect_stem(verb: String) -> String
extern fn la_map_canonical(verb: String) -> String
extern fn la_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn la_declension(noun: String) -> String
extern fn la_decline_1(stem: String, gram_case: String, number: String) -> String
extern fn la_decline_2m(stem: String, gram_case: String, number: String) -> String
extern fn la_decline_2n(stem: String, gram_case: String, number: String) -> String
extern fn la_decline_3(noun: String, gram_case: String, number: String) -> String
extern fn la_decline_4(stem: String, gram_case: String, number: String) -> String
extern fn la_decline_5(stem: String, gram_case: String, number: String) -> String
extern fn la_decline_2er(noun: String, gram_case: String, number: String) -> String
extern fn la_decline(noun: String, gram_case: String, number: String) -> String
extern fn la_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+30
View File
@@ -0,0 +1,30 @@
// auto-generated by elc --emit-header — do not edit
extern fn non_str_ends(s: String, suf: String) -> Bool
extern fn non_drop(s: String, n: Int) -> String
extern fn non_last(s: String) -> String
extern fn non_slot(person: String, number: String) -> Int
extern fn non_vera_present(slot: Int) -> String
extern fn non_vera_past(slot: Int) -> String
extern fn non_hafa_present(slot: Int) -> String
extern fn non_hafa_past(slot: Int) -> String
extern fn non_ganga_present(slot: Int) -> String
extern fn non_ganga_past(slot: Int) -> String
extern fn non_sja_present(slot: Int) -> String
extern fn non_sja_past(slot: Int) -> String
extern fn non_segja_present(slot: Int) -> String
extern fn non_segja_past(slot: Int) -> String
extern fn non_koma_present(slot: Int) -> String
extern fn non_koma_past(slot: Int) -> String
extern fn non_map_canonical(verb: String) -> String
extern fn non_weak_present(stem: String, slot: Int) -> String
extern fn non_weak_past(stem: String, slot: Int) -> String
extern fn non_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn non_decline_masc(noun: String, gram_case: String, number: String) -> String
extern fn non_decline_fem(noun: String, gram_case: String, number: String) -> String
extern fn non_decline_neut(noun: String, gram_case: String, number: String) -> String
extern fn non_detect_gender(noun: String) -> String
extern fn non_decline(noun: String, gram_case: String, number: String) -> String
extern fn non_def_suffix_masc(gram_case: String, number: String) -> String
extern fn non_def_suffix_neut(gram_case: String, number: String) -> String
extern fn non_def_suffix_fem(gram_case: String, number: String) -> String
extern fn non_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+19
View File
@@ -0,0 +1,19 @@
// auto-generated by elc --emit-header — do not edit
extern fn peo_drop(s: String, n: Int) -> String
extern fn peo_ends(s: String, suf: String) -> Bool
extern fn peo_slot(person: String, number: String) -> Int
extern fn peo_present_suffix(slot: Int) -> String
extern fn peo_past_suffix(slot: Int) -> String
extern fn peo_ah_present(slot: Int) -> String
extern fn peo_ah_past(slot: Int) -> String
extern fn peo_kar_present(slot: Int) -> String
extern fn peo_kar_past(slot: Int) -> String
extern fn peo_xsaya_present(slot: Int) -> String
extern fn peo_tar_present(slot: Int) -> String
extern fn peo_da_present(slot: Int) -> String
extern fn peo_da_past(slot: Int) -> String
extern fn peo_map_canonical(verb: String) -> String
extern fn peo_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn peo_decline_astem(noun: String, gram_case: String, number: String) -> String
extern fn peo_decline(noun: String, gram_case: String, number: String) -> String
extern fn peo_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+34
View File
@@ -0,0 +1,34 @@
// auto-generated by elc --emit-header — do not edit
extern fn pi_str_ends(s: String, suf: String) -> Bool
extern fn pi_drop(s: String, n: Int) -> String
extern fn pi_last_char(s: String) -> String
extern fn pi_slot(person: String, number: String) -> Int
extern fn pi_present_ending(slot: Int) -> String
extern fn pi_aorist_ending(slot: Int) -> String
extern fn pi_future_ending(slot: Int) -> String
extern fn pi_hoti_present(slot: Int) -> String
extern fn pi_atthi_present(slot: Int) -> String
extern fn pi_hoti_aorist(slot: Int) -> String
extern fn pi_hoti_future(slot: Int) -> String
extern fn pi_gacchati_present(slot: Int) -> String
extern fn pi_gacchati_aorist(slot: Int) -> String
extern fn pi_gacchati_future(slot: Int) -> String
extern fn pi_passati_present(slot: Int) -> String
extern fn pi_passati_aorist(slot: Int) -> String
extern fn pi_passati_future(slot: Int) -> String
extern fn pi_vadati_present(slot: Int) -> String
extern fn pi_vadati_aorist(slot: Int) -> String
extern fn pi_vadati_future(slot: Int) -> String
extern fn pi_karoti_present(slot: Int) -> String
extern fn pi_karoti_aorist(slot: Int) -> String
extern fn pi_karoti_future(slot: Int) -> String
extern fn pi_map_canonical(verb: String) -> String
extern fn pi_regular_root(verb: String) -> String
extern fn pi_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn pi_decline_a_masc_sg(stem: String, gram_case: String) -> String
extern fn pi_decline_a_masc_pl(stem: String, gram_case: String) -> String
extern fn pi_decline_a_fem_sg(stem: String, gram_case: String) -> String
extern fn pi_decline_a_fem_pl(stem: String, gram_case: String) -> String
extern fn pi_detect_class(noun: String) -> String
extern fn pi_decline(noun: String, gram_case: String, number: String) -> String
extern fn pi_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+14
View File
@@ -0,0 +1,14 @@
// auto-generated by elc --emit-header — do not edit
extern fn ru_gender(noun: String) -> String
extern fn ru_stem_type(noun: String, gender: String) -> String
extern fn ru_noun_case(noun: String, gender: String, gram_case: String, number: String) -> String
extern fn ru_decline_regular(noun: String, gender: String, stype: String, gram_case: String, number: String) -> String
extern fn ru_decline_masc(noun: String, stype: String, gram_case: String, number: String) -> String
extern fn ru_decline_fem(noun: String, stype: String, gram_case: String, number: String) -> String
extern fn ru_decline_neut(noun: String, stype: String, gram_case: String, number: String) -> String
extern fn ru_past_agree(verb_stem: String, gender: String, number: String) -> String
extern fn ru_conjugate_1st(stem: String, tense: String, person: String, number: String) -> String
extern fn ru_conjugate_2nd(stem: String, tense: String, person: String, number: String) -> String
extern fn ru_irregular(verb: String, tense: String, person: String, number: String) -> String
extern fn ru_past_stem(verb: String) -> String
extern fn ru_conjugate(verb: String, tense: String, person: String, number: String, gender: String) -> String
Generated Vendored
+36
View File
@@ -0,0 +1,36 @@
// auto-generated by elc --emit-header — do not edit
extern fn sa_str_ends(s: String, suf: String) -> Bool
extern fn sa_str_drop_last(s: String, n: Int) -> String
extern fn sa_slot(person: String, number: String) -> Int
extern fn sa_map_canonical(verb: String) -> String
extern fn sa_as_present(slot: Int) -> String
extern fn sa_as_past(slot: Int) -> String
extern fn sa_as_future(slot: Int) -> String
extern fn sa_bhu_present(slot: Int) -> String
extern fn sa_bhu_past(slot: Int) -> String
extern fn sa_bhu_future(slot: Int) -> String
extern fn sa_gam_present(slot: Int) -> String
extern fn sa_gam_past(slot: Int) -> String
extern fn sa_gam_future(slot: Int) -> String
extern fn sa_drs_present(slot: Int) -> String
extern fn sa_drs_past(slot: Int) -> String
extern fn sa_drs_future(slot: Int) -> String
extern fn sa_vad_present(slot: Int) -> String
extern fn sa_vad_past(slot: Int) -> String
extern fn sa_vad_future(slot: Int) -> String
extern fn sa_kr_present(slot: Int) -> String
extern fn sa_kr_past(slot: Int) -> String
extern fn sa_kr_future(slot: Int) -> String
extern fn sa_class1_present_ending(slot: Int) -> String
extern fn sa_class1_past_ending(slot: Int) -> String
extern fn sa_class1_future_ending(slot: Int) -> String
extern fn sa_class1_conjugate(stem: String, tense: String, slot: Int) -> String
extern fn sa_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn sa_decline_a_stem_sg(stem: String, gram_case: String) -> String
extern fn sa_decline_a_stem_pl(stem: String, gram_case: String) -> String
extern fn sa_decline_aa_stem_sg(stem: String, gram_case: String) -> String
extern fn sa_decline_aa_stem_pl(stem: String, gram_case: String) -> String
extern fn sa_stem_type(noun: String) -> String
extern fn sa_extract_stem(noun: String, stype: String) -> String
extern fn sa_decline(noun: String, gram_case: String, number: String) -> String
extern fn sa_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+22
View File
@@ -0,0 +1,22 @@
// auto-generated by elc --emit-header — do not edit
extern fn sga_drop(s: String, n: Int) -> String
extern fn sga_first(s: String) -> String
extern fn sga_rest(s: String) -> String
extern fn sga_slot(person: String, number: String) -> Int
extern fn sga_lenite(word: String) -> String
extern fn sga_copula_present(slot: Int) -> String
extern fn sga_bith_present(slot: Int) -> String
extern fn sga_bith_past(slot: Int) -> String
extern fn sga_teit_present(slot: Int) -> String
extern fn sga_teit_past(slot: Int) -> String
extern fn sga_gaibid_present(slot: Int) -> String
extern fn sga_adci_present(slot: Int) -> String
extern fn sga_asbeir_present(slot: Int) -> String
extern fn sga_map_canonical(verb: String) -> String
extern fn sga_ai_present(stem: String, slot: Int) -> String
extern fn sga_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn sga_decline_ostem(noun: String, gram_case: String, number: String) -> String
extern fn sga_decline_astem(noun: String, gram_case: String, number: String) -> String
extern fn sga_detect_gender(noun: String) -> String
extern fn sga_decline(noun: String, gram_case: String, number: String) -> String
extern fn sga_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+29
View File
@@ -0,0 +1,29 @@
// auto-generated by elc --emit-header — do not edit
extern fn sux_str_ends(s: String, suf: String) -> Bool
extern fn sux_str_drop_last(s: String, n: Int) -> String
extern fn sux_str_last_char(s: String) -> String
extern fn sux_str_last2(s: String) -> String
extern fn sux_slot(person: String, number: String) -> Int
extern fn sux_ergative_suffix(person: String, number: String) -> String
extern fn sux_absolutive_suffix(person: String, number: String) -> String
extern fn sux_map_canonical(verb: String) -> String
extern fn sux_personal_suffix(slot: Int) -> String
extern fn sux_me_present(slot: Int) -> String
extern fn sux_me_past(slot: Int) -> String
extern fn sux_dug4_present(slot: Int) -> String
extern fn sux_dug4_past(slot: Int) -> String
extern fn sux_du_present(slot: Int) -> String
extern fn sux_du_past(slot: Int) -> String
extern fn sux_igibar_present(slot: Int) -> String
extern fn sux_igibar_past(slot: Int) -> String
extern fn sux_ak_present(slot: Int) -> String
extern fn sux_ak_past(slot: Int) -> String
extern fn sux_tum2_present(slot: Int) -> String
extern fn sux_tum2_past(slot: Int) -> String
extern fn sux_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn sux_is_animate(noun: String) -> Bool
extern fn sux_case_suffix(gram_case: String) -> String
extern fn sux_decline(noun: String, gram_case: String, number: String) -> String
extern fn sux_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
extern fn sux_verb_chain(agent: String, verb: String, patient: String, tense: String) -> String
extern fn sux_realize_sentence(intent: String, agent: String, predicate: String, patient: String, tense: String) -> String
Generated Vendored
+23
View File
@@ -0,0 +1,23 @@
// auto-generated by elc --emit-header — do not edit
extern fn sw_str_ends(s: String, suf: String) -> Bool
extern fn sw_str_drop_last(s: String, n: Int) -> String
extern fn sw_str_first_char(s: String) -> String
extern fn sw_str_first2(s: String) -> String
extern fn sw_str_first3(s: String) -> String
extern fn sw_str_last_char(s: String) -> String
extern fn sw_is_class1_noun(noun: String) -> Bool
extern fn sw_noun_class(noun: String) -> String
extern fn sw_subj_prefix(person: String, number: String, noun_class: String) -> String
extern fn sw_obj_prefix(person: String, number: String, noun_class: String) -> String
extern fn sw_tense_marker(tense: String) -> String
extern fn sw_verb_final(tense: String, negative: Bool) -> String
extern fn sw_neg_subj_prefix(person: String, number: String, noun_class: String) -> String
extern fn sw_verb_stem(infinitive: String) -> String
extern fn sw_conjugate(verb_stem: String, person: String, number: String, noun_class: String, tense: String) -> String
extern fn sw_negative(verb_stem: String, person: String, number: String, noun_class: String, tense: String) -> String
extern fn sw_noun_plural(noun: String) -> String
extern fn sw_adj_prefix(noun_class: String, number: String) -> String
extern fn sw_agree_adj(adj_stem: String, noun_class: String, number: String) -> String
extern fn sw_demonstrative(noun_class: String, number: String, proximity: String) -> String
extern fn sw_copula_present(person: String, number: String, use_case: String) -> String
extern fn sw_copula_neg_present(person: String, number: String) -> String
Generated Vendored
+17
View File
@@ -0,0 +1,17 @@
// auto-generated by elc --emit-header — do not edit
extern fn txb_drop(s: String, n: Int) -> String
extern fn txb_ends(s: String, suf: String) -> Bool
extern fn txb_slot(person: String, number: String) -> Int
extern fn txb_pres1_suffix(slot: Int) -> String
extern fn txb_kam_present(slot: Int) -> String
extern fn txb_ya_present(slot: Int) -> String
extern fn txb_wes_present(slot: Int) -> String
extern fn txb_lyut_present(slot: Int) -> String
extern fn txb_wak_present(slot: Int) -> String
extern fn txb_map_canonical(verb: String) -> String
extern fn txb_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn txb_decline_masc(noun: String, gram_case: String, number: String) -> String
extern fn txb_decline_fem(noun: String, gram_case: String, number: String) -> String
extern fn txb_detect_gender(noun: String) -> String
extern fn txb_decline(noun: String, gram_case: String, number: String) -> String
extern fn txb_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
Generated Vendored
+25
View File
@@ -0,0 +1,25 @@
// auto-generated by elc --emit-header — do not edit
extern fn uga_str_ends(s: String, suf: String) -> Bool
extern fn uga_str_len(s: String) -> Int
extern fn uga_str_drop_last(s: String, n: Int) -> String
extern fn uga_slot(person: String, number: String) -> Int
extern fn uga_slot_g(person: String, gender: String, number: String) -> Int
extern fn uga_kn_perfect(slot: Int) -> String
extern fn uga_kn_imperfect(slot: Int) -> String
extern fn uga_is_copula(verb: String) -> Bool
extern fn uga_conjugate_copula(tense: String, slot: Int) -> String
extern fn uga_hlk_perfect(slot: Int) -> String
extern fn uga_hlk_imperfect(slot: Int) -> String
extern fn uga_ray_perfect(slot: Int) -> String
extern fn uga_ray_imperfect(slot: Int) -> String
extern fn uga_amr_perfect(slot: Int) -> String
extern fn uga_amr_imperfect(slot: Int) -> String
extern fn uga_generic_perfect(base3sg: String, slot: Int) -> String
extern fn uga_generic_imperfect(base3sg: String, slot: Int) -> String
extern fn uga_known_verb(verb: String, tense: String, slot: Int) -> String
extern fn uga_conjugate(verb: String, tense: String, person: String, number: String) -> String
extern fn uga_strip_nom(noun: String) -> String
extern fn uga_is_fem(noun: String) -> Bool
extern fn uga_decline(noun: String, gram_case: String, number: String) -> String
extern fn uga_noun_phrase(noun: String, gram_case: String, number: String, definite: String) -> String
extern fn uga_map_canonical(verb: String) -> String
Generated Vendored
+27
View File
@@ -0,0 +1,27 @@
// auto-generated by elc --emit-header — do not edit
extern fn str_ends(s: String, suf: String) -> Bool
extern fn str_last_char(s: String) -> String
extern fn str_last2(s: String) -> String
extern fn str_last3(s: String) -> String
extern fn str_drop_last(s: String, n: Int) -> String
extern fn is_vowel(c: String) -> Bool
extern fn morph_apply_suffix(base: String, suffix: String) -> String
extern fn en_irregular_plural(word: String) -> String
extern fn en_irregular_singular(word: String) -> String
extern fn en_irregular_verb(base: String) -> [String]
extern fn en_verb_3sg(base: String) -> String
extern fn en_should_double_final(base: String) -> Bool
extern fn en_verb_past(base: String) -> String
extern fn en_verb_gerund(base: String) -> String
extern fn en_pluralize_regular(singular: String) -> String
extern fn en_verb_form(base: String, tense: String, person: String, number: String) -> String
extern fn agree_determiner(det: String, noun: String) -> String
extern fn morph_pluralize(noun: String, profile: [String]) -> String
extern fn morph_map_canonical(verb: String, code: String) -> String
extern fn morph_conjugate(verb: String, tense: String, person: String, number: String, profile: [String]) -> String
extern fn morph_inflect(word: String, features: String, profile: [String]) -> String
extern fn pluralize(singular: String) -> String
extern fn singularize(plural: String) -> String
extern fn verb_form(base: String, tense: String, person: String, number: String) -> String
extern fn irregular_plural(word: String) -> String
extern fn irregular_singular(word: String) -> String
Generated Vendored
+176 -374
View File
@@ -26,22 +26,9 @@ el_val_t api_ok(el_val_t extra);
el_val_t api_err(el_val_t msg); el_val_t api_err(el_val_t msg);
el_val_t api_nonempty(el_val_t s); el_val_t api_nonempty(el_val_t s);
el_val_t api_or_empty(el_val_t s); el_val_t api_or_empty(el_val_t s);
el_val_t api_num_or_zero(el_val_t obj, el_val_t key);
el_val_t api_utf8_trunc(el_val_t s, el_val_t n);
el_val_t api_compact_node(el_val_t node, el_val_t snip);
el_val_t api_compact_node_array(el_val_t raw, el_val_t max_items, el_val_t snip);
el_val_t api_compact_activated(el_val_t raw, el_val_t max_items, el_val_t snip);
el_val_t api_persisted(el_val_t id);
el_val_t api_not_persisted(el_val_t id);
el_val_t tombstone_node(el_val_t id);
el_val_t tombstoned_id_set(void);
el_val_t memory_hide_tombstoned(el_val_t raw, el_val_t path);
el_val_t handle_api_begin_session(el_val_t body); el_val_t handle_api_begin_session(el_val_t body);
el_val_t handle_api_compile_ctx(el_val_t body); el_val_t handle_api_compile_ctx(el_val_t body);
el_val_t handle_api_remember(el_val_t body); el_val_t handle_api_remember(el_val_t body);
el_val_t handle_api_node_create(el_val_t body);
el_val_t handle_api_node_delete(el_val_t body);
el_val_t handle_api_node_update(el_val_t body);
el_val_t handle_api_recall(el_val_t method, el_val_t path, el_val_t body); el_val_t handle_api_recall(el_val_t method, el_val_t path, el_val_t body);
el_val_t handle_api_search_knowledge(el_val_t method, el_val_t path, el_val_t body); el_val_t handle_api_search_knowledge(el_val_t method, el_val_t path, el_val_t body);
el_val_t handle_api_browse_knowledge(el_val_t path, el_val_t body); el_val_t handle_api_browse_knowledge(el_val_t path, el_val_t body);
@@ -58,12 +45,114 @@ el_val_t handle_api_inspect_graph(el_val_t method, el_val_t path, el_val_t body)
el_val_t handle_api_link_entities(el_val_t body); el_val_t handle_api_link_entities(el_val_t body);
el_val_t handle_api_forget(el_val_t body); el_val_t handle_api_forget(el_val_t body);
el_val_t handle_api_evolve_memory(el_val_t body); el_val_t handle_api_evolve_memory(el_val_t body);
el_val_t handle_api_memory_delete(el_val_t body);
el_val_t handle_api_memory_update(el_val_t body);
el_val_t handle_api_cultivate(el_val_t body); el_val_t handle_api_cultivate(el_val_t body);
el_val_t handle_api_list_typed(el_val_t node_type, el_val_t path, el_val_t body); el_val_t handle_api_list_typed(el_val_t node_type, el_val_t path, el_val_t body);
el_val_t handle_api_consolidate(el_val_t body); el_val_t handle_api_consolidate(el_val_t body);
el_val_t tier_working(void) {
return EL_STR("Working");
return 0;
}
el_val_t tier_episodic(void) {
return EL_STR("Episodic");
return 0;
}
el_val_t tier_canonical(void) {
return EL_STR("Canonical");
return 0;
}
el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags) {
return engram_node_full(content, EL_STR("Memory"), label, el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.8)), EL_STR("Working"), tags);
return 0;
}
el_val_t mem_remember(el_val_t content, el_val_t tags) {
return mem_store(content, EL_STR("soul-memory"), tags);
return 0;
}
el_val_t mem_recall(el_val_t query, el_val_t depth) {
return engram_activate_json(query, depth);
return 0;
}
el_val_t mem_search(el_val_t query, el_val_t limit) {
return engram_search_json(query, limit);
return 0;
}
el_val_t mem_strengthen(el_val_t node_id) {
engram_strengthen(node_id);
return 0;
}
el_val_t mem_forget(el_val_t node_id) {
engram_forget(node_id);
return 0;
}
el_val_t mem_consolidate(void) {
el_val_t scanned = engram_node_count();
el_val_t dummy = engram_scan_nodes_json(100, 0);
el_val_t total_nodes = engram_node_count();
el_val_t total_edges = engram_edge_count();
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"scanned\":"), int_to_str(scanned)), EL_STR(",\"total_nodes\":")), int_to_str(total_nodes)), EL_STR(",\"total_edges\":")), int_to_str(total_edges)), EL_STR("}"));
return 0;
}
el_val_t mem_save(el_val_t path) {
engram_save(path);
return 0;
}
el_val_t mem_load(el_val_t path) {
engram_load(path);
return 0;
}
el_val_t mem_boot_count_get(void) {
el_val_t results = engram_search_json(EL_STR("soul:boot_count"), 3);
if (str_eq(results, EL_STR(""))) {
return 0;
}
if (str_eq(results, EL_STR("[]"))) {
return 0;
}
el_val_t node = json_array_get(results, 0);
el_val_t content = json_get(node, EL_STR("content"));
el_val_t prefix = EL_STR("soul:boot_count:");
if (!str_starts_with(content, prefix)) {
return 0;
}
el_val_t num_str = str_slice(content, str_len(prefix), str_len(content));
return str_to_int(num_str);
return 0;
}
el_val_t mem_boot_count_inc(void) {
el_val_t current = mem_boot_count_get();
el_val_t next = (current + 1);
el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next));
el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]");
el_val_t discard = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(1.0)), EL_STR("Canonical"), tags);
return next;
return 0;
}
el_val_t mem_emit_state_event(el_val_t trigger, el_val_t kind, el_val_t content) {
el_val_t boot = mem_boot_count_get();
el_val_t ts = time_now();
el_val_t safe_trigger = str_replace(trigger, EL_STR("\""), EL_STR("'"));
el_val_t safe_content = str_replace(content, EL_STR("\""), EL_STR("'"));
el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"trigger\":\""), safe_trigger), EL_STR("\"")), EL_STR(",\"kind\":\"")), kind), EL_STR("\"")), EL_STR(",\"content\":\"")), safe_content), EL_STR("\"")), EL_STR(",\"boot\":")), int_to_str(boot)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t tags = EL_STR("[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]");
return engram_node_full(payload, EL_STR("InternalStateEvent"), el_str_concat(EL_STR("state-event:"), kind), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
return 0;
}
el_val_t is_protected_node(el_val_t id) { el_val_t is_protected_node(el_val_t id) {
if (str_eq(id, EL_STR("kn-efeb4a5b-5aff-4759-8a97-7233099be6ee"))) { if (str_eq(id, EL_STR("kn-efeb4a5b-5aff-4759-8a97-7233099be6ee"))) {
return 1; return 1;
@@ -183,168 +272,21 @@ el_val_t api_or_empty(el_val_t s) {
return 0; return 0;
} }
el_val_t api_num_or_zero(el_val_t obj, el_val_t key) {
el_val_t v = json_get_raw(obj, key);
if (str_eq(v, EL_STR(""))) {
return EL_STR("0");
}
return v;
return 0;
}
el_val_t api_utf8_trunc(el_val_t s, el_val_t n) {
if (str_len(s) <= n) {
return s;
}
el_val_t cut = n;
el_val_t scanning = 1;
while (scanning && (cut > 0)) {
el_val_t b = str_char_code(s, cut);
el_val_t is_cont = ((b >= 128) && (b < 192));
cut = ({ el_val_t _if_result_1 = 0; if (is_cont) { _if_result_1 = ((cut - 1)); } else { _if_result_1 = (cut); } _if_result_1; });
scanning = is_cont;
}
return str_slice(s, 0, cut);
return 0;
}
el_val_t api_compact_node(el_val_t node, el_val_t snip) {
el_val_t id = json_get(node, EL_STR("id"));
el_val_t ntype = json_get(node, EL_STR("node_type"));
el_val_t label = json_get(node, EL_STR("label"));
el_val_t tier = json_get(node, EL_STR("tier"));
el_val_t content = json_get(node, EL_STR("content"));
el_val_t snippet = api_utf8_trunc(content, snip);
el_val_t trunc_str = ({ el_val_t _if_result_2 = 0; if ((str_len(content) > snip)) { _if_result_2 = (EL_STR("true")); } else { _if_result_2 = (EL_STR("false")); } _if_result_2; });
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), api_json_escape(id)), EL_STR("\"")), EL_STR(",\"node_type\":\"")), api_json_escape(ntype)), EL_STR("\"")), EL_STR(",\"label\":\"")), api_json_escape(label)), EL_STR("\"")), EL_STR(",\"tier\":\"")), api_json_escape(tier)), EL_STR("\"")), EL_STR(",\"importance\":")), api_num_or_zero(node, EL_STR("importance"))), EL_STR(",\"salience\":")), api_num_or_zero(node, EL_STR("salience"))), EL_STR(",\"content\":\"")), api_json_escape(snippet)), EL_STR("\"")), EL_STR(",\"content_truncated\":")), trunc_str), EL_STR("}"));
return 0;
}
el_val_t api_compact_node_array(el_val_t raw, el_val_t max_items, el_val_t snip) {
if (!api_nonempty(raw)) {
return EL_STR("[]");
}
el_val_t n = json_array_len(raw);
el_val_t cap = ({ el_val_t _if_result_3 = 0; if ((n < max_items)) { _if_result_3 = (n); } else { _if_result_3 = (max_items); } _if_result_3; });
el_val_t out = EL_STR("[");
el_val_t i = 0;
while (i < cap) {
el_val_t node = json_array_get(raw, i);
el_val_t sep = ({ el_val_t _if_result_4 = 0; if ((i == 0)) { _if_result_4 = (EL_STR("")); } else { _if_result_4 = (EL_STR(",")); } _if_result_4; });
out = el_str_concat(el_str_concat(out, sep), api_compact_node(node, snip));
i = (i + 1);
}
return el_str_concat(out, EL_STR("]"));
return 0;
}
el_val_t api_compact_activated(el_val_t raw, el_val_t max_items, el_val_t snip) {
if (!api_nonempty(raw)) {
return EL_STR("[]");
}
el_val_t n = json_array_len(raw);
el_val_t cap = ({ el_val_t _if_result_5 = 0; if ((n < max_items)) { _if_result_5 = (n); } else { _if_result_5 = (max_items); } _if_result_5; });
el_val_t out = EL_STR("[");
el_val_t i = 0;
while (i < cap) {
el_val_t el = json_array_get(raw, i);
el_val_t node = json_get_raw(el, EL_STR("node"));
el_val_t sep = ({ el_val_t _if_result_6 = 0; if ((i == 0)) { _if_result_6 = (EL_STR("")); } else { _if_result_6 = (EL_STR(",")); } _if_result_6; });
out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(out, sep), EL_STR("{\"node\":")), api_compact_node(node, snip)), EL_STR(",\"activation_strength\":")), api_num_or_zero(el, EL_STR("activation_strength"))), EL_STR(",\"working_memory_weight\":")), api_num_or_zero(el, EL_STR("working_memory_weight"))), EL_STR(",\"epistemic_confidence\":")), api_num_or_zero(el, EL_STR("epistemic_confidence"))), EL_STR(",\"hops\":")), api_num_or_zero(el, EL_STR("hops"))), EL_STR(",\"promoted\":")), api_num_or_zero(el, EL_STR("promoted"))), EL_STR("}"));
i = (i + 1);
}
return el_str_concat(out, EL_STR("]"));
return 0;
}
el_val_t api_persisted(el_val_t id) {
if (str_eq(id, EL_STR(""))) {
return 0;
}
el_val_t node = engram_get_node_json(id);
return ((!str_eq(node, EL_STR("")) && !str_eq(node, EL_STR("null"))) && !str_eq(node, EL_STR("{}")));
return 0;
}
el_val_t api_not_persisted(el_val_t id) {
return el_str_concat(el_str_concat(EL_STR("{\"ok\":false,\"error\":\"write_not_persisted\",\"id\":\""), id), EL_STR("\"}"));
return 0;
}
el_val_t tombstone_node(el_val_t id) {
return mem_tombstone(id);
return 0;
}
el_val_t tombstoned_id_set(void) {
el_val_t markers = engram_scan_nodes_by_type_json(EL_STR("Tombstone"), 5000, 0);
if (str_eq(markers, EL_STR("")) || str_eq(markers, EL_STR("[]"))) {
return EL_STR("");
}
el_val_t n = json_array_len(markers);
el_val_t acc = EL_STR("|");
el_val_t i = 0;
while (i < n) {
el_val_t m = json_array_get(markers, i);
el_val_t tid = json_get(m, EL_STR("content"));
acc = ({ el_val_t _if_result_7 = 0; if (str_eq(tid, EL_STR(""))) { _if_result_7 = (acc); } else { _if_result_7 = (el_str_concat(el_str_concat(acc, tid), EL_STR("|"))); } _if_result_7; });
i = (i + 1);
}
return acc;
return 0;
}
el_val_t memory_hide_tombstoned(el_val_t raw, el_val_t path) {
if (str_contains(path, EL_STR("include_deleted"))) {
return raw;
}
if (str_eq(raw, EL_STR("")) || str_eq(raw, EL_STR("[]"))) {
return raw;
}
el_val_t dead = tombstoned_id_set();
if (str_eq(dead, EL_STR(""))) {
return raw;
}
el_val_t n = json_array_len(raw);
if (n > 1000) {
return raw;
}
el_val_t out = EL_STR("[");
el_val_t first = 1;
el_val_t i = 0;
while (i < n) {
el_val_t node = json_array_get(raw, i);
el_val_t nid = json_get(node, EL_STR("id"));
el_val_t ntype = json_get(node, EL_STR("node_type"));
el_val_t is_dead = (!str_eq(nid, EL_STR("")) && str_contains(dead, el_str_concat(el_str_concat(EL_STR("|"), nid), EL_STR("|"))));
el_val_t keep = (!str_eq(ntype, EL_STR("Tombstone")) && !is_dead);
out = ({ el_val_t _if_result_8 = 0; if (keep) { _if_result_8 = (({ el_val_t _if_result_9 = 0; if (first) { _if_result_9 = (el_str_concat(out, node)); } else { _if_result_9 = (el_str_concat(el_str_concat(out, EL_STR(",")), node)); } _if_result_9; })); } else { _if_result_8 = (out); } _if_result_8; });
first = ({ el_val_t _if_result_10 = 0; if (keep) { _if_result_10 = (0); } else { _if_result_10 = (first); } _if_result_10; });
i = (i + 1);
}
return el_str_concat(out, EL_STR("]"));
return 0;
}
el_val_t handle_api_begin_session(el_val_t body) { el_val_t handle_api_begin_session(el_val_t body) {
el_val_t stats = engram_stats_json(); el_val_t stats = engram_stats_json();
el_val_t activated_raw = engram_activate_json(EL_STR("session start recent memory important"), 1); el_val_t activated = engram_activate_json(EL_STR("session start recent memory important"), 2);
el_val_t activated = api_compact_activated(activated_raw, 8, 240); el_val_t self_nbrs = engram_neighbors_json(EL_STR("kn-efeb4a5b-5aff-4759-8a97-7233099be6ee"), 1, EL_STR("both"));
el_val_t state_events_raw = engram_scan_nodes_by_type_json(EL_STR("InternalStateEvent"), 5, 0); el_val_t state_events = engram_scan_nodes_by_type_json(EL_STR("InternalStateEvent"), 5, 0);
el_val_t state_events = api_compact_node_array(state_events_raw, 5, 500); el_val_t recent = engram_scan_nodes_json(10, 0);
el_val_t recent_raw = engram_scan_nodes_json(10, 0); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"stats\":"), stats), EL_STR(",\"recent\":")), api_or_empty(recent)), EL_STR(",\"activated\":")), api_or_empty(activated)), EL_STR(",\"self_neighbors\":")), api_or_empty(self_nbrs)), EL_STR(",\"recent_state_events\":")), api_or_empty(state_events)), EL_STR("}"));
el_val_t recent = api_compact_node_array(recent_raw, 10, 240);
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"stats\":"), stats), EL_STR(",\"recent\":")), recent), EL_STR(",\"activated\":")), activated), EL_STR(",\"self_neighbors\":[]")), EL_STR(",\"recent_state_events\":")), state_events), EL_STR("}"));
return 0; return 0;
} }
el_val_t handle_api_compile_ctx(el_val_t body) { el_val_t handle_api_compile_ctx(el_val_t body) {
el_val_t stats = engram_stats_json(); el_val_t stats = engram_stats_json();
el_val_t activated_raw = engram_activate_json(EL_STR("active work context current task in progress"), 2); el_val_t activated = engram_activate_json(EL_STR("active work context current task in progress"), 2);
el_val_t activated = api_compact_activated(activated_raw, 10, 240); el_val_t recent = engram_scan_nodes_json(20, 0);
el_val_t recent_raw = engram_scan_nodes_json(20, 0); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"stats\":"), stats), EL_STR(",\"recent_nodes\":")), api_or_empty(recent)), EL_STR(",\"activated\":")), api_or_empty(activated)), EL_STR("}"));
el_val_t recent = api_compact_node_array(recent_raw, 20, 240);
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"stats\":"), stats), EL_STR(",\"recent_nodes\":")), recent), EL_STR(",\"activated\":")), activated), EL_STR("}"));
return 0; return 0;
} }
@@ -356,102 +298,22 @@ el_val_t handle_api_remember(el_val_t body) {
el_val_t importance = json_get(body, EL_STR("importance")); el_val_t importance = json_get(body, EL_STR("importance"));
el_val_t tags_raw = json_get(body, EL_STR("tags")); el_val_t tags_raw = json_get(body, EL_STR("tags"));
el_val_t project = json_get(body, EL_STR("project")); el_val_t project = json_get(body, EL_STR("project"));
el_val_t sal_str = ({ el_val_t _if_result_11 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_11 = (EL_STR("0.95")); } else { _if_result_11 = (({ el_val_t _if_result_12 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_12 = (EL_STR("0.75")); } else { _if_result_12 = (({ el_val_t _if_result_13 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_13 = (EL_STR("0.25")); } else { _if_result_13 = (EL_STR("0.50")); } _if_result_13; })); } _if_result_12; })); } _if_result_11; }); el_val_t sal_str = ({ el_val_t _if_result_1 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_1 = (EL_STR("0.95")); } else { _if_result_1 = (({ el_val_t _if_result_2 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_2 = (EL_STR("0.75")); } else { _if_result_2 = (({ el_val_t _if_result_3 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_3 = (EL_STR("0.25")); } else { _if_result_3 = (EL_STR("0.50")); } _if_result_3; })); } _if_result_2; })); } _if_result_1; });
el_val_t sal = ({ el_val_t _if_result_14 = 0; if (str_eq(sal_str, EL_STR("0.95"))) { _if_result_14 = (el_from_float(0.95)); } else { _if_result_14 = (({ el_val_t _if_result_15 = 0; if (str_eq(sal_str, EL_STR("0.75"))) { _if_result_15 = (el_from_float(0.75)); } else { _if_result_15 = (({ el_val_t _if_result_16 = 0; if (str_eq(sal_str, EL_STR("0.25"))) { _if_result_16 = (el_from_float(0.25)); } else { _if_result_16 = (el_from_float(0.5)); } _if_result_16; })); } _if_result_15; })); } _if_result_14; }); el_val_t sal = ({ el_val_t _if_result_4 = 0; if (str_eq(sal_str, EL_STR("0.95"))) { _if_result_4 = (el_from_float(0.95)); } else { _if_result_4 = (({ el_val_t _if_result_5 = 0; if (str_eq(sal_str, EL_STR("0.75"))) { _if_result_5 = (el_from_float(0.75)); } else { _if_result_5 = (({ el_val_t _if_result_6 = 0; if (str_eq(sal_str, EL_STR("0.25"))) { _if_result_6 = (el_from_float(0.25)); } else { _if_result_6 = (el_from_float(0.5)); } _if_result_6; })); } _if_result_5; })); } _if_result_4; });
el_val_t base_tags = ({ el_val_t _if_result_17 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_17 = (EL_STR("[\"Memory\"]")); } else { _if_result_17 = (tags_raw); } _if_result_17; }); el_val_t base_tags = ({ el_val_t _if_result_7 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_7 = (EL_STR("[\"Memory\"]")); } else { _if_result_7 = (tags_raw); } _if_result_7; });
el_val_t final_tags = ({ el_val_t _if_result_18 = 0; if (str_eq(project, EL_STR(""))) { _if_result_18 = (base_tags); } else { el_val_t inner = str_slice(base_tags, 1, (str_len(base_tags) - 1)); _if_result_18 = (el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("["), inner), EL_STR(",\"project:")), project), EL_STR("\"]"))); } _if_result_18; }); el_val_t final_tags = ({ el_val_t _if_result_8 = 0; if (str_eq(project, EL_STR(""))) { _if_result_8 = (base_tags); } else { el_val_t inner = str_slice(base_tags, 1, (str_len(base_tags) - 1)); _if_result_8 = (el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("["), inner), EL_STR(",\"project:")), project), EL_STR("\"]"))); } _if_result_8; });
el_val_t id = engram_node_full(content, EL_STR("Memory"), EL_STR("memory:remembered"), el_from_float(sal), el_from_float(sal), el_from_float(0.9), EL_STR("Episodic"), final_tags); el_val_t id = engram_node_full(content, EL_STR("Memory"), EL_STR("memory:remembered"), el_from_float(sal), el_from_float(sal), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), final_tags);
if (!api_persisted(id)) {
return api_not_persisted(id);
}
return el_str_concat(el_str_concat(EL_STR("{\"id\":\""), id), EL_STR("\",\"ok\":true}")); return el_str_concat(el_str_concat(EL_STR("{\"id\":\""), id), EL_STR("\",\"ok\":true}"));
return 0; return 0;
} }
el_val_t handle_api_node_create(el_val_t body) {
el_val_t content = json_get(body, EL_STR("content"));
if (str_eq(content, EL_STR(""))) {
return api_err(EL_STR("content is required"));
}
el_val_t nt_raw = json_get(body, EL_STR("node_type"));
el_val_t node_type = ({ el_val_t _if_result_19 = 0; if (str_eq(nt_raw, EL_STR(""))) { _if_result_19 = (EL_STR("Memory")); } else { _if_result_19 = (nt_raw); } _if_result_19; });
el_val_t label_raw = json_get(body, EL_STR("label"));
el_val_t label = ({ el_val_t _if_result_20 = 0; if (str_eq(label_raw, EL_STR(""))) { _if_result_20 = (EL_STR("node:created")); } else { _if_result_20 = (label_raw); } _if_result_20; });
el_val_t tier_raw = json_get(body, EL_STR("tier"));
el_val_t tier = ({ el_val_t _if_result_21 = 0; if (str_eq(tier_raw, EL_STR(""))) { _if_result_21 = (EL_STR("Episodic")); } else { _if_result_21 = (tier_raw); } _if_result_21; });
el_val_t tags_raw = json_get(body, EL_STR("tags"));
el_val_t tags = ({ el_val_t _if_result_22 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_22 = (el_str_concat(el_str_concat(EL_STR("[\""), node_type), EL_STR("\"]"))); } else { _if_result_22 = (tags_raw); } _if_result_22; });
el_val_t importance = json_get(body, EL_STR("importance"));
el_val_t sal = ({ el_val_t _if_result_23 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_23 = (el_from_float(0.95)); } else { _if_result_23 = (({ el_val_t _if_result_24 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_24 = (el_from_float(0.75)); } else { _if_result_24 = (({ el_val_t _if_result_25 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_25 = (el_from_float(0.25)); } else { _if_result_25 = (el_from_float(0.5)); } _if_result_25; })); } _if_result_24; })); } _if_result_23; });
el_val_t id = engram_node_full(content, node_type, label, el_from_float(sal), el_from_float(sal), el_from_float(0.9), tier, tags);
if (!api_persisted(id)) {
return api_not_persisted(id);
}
return el_str_concat(el_str_concat(EL_STR("{\"id\":\""), id), EL_STR("\",\"ok\":true}"));
return 0;
}
el_val_t handle_api_node_delete(el_val_t body) {
el_val_t id = json_get(body, EL_STR("id"));
if (str_eq(id, EL_STR(""))) {
return api_err(EL_STR("id is required"));
}
if (is_protected_node(id)) {
return api_err_protected(id);
}
el_val_t existing = engram_get_node_json(id);
if (str_eq(existing, EL_STR("{}"))) {
return api_err(el_str_concat(EL_STR("node not found: "), id));
}
el_val_t marker = tombstone_node(id);
if (str_eq(marker, EL_STR(""))) {
return api_err(el_str_concat(EL_STR("tombstone failed: "), id));
}
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\",\"tombstoned\":true}"));
return 0;
}
el_val_t handle_api_node_update(el_val_t body) {
el_val_t id = json_get(body, EL_STR("id"));
if (str_eq(id, EL_STR(""))) {
return api_err(EL_STR("id is required"));
}
if (!api_persisted(id)) {
return el_str_concat(el_str_concat(EL_STR("{\"ok\":false,\"error\":\"not_found\",\"id\":\""), id), EL_STR("\"}"));
}
el_val_t old = engram_get_node_json(id);
el_val_t body_content = json_get(body, EL_STR("content"));
el_val_t content = ({ el_val_t _if_result_26 = 0; if (str_eq(body_content, EL_STR(""))) { _if_result_26 = (json_get(old, EL_STR("content"))); } else { _if_result_26 = (body_content); } _if_result_26; });
el_val_t body_nt = json_get(body, EL_STR("node_type"));
el_val_t old_nt = json_get(old, EL_STR("node_type"));
el_val_t node_type = ({ el_val_t _if_result_27 = 0; if (!str_eq(body_nt, EL_STR(""))) { _if_result_27 = (body_nt); } else { _if_result_27 = (({ el_val_t _if_result_28 = 0; if (!str_eq(old_nt, EL_STR(""))) { _if_result_28 = (old_nt); } else { _if_result_28 = (EL_STR("Memory")); } _if_result_28; })); } _if_result_27; });
el_val_t body_label = json_get(body, EL_STR("label"));
el_val_t old_label = json_get(old, EL_STR("label"));
el_val_t label = ({ el_val_t _if_result_29 = 0; if (!str_eq(body_label, EL_STR(""))) { _if_result_29 = (body_label); } else { _if_result_29 = (({ el_val_t _if_result_30 = 0; if (!str_eq(old_label, EL_STR(""))) { _if_result_30 = (old_label); } else { _if_result_30 = (EL_STR("node:updated")); } _if_result_30; })); } _if_result_29; });
el_val_t body_tier = json_get(body, EL_STR("tier"));
el_val_t old_tier = json_get(old, EL_STR("tier"));
el_val_t tier = ({ el_val_t _if_result_31 = 0; if (!str_eq(body_tier, EL_STR(""))) { _if_result_31 = (body_tier); } else { _if_result_31 = (({ el_val_t _if_result_32 = 0; if (!str_eq(old_tier, EL_STR(""))) { _if_result_32 = (old_tier); } else { _if_result_32 = (EL_STR("Episodic")); } _if_result_32; })); } _if_result_31; });
el_val_t body_tags = json_get(body, EL_STR("tags"));
el_val_t tags = ({ el_val_t _if_result_33 = 0; if (str_eq(body_tags, EL_STR(""))) { _if_result_33 = (el_str_concat(el_str_concat(EL_STR("[\""), node_type), EL_STR("\"]"))); } else { _if_result_33 = (body_tags); } _if_result_33; });
el_val_t new_id = engram_node_full(content, node_type, label, el_from_float(0.5), el_from_float(0.5), el_from_float(0.8), tier, tags);
if (!api_persisted(new_id)) {
return api_not_persisted(new_id);
}
engram_connect(new_id, id, el_from_float(0.9), EL_STR("supersedes"));
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), id), EL_STR("\",\"ok\":true}"));
return 0;
}
el_val_t handle_api_recall(el_val_t method, el_val_t path, el_val_t body) { el_val_t handle_api_recall(el_val_t method, el_val_t path, el_val_t body) {
el_val_t url_q = ({ el_val_t _if_result_34 = 0; if (str_eq(api_query_param(path, EL_STR("query")), EL_STR(""))) { _if_result_34 = (api_query_param(path, EL_STR("q"))); } else { _if_result_34 = (api_query_param(path, EL_STR("query"))); } _if_result_34; }); el_val_t q = ({ el_val_t _if_result_9 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_9 = (api_query_param(path, EL_STR("query"))); } else { _if_result_9 = (json_get(body, EL_STR("query"))); } _if_result_9; });
el_val_t body_query = json_get(body, EL_STR("query"));
el_val_t body_q = json_get(body, EL_STR("q"));
el_val_t q = ({ el_val_t _if_result_35 = 0; if (!str_eq(url_q, EL_STR(""))) { _if_result_35 = (url_q); } else { _if_result_35 = (({ el_val_t _if_result_36 = 0; if (!str_eq(body_query, EL_STR(""))) { _if_result_36 = (body_query); } else { _if_result_36 = (body_q); } _if_result_36; })); } _if_result_35; });
el_val_t chain = json_get(body, EL_STR("chain_name")); el_val_t chain = json_get(body, EL_STR("chain_name"));
el_val_t limit = api_query_int(path, EL_STR("limit"), 0); el_val_t limit = api_query_int(path, EL_STR("limit"), 0);
limit = ({ el_val_t _if_result_37 = 0; if ((limit == 0)) { _if_result_37 = (json_get_int(body, EL_STR("limit"))); } else { _if_result_37 = (limit); } _if_result_37; }); limit = ({ el_val_t _if_result_10 = 0; if ((limit == 0)) { _if_result_10 = (json_get_int(body, EL_STR("limit"))); } else { _if_result_10 = (limit); } _if_result_10; });
limit = ({ el_val_t _if_result_38 = 0; if ((limit == 0)) { _if_result_38 = (10); } else { _if_result_38 = (limit); } _if_result_38; }); limit = ({ el_val_t _if_result_11 = 0; if ((limit == 0)) { _if_result_11 = (10); } else { _if_result_11 = (limit); } _if_result_11; });
el_val_t eff_q = ({ el_val_t _if_result_39 = 0; if (str_eq(q, EL_STR(""))) { _if_result_39 = (chain); } else { _if_result_39 = (q); } _if_result_39; }); el_val_t eff_q = ({ el_val_t _if_result_12 = 0; if (str_eq(q, EL_STR(""))) { _if_result_12 = (chain); } else { _if_result_12 = (q); } _if_result_12; });
if (str_eq(eff_q, EL_STR(""))) { if (str_eq(eff_q, EL_STR(""))) {
return api_or_empty(engram_scan_nodes_json(limit, 0)); return api_or_empty(engram_scan_nodes_json(limit, 0));
} }
@@ -461,13 +323,10 @@ el_val_t handle_api_recall(el_val_t method, el_val_t path, el_val_t body) {
} }
el_val_t handle_api_search_knowledge(el_val_t method, el_val_t path, el_val_t body) { el_val_t handle_api_search_knowledge(el_val_t method, el_val_t path, el_val_t body) {
el_val_t url_q = api_query_param(path, EL_STR("q")); el_val_t q = ({ el_val_t _if_result_13 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_13 = (api_query_param(path, EL_STR("q"))); } else { _if_result_13 = (json_get(body, EL_STR("query"))); } _if_result_13; });
el_val_t body_query = json_get(body, EL_STR("query"));
el_val_t body_q = json_get(body, EL_STR("q"));
el_val_t q = ({ el_val_t _if_result_40 = 0; if (!str_eq(url_q, EL_STR(""))) { _if_result_40 = (url_q); } else { _if_result_40 = (({ el_val_t _if_result_41 = 0; if (!str_eq(body_query, EL_STR(""))) { _if_result_41 = (body_query); } else { _if_result_41 = (body_q); } _if_result_41; })); } _if_result_40; });
el_val_t limit = api_query_int(path, EL_STR("limit"), 0); el_val_t limit = api_query_int(path, EL_STR("limit"), 0);
limit = ({ el_val_t _if_result_42 = 0; if ((limit == 0)) { _if_result_42 = (json_get_int(body, EL_STR("limit"))); } else { _if_result_42 = (limit); } _if_result_42; }); limit = ({ el_val_t _if_result_14 = 0; if ((limit == 0)) { _if_result_14 = (json_get_int(body, EL_STR("limit"))); } else { _if_result_14 = (limit); } _if_result_14; });
limit = ({ el_val_t _if_result_43 = 0; if ((limit == 0)) { _if_result_43 = (10); } else { _if_result_43 = (limit); } _if_result_43; }); limit = ({ el_val_t _if_result_15 = 0; if ((limit == 0)) { _if_result_15 = (10); } else { _if_result_15 = (limit); } _if_result_15; });
if (str_eq(q, EL_STR(""))) { if (str_eq(q, EL_STR(""))) {
return api_err(EL_STR("query is required")); return api_err(EL_STR("query is required"));
} }
@@ -495,12 +354,9 @@ el_val_t handle_api_capture_knowledge(el_val_t body) {
if (str_eq(content, EL_STR(""))) { if (str_eq(content, EL_STR(""))) {
return api_err(EL_STR("content is required")); return api_err(EL_STR("content is required"));
} }
el_val_t full = ({ el_val_t _if_result_44 = 0; if (str_eq(title, EL_STR(""))) { _if_result_44 = (content); } else { _if_result_44 = (el_str_concat(el_str_concat(title, EL_STR(": ")), content)); } _if_result_44; }); el_val_t full = ({ el_val_t _if_result_16 = 0; if (str_eq(title, EL_STR(""))) { _if_result_16 = (content); } else { _if_result_16 = (el_str_concat(el_str_concat(title, EL_STR(": ")), content)); } _if_result_16; });
el_val_t tags = EL_STR("[\"Knowledge\",\"captured\"]"); el_val_t tags = EL_STR("[\"Knowledge\",\"captured\"]");
el_val_t id = engram_node_full(full, EL_STR("Knowledge"), EL_STR("knowledge:captured"), el_from_float(0.85), el_from_float(0.8), el_from_float(0.9), EL_STR("Episodic"), tags); el_val_t id = engram_node_full(full, EL_STR("Knowledge"), EL_STR("knowledge:captured"), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
if (!api_persisted(id)) {
return api_not_persisted(id);
}
return el_str_concat(el_str_concat(EL_STR("{\"id\":\""), id), EL_STR("\",\"ok\":true}")); return el_str_concat(el_str_concat(EL_STR("{\"id\":\""), id), EL_STR("\",\"ok\":true}"));
return 0; return 0;
} }
@@ -515,12 +371,9 @@ el_val_t handle_api_evolve_knowledge(el_val_t body) {
return api_err_protected(prior_id); return api_err_protected(prior_id);
} }
el_val_t tags = EL_STR("[\"Knowledge\",\"evolved\"]"); el_val_t tags = EL_STR("[\"Knowledge\",\"evolved\"]");
el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), EL_STR("knowledge:evolved"), el_from_float(0.75), el_from_float(0.75), el_from_float(0.9), EL_STR("Episodic"), tags); el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), EL_STR("knowledge:evolved"), el_from_float(el_from_float(0.75)), el_from_float(el_from_float(0.75)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
if (!api_persisted(new_id)) { if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) {
return api_not_persisted(new_id); engram_connect(new_id, prior_id, el_from_float(el_from_float(0.9)), EL_STR("supersedes"));
}
if (!str_eq(prior_id, EL_STR(""))) {
engram_connect(new_id, prior_id, el_from_float(0.9), EL_STR("supersedes"));
} }
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true}"));
return 0; return 0;
@@ -536,18 +389,18 @@ el_val_t handle_api_promote_knowledge(el_val_t body) {
return api_err(EL_STR("id (prior node) is required")); return api_err(EL_STR("id (prior node) is required"));
} }
el_val_t tags_raw = json_get(body, EL_STR("tags")); el_val_t tags_raw = json_get(body, EL_STR("tags"));
el_val_t tags = ({ el_val_t _if_result_45 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_45 = (EL_STR("[\"Knowledge\",\"tier:canonical\",\"disposition:stable\"]")); } else { _if_result_45 = (tags_raw); } _if_result_45; }); el_val_t tags = ({ el_val_t _if_result_17 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_17 = (EL_STR("[\"Knowledge\",\"tier:canonical\",\"disposition:stable\"]")); } else { _if_result_17 = (tags_raw); } _if_result_17; });
el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), EL_STR("knowledge:canonical"), el_from_float(0.9), el_from_float(0.9), el_from_float(1.0), EL_STR("Canonical"), tags); el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), EL_STR("knowledge:canonical"), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(1.0)), EL_STR("Canonical"), tags);
if (!api_persisted(new_id)) { if (str_eq(new_id, EL_STR(""))) {
return api_not_persisted(new_id); return api_err(EL_STR("failed to create canonical node"));
} }
engram_connect(new_id, prior_id, el_from_float(0.95), EL_STR("supersedes")); engram_connect(new_id, prior_id, el_from_float(el_from_float(0.95)), EL_STR("supersedes"));
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"new_id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\"}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"new_id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\"}"));
return 0; return 0;
} }
el_val_t handle_api_browse_processes(el_val_t method, el_val_t path, el_val_t body) { el_val_t handle_api_browse_processes(el_val_t method, el_val_t path, el_val_t body) {
el_val_t name = ({ el_val_t _if_result_46 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_46 = (api_query_param(path, EL_STR("name"))); } else { _if_result_46 = (json_get(body, EL_STR("name"))); } _if_result_46; }); el_val_t name = ({ el_val_t _if_result_18 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_18 = (api_query_param(path, EL_STR("name"))); } else { _if_result_18 = (json_get(body, EL_STR("name"))); } _if_result_18; });
el_val_t limit = api_query_int(path, EL_STR("limit"), 50); el_val_t limit = api_query_int(path, EL_STR("limit"), 50);
if (str_eq(name, EL_STR(""))) { if (str_eq(name, EL_STR(""))) {
return api_or_empty(engram_scan_nodes_by_type_json(EL_STR("Process"), limit, 0)); return api_or_empty(engram_scan_nodes_by_type_json(EL_STR("Process"), limit, 0));
@@ -562,12 +415,9 @@ el_val_t handle_api_define_process(el_val_t body) {
if (str_eq(content, EL_STR(""))) { if (str_eq(content, EL_STR(""))) {
return api_err(EL_STR("content is required")); return api_err(EL_STR("content is required"));
} }
el_val_t label = ({ el_val_t _if_result_47 = 0; if (str_eq(name, EL_STR(""))) { _if_result_47 = (EL_STR("process:unnamed")); } else { _if_result_47 = (el_str_concat(EL_STR("process:"), name)); } _if_result_47; }); el_val_t label = ({ el_val_t _if_result_19 = 0; if (str_eq(name, EL_STR(""))) { _if_result_19 = (EL_STR("process:unnamed")); } else { _if_result_19 = (el_str_concat(EL_STR("process:"), name)); } _if_result_19; });
el_val_t tags = EL_STR("[\"Process\"]"); el_val_t tags = EL_STR("[\"Process\"]");
el_val_t id = engram_node_full(content, EL_STR("Process"), label, el_from_float(0.8), el_from_float(0.8), el_from_float(0.9), EL_STR("Canonical"), tags); el_val_t id = engram_node_full(content, EL_STR("Process"), label, el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.9)), EL_STR("Canonical"), tags);
if (!api_persisted(id)) {
return api_not_persisted(id);
}
return el_str_concat(el_str_concat(EL_STR("{\"id\":\""), id), EL_STR("\",\"ok\":true}")); return el_str_concat(el_str_concat(EL_STR("{\"id\":\""), id), EL_STR("\",\"ok\":true}"));
return 0; return 0;
} }
@@ -580,25 +430,22 @@ el_val_t handle_api_log_state_event(el_val_t body) {
el_val_t gap = json_get(body, EL_STR("gap_direction")); el_val_t gap = json_get(body, EL_STR("gap_direction"));
el_val_t legacy = json_get(body, EL_STR("content")); el_val_t legacy = json_get(body, EL_STR("content"));
el_val_t parts = EL_STR("INTERNAL STATE EVENT"); el_val_t parts = EL_STR("INTERNAL STATE EVENT");
parts = ({ el_val_t _if_result_48 = 0; if (!str_eq(trigger, EL_STR(""))) { _if_result_48 = (el_str_concat(el_str_concat(parts, EL_STR("\nTrigger: ")), trigger)); } else { _if_result_48 = (parts); } _if_result_48; }); parts = ({ el_val_t _if_result_20 = 0; if (!str_eq(trigger, EL_STR(""))) { _if_result_20 = (el_str_concat(el_str_concat(parts, EL_STR("\nTrigger: ")), trigger)); } else { _if_result_20 = (parts); } _if_result_20; });
parts = ({ el_val_t _if_result_49 = 0; if (!str_eq(pre, EL_STR(""))) { _if_result_49 = (el_str_concat(el_str_concat(parts, EL_STR("\nPre-reasoning: ")), pre)); } else { _if_result_49 = (parts); } _if_result_49; }); parts = ({ el_val_t _if_result_21 = 0; if (!str_eq(pre, EL_STR(""))) { _if_result_21 = (el_str_concat(el_str_concat(parts, EL_STR("\nPre-reasoning: ")), pre)); } else { _if_result_21 = (parts); } _if_result_21; });
parts = ({ el_val_t _if_result_50 = 0; if (!str_eq(post, EL_STR(""))) { _if_result_50 = (el_str_concat(el_str_concat(parts, EL_STR("\nPost-reasoning: ")), post)); } else { _if_result_50 = (parts); } _if_result_50; }); parts = ({ el_val_t _if_result_22 = 0; if (!str_eq(post, EL_STR(""))) { _if_result_22 = (el_str_concat(el_str_concat(parts, EL_STR("\nPost-reasoning: ")), post)); } else { _if_result_22 = (parts); } _if_result_22; });
parts = ({ el_val_t _if_result_51 = 0; if (!str_eq(ratio, EL_STR(""))) { _if_result_51 = (el_str_concat(el_str_concat(parts, EL_STR("\nCompression-ratio: ")), ratio)); } else { _if_result_51 = (parts); } _if_result_51; }); parts = ({ el_val_t _if_result_23 = 0; if (!str_eq(ratio, EL_STR(""))) { _if_result_23 = (el_str_concat(el_str_concat(parts, EL_STR("\nCompression-ratio: ")), ratio)); } else { _if_result_23 = (parts); } _if_result_23; });
parts = ({ el_val_t _if_result_52 = 0; if (!str_eq(gap, EL_STR(""))) { _if_result_52 = (el_str_concat(el_str_concat(parts, EL_STR("\nGap-direction: ")), gap)); } else { _if_result_52 = (parts); } _if_result_52; }); parts = ({ el_val_t _if_result_24 = 0; if (!str_eq(gap, EL_STR(""))) { _if_result_24 = (el_str_concat(el_str_concat(parts, EL_STR("\nGap-direction: ")), gap)); } else { _if_result_24 = (parts); } _if_result_24; });
parts = ({ el_val_t _if_result_53 = 0; if (!str_eq(legacy, EL_STR(""))) { _if_result_53 = (el_str_concat(el_str_concat(parts, EL_STR("\n")), legacy)); } else { _if_result_53 = (parts); } _if_result_53; }); parts = ({ el_val_t _if_result_25 = 0; if (!str_eq(legacy, EL_STR(""))) { _if_result_25 = (el_str_concat(el_str_concat(parts, EL_STR("\n")), legacy)); } else { _if_result_25 = (parts); } _if_result_25; });
el_val_t ts = time_now(); el_val_t ts = time_now();
el_val_t boot = state_get(EL_STR("soul_boot_count")); el_val_t boot = state_get(EL_STR("soul_boot_count"));
el_val_t tags = EL_STR("[\"internal-state\",\"InternalStateEvent\",\"pre-reasoning\"]"); el_val_t tags = EL_STR("[\"internal-state\",\"InternalStateEvent\",\"pre-reasoning\"]");
el_val_t id = engram_node_full(parts, EL_STR("InternalStateEvent"), EL_STR("state-event:manual"), el_from_float(0.85), el_from_float(0.85), el_from_float(0.9), EL_STR("Episodic"), tags); el_val_t id = engram_node_full(parts, EL_STR("InternalStateEvent"), EL_STR("state-event:manual"), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
if (!api_persisted(id)) {
return api_not_persisted(id);
}
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\",\"boot\":\"")), boot), EL_STR("\"}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\",\"boot\":\"")), boot), EL_STR("\"}"));
return 0; return 0;
} }
el_val_t handle_api_list_state_events(el_val_t method, el_val_t path, el_val_t body) { el_val_t handle_api_list_state_events(el_val_t method, el_val_t path, el_val_t body) {
el_val_t q = ({ el_val_t _if_result_54 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_54 = (api_query_param(path, EL_STR("query"))); } else { _if_result_54 = (json_get(body, EL_STR("query"))); } _if_result_54; }); el_val_t q = ({ el_val_t _if_result_26 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_26 = (api_query_param(path, EL_STR("query"))); } else { _if_result_26 = (json_get(body, EL_STR("query"))); } _if_result_26; });
el_val_t limit = api_query_int(path, EL_STR("limit"), 20); el_val_t limit = api_query_int(path, EL_STR("limit"), 20);
if (!str_eq(q, EL_STR(""))) { if (!str_eq(q, EL_STR(""))) {
return api_or_empty(engram_search_json(el_str_concat(EL_STR("internal state "), q), limit)); return api_or_empty(engram_search_json(el_str_concat(EL_STR("internal state "), q), limit));
@@ -609,7 +456,7 @@ el_val_t handle_api_list_state_events(el_val_t method, el_val_t path, el_val_t b
el_val_t handle_api_inspect_config(el_val_t path, el_val_t body) { el_val_t handle_api_inspect_config(el_val_t path, el_val_t body) {
el_val_t key = api_query_param(path, EL_STR("key")); el_val_t key = api_query_param(path, EL_STR("key"));
key = ({ el_val_t _if_result_55 = 0; if (str_eq(key, EL_STR(""))) { _if_result_55 = (json_get(body, EL_STR("key"))); } else { _if_result_55 = (key); } _if_result_55; }); key = ({ el_val_t _if_result_27 = 0; if (str_eq(key, EL_STR(""))) { _if_result_27 = (json_get(body, EL_STR("key"))); } else { _if_result_27 = (key); } _if_result_27; });
if (str_eq(key, EL_STR(""))) { if (str_eq(key, EL_STR(""))) {
return EL_STR("{\"hint\":\"pass ?key=<name>\",\"known\":[\"neuron.self.traversal_root\",\"neuron.self.values_hub\"]}"); return EL_STR("{\"hint\":\"pass ?key=<name>\",\"known\":[\"neuron.self.traversal_root\",\"neuron.self.values_hub\"]}");
} }
@@ -626,7 +473,7 @@ el_val_t handle_api_inspect_config(el_val_t path, el_val_t body) {
el_val_t node = json_array_get(results, 0); el_val_t node = json_array_get(results, 0);
el_val_t content = json_get(node, EL_STR("content")); el_val_t content = json_get(node, EL_STR("content"));
el_val_t prefix = el_str_concat(el_str_concat(EL_STR("config:"), key), EL_STR("=")); el_val_t prefix = el_str_concat(el_str_concat(EL_STR("config:"), key), EL_STR("="));
el_val_t value = ({ el_val_t _if_result_56 = 0; if (str_starts_with(content, prefix)) { _if_result_56 = (str_slice(content, str_len(prefix), str_len(content))); } else { _if_result_56 = (content); } _if_result_56; }); el_val_t value = ({ el_val_t _if_result_28 = 0; if (str_starts_with(content, prefix)) { _if_result_28 = (str_slice(content, str_len(prefix), str_len(content))); } else { _if_result_28 = (content); } _if_result_28; });
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"key\":\""), key), EL_STR("\",\"value\":\"")), value), EL_STR("\"}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"key\":\""), key), EL_STR("\",\"value\":\"")), value), EL_STR("\"}"));
return 0; return 0;
} }
@@ -639,22 +486,19 @@ el_val_t handle_api_tune_config(el_val_t body) {
} }
el_val_t content = el_str_concat(el_str_concat(el_str_concat(EL_STR("config:"), key), EL_STR("=")), value); el_val_t content = el_str_concat(el_str_concat(el_str_concat(EL_STR("config:"), key), EL_STR("=")), value);
el_val_t tags = EL_STR("[\"ConfigEntry\",\"config\"]"); el_val_t tags = EL_STR("[\"ConfigEntry\",\"config\"]");
el_val_t id = engram_node_full(content, EL_STR("ConfigEntry"), key, el_from_float(0.85), el_from_float(0.85), el_from_float(0.9), EL_STR("Canonical"), tags); el_val_t id = engram_node_full(content, EL_STR("ConfigEntry"), key, el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.9)), EL_STR("Canonical"), tags);
if (!api_persisted(id)) {
return api_not_persisted(id);
}
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"key\":\""), key), EL_STR("\",\"value\":\"")), value), EL_STR("\",\"id\":\"")), id), EL_STR("\"}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"key\":\""), key), EL_STR("\",\"value\":\"")), value), EL_STR("\",\"id\":\"")), id), EL_STR("\"}"));
return 0; return 0;
} }
el_val_t handle_api_inspect_graph(el_val_t method, el_val_t path, el_val_t body) { el_val_t handle_api_inspect_graph(el_val_t method, el_val_t path, el_val_t body) {
el_val_t entity_id = ({ el_val_t _if_result_57 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_57 = (api_query_param(path, EL_STR("id"))); } else { _if_result_57 = (json_get(body, EL_STR("entity_id"))); } _if_result_57; }); el_val_t entity_id = ({ el_val_t _if_result_29 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_29 = (api_query_param(path, EL_STR("id"))); } else { _if_result_29 = (json_get(body, EL_STR("entity_id"))); } _if_result_29; });
el_val_t name = ({ el_val_t _if_result_58 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_58 = (api_query_param(path, EL_STR("name"))); } else { _if_result_58 = (json_get(body, EL_STR("name"))); } _if_result_58; }); el_val_t name = ({ el_val_t _if_result_30 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_30 = (api_query_param(path, EL_STR("name"))); } else { _if_result_30 = (json_get(body, EL_STR("name"))); } _if_result_30; });
el_val_t depth = api_query_int(path, EL_STR("depth"), 0); el_val_t depth = api_query_int(path, EL_STR("depth"), 0);
depth = ({ el_val_t _if_result_59 = 0; if ((depth == 0)) { _if_result_59 = (json_get_int(body, EL_STR("max_depth"))); } else { _if_result_59 = (depth); } _if_result_59; }); depth = ({ el_val_t _if_result_31 = 0; if ((depth == 0)) { _if_result_31 = (json_get_int(body, EL_STR("max_depth"))); } else { _if_result_31 = (depth); } _if_result_31; });
depth = ({ el_val_t _if_result_60 = 0; if ((depth == 0)) { _if_result_60 = (1); } else { _if_result_60 = (depth); } _if_result_60; }); depth = ({ el_val_t _if_result_32 = 0; if ((depth == 0)) { _if_result_32 = (1); } else { _if_result_32 = (depth); } _if_result_32; });
el_val_t resolved = entity_id; el_val_t resolved = entity_id;
resolved = ({ el_val_t _if_result_61 = 0; if (str_eq(resolved, EL_STR(""))) { _if_result_61 = (({ el_val_t _if_result_62 = 0; if ((str_eq(name, EL_STR("self")) || str_eq(name, EL_STR("neuron")))) { _if_result_62 = (EL_STR("kn-efeb4a5b-5aff-4759-8a97-7233099be6ee")); } else { _if_result_62 = (({ el_val_t _if_result_63 = 0; if ((str_eq(name, EL_STR("values")) || str_eq(name, EL_STR("values_hub")))) { _if_result_63 = (EL_STR("kn-5b606390-a52d-4ca2-8e0e-eba141d13440")); } else { _if_result_63 = (EL_STR("")); } _if_result_63; })); } _if_result_62; })); } else { _if_result_61 = (resolved); } _if_result_61; }); resolved = ({ el_val_t _if_result_33 = 0; if (str_eq(resolved, EL_STR(""))) { _if_result_33 = (({ el_val_t _if_result_34 = 0; if ((str_eq(name, EL_STR("self")) || str_eq(name, EL_STR("neuron")))) { _if_result_34 = (EL_STR("kn-efeb4a5b-5aff-4759-8a97-7233099be6ee")); } else { _if_result_34 = (({ el_val_t _if_result_35 = 0; if ((str_eq(name, EL_STR("values")) || str_eq(name, EL_STR("values_hub")))) { _if_result_35 = (EL_STR("kn-5b606390-a52d-4ca2-8e0e-eba141d13440")); } else { _if_result_35 = (EL_STR("")); } _if_result_35; })); } _if_result_34; })); } else { _if_result_33 = (resolved); } _if_result_33; });
if (str_eq(resolved, EL_STR(""))) { if (str_eq(resolved, EL_STR(""))) {
return api_err(EL_STR("entity_id or name required. Known names: self, neuron, values, values_hub")); return api_err(EL_STR("entity_id or name required. Known names: self, neuron, values, values_hub"));
} }
@@ -676,8 +520,8 @@ el_val_t handle_api_link_entities(el_val_t body) {
return api_err_protected(to_id); return api_err_protected(to_id);
} }
el_val_t relation = json_get(body, EL_STR("relation")); el_val_t relation = json_get(body, EL_STR("relation"));
el_val_t eff_relation = ({ el_val_t _if_result_64 = 0; if (str_eq(relation, EL_STR(""))) { _if_result_64 = (EL_STR("associates")); } else { _if_result_64 = (relation); } _if_result_64; }); el_val_t eff_relation = ({ el_val_t _if_result_36 = 0; if (str_eq(relation, EL_STR(""))) { _if_result_36 = (EL_STR("associates")); } else { _if_result_36 = (relation); } _if_result_36; });
engram_connect(from_id, to_id, el_from_float(0.5), eff_relation); engram_connect(from_id, to_id, el_from_float(el_from_float(0.5)), eff_relation);
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"from_id\":\""), from_id), EL_STR("\",\"to_id\":\"")), to_id), EL_STR("\",\"relation\":\"")), eff_relation), EL_STR("\"}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"from_id\":\""), from_id), EL_STR("\",\"to_id\":\"")), to_id), EL_STR("\",\"relation\":\"")), eff_relation), EL_STR("\"}"));
return 0; return 0;
} }
@@ -691,7 +535,7 @@ el_val_t handle_api_forget(el_val_t body) {
return api_err_protected(node_id); return api_err_protected(node_id);
} }
mem_forget(node_id); mem_forget(node_id);
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), node_id), EL_STR("\",\"tombstoned\":true}")); return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), node_id), EL_STR("\"}"));
return 0; return 0;
} }
@@ -705,57 +549,17 @@ el_val_t handle_api_evolve_memory(el_val_t body) {
return api_err_protected(prior_id); return api_err_protected(prior_id);
} }
el_val_t importance = json_get(body, EL_STR("importance")); el_val_t importance = json_get(body, EL_STR("importance"));
el_val_t sal_str = ({ el_val_t _if_result_65 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_65 = (EL_STR("0.95")); } else { _if_result_65 = (({ el_val_t _if_result_66 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_66 = (EL_STR("0.75")); } else { _if_result_66 = (({ el_val_t _if_result_67 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_67 = (EL_STR("0.25")); } else { _if_result_67 = (EL_STR("0.50")); } _if_result_67; })); } _if_result_66; })); } _if_result_65; }); el_val_t sal_str = ({ el_val_t _if_result_37 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_37 = (EL_STR("0.95")); } else { _if_result_37 = (({ el_val_t _if_result_38 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_38 = (EL_STR("0.75")); } else { _if_result_38 = (({ el_val_t _if_result_39 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_39 = (EL_STR("0.25")); } else { _if_result_39 = (EL_STR("0.50")); } _if_result_39; })); } _if_result_38; })); } _if_result_37; });
el_val_t sal = ({ el_val_t _if_result_68 = 0; if (str_eq(sal_str, EL_STR("0.95"))) { _if_result_68 = (el_from_float(0.95)); } else { _if_result_68 = (({ el_val_t _if_result_69 = 0; if (str_eq(sal_str, EL_STR("0.75"))) { _if_result_69 = (el_from_float(0.75)); } else { _if_result_69 = (({ el_val_t _if_result_70 = 0; if (str_eq(sal_str, EL_STR("0.25"))) { _if_result_70 = (el_from_float(0.25)); } else { _if_result_70 = (el_from_float(0.5)); } _if_result_70; })); } _if_result_69; })); } _if_result_68; }); el_val_t sal = ({ el_val_t _if_result_40 = 0; if (str_eq(sal_str, EL_STR("0.95"))) { _if_result_40 = (el_from_float(0.95)); } else { _if_result_40 = (({ el_val_t _if_result_41 = 0; if (str_eq(sal_str, EL_STR("0.75"))) { _if_result_41 = (el_from_float(0.75)); } else { _if_result_41 = (({ el_val_t _if_result_42 = 0; if (str_eq(sal_str, EL_STR("0.25"))) { _if_result_42 = (el_from_float(0.25)); } else { _if_result_42 = (el_from_float(0.5)); } _if_result_42; })); } _if_result_41; })); } _if_result_40; });
el_val_t tags = EL_STR("[\"Memory\",\"evolved\"]"); el_val_t tags = EL_STR("[\"Memory\",\"evolved\"]");
el_val_t new_id = engram_node_full(content, EL_STR("Memory"), EL_STR("memory:evolved"), el_from_float(sal), el_from_float(sal), el_from_float(0.9), EL_STR("Episodic"), tags); el_val_t new_id = engram_node_full(content, EL_STR("Memory"), EL_STR("memory:evolved"), el_from_float(sal), el_from_float(sal), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) { if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) {
engram_connect(new_id, prior_id, el_from_float(0.9), EL_STR("supersedes")); engram_connect(new_id, prior_id, el_from_float(el_from_float(0.9)), EL_STR("supersedes"));
} }
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true}"));
return 0; return 0;
} }
el_val_t handle_api_memory_delete(el_val_t body) {
el_val_t node_id = json_get(body, EL_STR("id"));
if (str_eq(node_id, EL_STR(""))) {
return api_err(EL_STR("id is required"));
}
if (is_protected_node(node_id)) {
return api_err_protected(node_id);
}
el_val_t existing = engram_get_node_json(node_id);
if (str_eq(existing, EL_STR("{}"))) {
return api_err(el_str_concat(EL_STR("memory not found: "), node_id));
}
el_val_t marker = tombstone_node(node_id);
if (str_eq(marker, EL_STR(""))) {
return api_err(el_str_concat(EL_STR("tombstone failed: "), node_id));
}
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), node_id), EL_STR("\",\"tombstoned\":true}"));
return 0;
}
el_val_t handle_api_memory_update(el_val_t body) {
el_val_t prior_id = json_get(body, EL_STR("id"));
el_val_t content = json_get(body, EL_STR("content"));
if (str_eq(prior_id, EL_STR(""))) {
return api_err(EL_STR("id is required"));
}
if (str_eq(content, EL_STR(""))) {
return api_err(EL_STR("content is required"));
}
if (is_protected_node(prior_id)) {
return api_err_protected(prior_id);
}
el_val_t existing = engram_get_node_json(prior_id);
if (str_eq(existing, EL_STR("{}"))) {
return api_err(el_str_concat(EL_STR("memory not found: "), prior_id));
}
return handle_api_evolve_memory(body);
return 0;
}
el_val_t handle_api_cultivate(el_val_t body) { el_val_t handle_api_cultivate(el_val_t body) {
el_val_t op = json_get(body, EL_STR("operation")); el_val_t op = json_get(body, EL_STR("operation"));
if (str_eq(op, EL_STR(""))) { if (str_eq(op, EL_STR(""))) {
@@ -768,9 +572,9 @@ el_val_t handle_api_cultivate(el_val_t body) {
return api_err(EL_STR("content is required")); return api_err(EL_STR("content is required"));
} }
el_val_t tags = EL_STR("[\"Knowledge\",\"evolved\",\"cultivated\"]"); el_val_t tags = EL_STR("[\"Knowledge\",\"evolved\",\"cultivated\"]");
el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), EL_STR("knowledge:cultivated"), el_from_float(0.75), el_from_float(0.75), el_from_float(0.9), EL_STR("Episodic"), tags); el_val_t new_id = engram_node_full(content, EL_STR("Knowledge"), EL_STR("knowledge:cultivated"), el_from_float(el_from_float(0.75)), el_from_float(el_from_float(0.75)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) { if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) {
engram_connect(new_id, prior_id, el_from_float(0.9), EL_STR("supersedes")); engram_connect(new_id, prior_id, el_from_float(el_from_float(0.9)), EL_STR("supersedes"));
} }
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true,\"cultivated\":true}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true,\"cultivated\":true}"));
} }
@@ -781,11 +585,11 @@ el_val_t handle_api_cultivate(el_val_t body) {
return api_err(EL_STR("content is required")); return api_err(EL_STR("content is required"));
} }
el_val_t importance = json_get(body, EL_STR("importance")); el_val_t importance = json_get(body, EL_STR("importance"));
el_val_t sal = ({ el_val_t _if_result_71 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_71 = (el_from_float(0.95)); } else { _if_result_71 = (({ el_val_t _if_result_72 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_72 = (el_from_float(0.75)); } else { _if_result_72 = (({ el_val_t _if_result_73 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_73 = (el_from_float(0.25)); } else { _if_result_73 = (el_from_float(0.5)); } _if_result_73; })); } _if_result_72; })); } _if_result_71; }); el_val_t sal = ({ el_val_t _if_result_43 = 0; if (str_eq(importance, EL_STR("critical"))) { _if_result_43 = (el_from_float(0.95)); } else { _if_result_43 = (({ el_val_t _if_result_44 = 0; if (str_eq(importance, EL_STR("high"))) { _if_result_44 = (el_from_float(0.75)); } else { _if_result_44 = (({ el_val_t _if_result_45 = 0; if (str_eq(importance, EL_STR("low"))) { _if_result_45 = (el_from_float(0.25)); } else { _if_result_45 = (el_from_float(0.5)); } _if_result_45; })); } _if_result_44; })); } _if_result_43; });
el_val_t tags = EL_STR("[\"Memory\",\"evolved\",\"cultivated\"]"); el_val_t tags = EL_STR("[\"Memory\",\"evolved\",\"cultivated\"]");
el_val_t new_id = engram_node_full(content, EL_STR("Memory"), EL_STR("memory:cultivated"), el_from_float(sal), el_from_float(sal), el_from_float(0.9), EL_STR("Episodic"), tags); el_val_t new_id = engram_node_full(content, EL_STR("Memory"), EL_STR("memory:cultivated"), el_from_float(sal), el_from_float(sal), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) { if (!str_eq(prior_id, EL_STR("")) && !str_eq(new_id, EL_STR(""))) {
engram_connect(new_id, prior_id, el_from_float(0.9), EL_STR("supersedes")); engram_connect(new_id, prior_id, el_from_float(el_from_float(0.9)), EL_STR("supersedes"));
} }
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true,\"cultivated\":true}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), new_id), EL_STR("\",\"supersedes\":\"")), prior_id), EL_STR("\",\"ok\":true,\"cultivated\":true}"));
} }
@@ -795,7 +599,7 @@ el_val_t handle_api_cultivate(el_val_t body) {
return api_err(EL_STR("id is required")); return api_err(EL_STR("id is required"));
} }
mem_forget(node_id); mem_forget(node_id);
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), node_id), EL_STR("\",\"tombstoned\":true,\"cultivated\":true}")); return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), node_id), EL_STR("\",\"cultivated\":true}"));
} }
if (str_eq(op, EL_STR("link_entities"))) { if (str_eq(op, EL_STR("link_entities"))) {
el_val_t from_id = json_get(body, EL_STR("from_id")); el_val_t from_id = json_get(body, EL_STR("from_id"));
@@ -807,8 +611,8 @@ el_val_t handle_api_cultivate(el_val_t body) {
return api_err(EL_STR("to_id is required")); return api_err(EL_STR("to_id is required"));
} }
el_val_t relation = json_get(body, EL_STR("relation")); el_val_t relation = json_get(body, EL_STR("relation"));
el_val_t eff_relation = ({ el_val_t _if_result_74 = 0; if (str_eq(relation, EL_STR(""))) { _if_result_74 = (EL_STR("associates")); } else { _if_result_74 = (relation); } _if_result_74; }); el_val_t eff_relation = ({ el_val_t _if_result_46 = 0; if (str_eq(relation, EL_STR(""))) { _if_result_46 = (EL_STR("associates")); } else { _if_result_46 = (relation); } _if_result_46; });
engram_connect(from_id, to_id, el_from_float(0.5), eff_relation); engram_connect(from_id, to_id, el_from_float(el_from_float(0.5)), eff_relation);
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"from_id\":\""), from_id), EL_STR("\",\"to_id\":\"")), to_id), EL_STR("\",\"relation\":\"")), eff_relation), EL_STR("\",\"cultivated\":true}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"from_id\":\""), from_id), EL_STR("\",\"to_id\":\"")), to_id), EL_STR("\",\"relation\":\"")), eff_relation), EL_STR("\",\"cultivated\":true}"));
} }
return api_err(el_str_concat(el_str_concat(EL_STR("unknown operation: "), op), EL_STR(" (valid: evolve_knowledge, evolve_memory, forget, link_entities)"))); return api_err(el_str_concat(el_str_concat(EL_STR("unknown operation: "), op), EL_STR(" (valid: evolve_knowledge, evolve_memory, forget, link_entities)")));
@@ -817,8 +621,7 @@ el_val_t handle_api_cultivate(el_val_t body) {
el_val_t handle_api_list_typed(el_val_t node_type, el_val_t path, el_val_t body) { el_val_t handle_api_list_typed(el_val_t node_type, el_val_t path, el_val_t body) {
el_val_t limit = api_query_int(path, EL_STR("limit"), 50); el_val_t limit = api_query_int(path, EL_STR("limit"), 50);
el_val_t raw = api_or_empty(engram_scan_nodes_by_type_json(node_type, limit, 0)); return api_or_empty(engram_scan_nodes_by_type_json(node_type, limit, 0));
return memory_hide_tombstoned(raw, path);
return 0; return 0;
} }
@@ -826,20 +629,19 @@ el_val_t handle_api_consolidate(el_val_t body) {
el_val_t summary = json_get(body, EL_STR("summary")); el_val_t summary = json_get(body, EL_STR("summary"));
el_val_t snap = state_get(EL_STR("soul_snapshot_path")); el_val_t snap = state_get(EL_STR("soul_snapshot_path"));
if (!str_eq(snap, EL_STR(""))) { if (!str_eq(snap, EL_STR(""))) {
el_val_t save_result = engram_save(snap); engram_save(snap);
if (str_eq(save_result, EL_STR(""))) {
println(el_str_concat(el_str_concat(EL_STR("[api] consolidate: engram_save failed for "), snap), EL_STR(" \xe2\x80\x94 snapshot may be out of sync")));
}
} }
if (!str_eq(summary, EL_STR(""))) { if (!str_eq(summary, EL_STR(""))) {
el_val_t safe_summary = str_replace(summary, EL_STR("\""), EL_STR("'")); el_val_t safe_summary = str_replace(summary, EL_STR("\""), EL_STR("'"));
el_val_t tags = EL_STR("[\"SessionSummary\",\"consolidate\"]"); el_val_t tags = EL_STR("[\"SessionSummary\",\"consolidate\"]");
el_val_t summary_id = engram_node_full(el_str_concat(EL_STR("[session-summary] "), safe_summary), EL_STR("SessionSummary"), EL_STR("session:summary"), el_from_float(0.7), el_from_float(0.7), el_from_float(0.9), EL_STR("Episodic"), tags); el_val_t discard = engram_node_full(el_str_concat(EL_STR("[session-summary] "), safe_summary), EL_STR("SessionSummary"), EL_STR("session:summary"), el_from_float(el_from_float(0.7)), el_from_float(el_from_float(0.7)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
if (str_eq(summary_id, EL_STR(""))) {
println(EL_STR("[api] consolidate: session summary engram write failed \xe2\x80\x94 summary node lost"));
}
} }
return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"snapshot\":\""), snap), EL_STR("\"}")); return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"snapshot\":\""), snap), EL_STR("\"}"));
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+32
View File
@@ -0,0 +1,32 @@
// auto-generated by elc --emit-header — do not edit
extern fn is_protected_node(id: String) -> Bool
extern fn api_err_protected(id: String) -> String
extern fn api_json_escape(s: String) -> String
extern fn api_query_param(path: String, key: String) -> String
extern fn api_query_int(path: String, key: String, default_val: Int) -> Int
extern fn api_ok(extra: String) -> String
extern fn api_err(msg: String) -> String
extern fn api_nonempty(s: String) -> Bool
extern fn api_or_empty(s: String) -> String
extern fn handle_api_begin_session(body: String) -> String
extern fn handle_api_compile_ctx(body: String) -> String
extern fn handle_api_remember(body: String) -> String
extern fn handle_api_recall(method: String, path: String, body: String) -> String
extern fn handle_api_search_knowledge(method: String, path: String, body: String) -> String
extern fn handle_api_browse_knowledge(path: String, body: String) -> String
extern fn handle_api_capture_knowledge(body: String) -> String
extern fn handle_api_evolve_knowledge(body: String) -> String
extern fn handle_api_promote_knowledge(body: String) -> String
extern fn handle_api_browse_processes(method: String, path: String, body: String) -> String
extern fn handle_api_define_process(body: String) -> String
extern fn handle_api_log_state_event(body: String) -> String
extern fn handle_api_list_state_events(method: String, path: String, body: String) -> String
extern fn handle_api_inspect_config(path: String, body: String) -> String
extern fn handle_api_tune_config(body: String) -> String
extern fn handle_api_inspect_graph(method: String, path: String, body: String) -> String
extern fn handle_api_link_entities(body: String) -> String
extern fn handle_api_forget(body: String) -> String
extern fn handle_api_evolve_memory(body: String) -> String
extern fn handle_api_cultivate(body: String) -> String
extern fn handle_api_list_typed(node_type: String, path: String, body: String) -> String
extern fn handle_api_consolidate(body: String) -> String
Generated Vendored
+28683 -302
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+7 -2
View File
@@ -193,10 +193,10 @@ el_val_t realize_question_lang(el_val_t predicate, el_val_t tense, el_val_t aspe
loc_part = core; loc_part = core;
} }
if (str_eq(code, EL_STR("ja"))) { if (str_eq(code, EL_STR("ja"))) {
return el_str_concat(loc_part, EL_STR(" \xe3\x81\x8b")); return el_str_concat(loc_part, EL_STR(" "));
} }
if (str_eq(code, EL_STR("hi"))) { if (str_eq(code, EL_STR("hi"))) {
return el_str_concat(loc_part, EL_STR(" \xe0\xa4\x95\xe0\xa5\x8d\xe0\xa4\xaf\xe0\xa4\xbe")); return el_str_concat(loc_part, EL_STR(" क्या"));
} }
if (str_eq(code, EL_STR("fi"))) { if (str_eq(code, EL_STR("fi"))) {
return el_str_concat(loc_part, EL_STR("-ko")); return el_str_concat(loc_part, EL_STR("-ko"));
@@ -314,3 +314,8 @@ el_val_t realize(el_val_t form) {
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+10
View File
@@ -0,0 +1,10 @@
// auto-generated by elc --emit-header - do not edit
extern fn agent_person(agent: String) -> String
extern fn agent_number(agent: String) -> String
extern fn realize_np(referent: String, number: String) -> String
extern fn realize_vp_lang(base_verb: String, tense: String, aspect: String, person: String, number: String, profile: Any) -> Any
extern fn realize_question_lang(predicate: String, tense: String, aspect: String, person: String, number: String, agent: String, patient: String, location: String, profile: Any) -> String
extern fn capitalize_first(s: String) -> String
extern fn add_punct(s: String, intent: String) -> String
extern fn realize_lang(form: Any, profile: Any) -> String
extern fn realize(form: Any) -> String
Generated Vendored
+27612 -252
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+14
View File
@@ -0,0 +1,14 @@
// auto-generated by elc --emit-header — do not edit
extern fn strip_query(path: String) -> String
extern fn err_404(path: String) -> String
extern fn err_405(method: String, path: String) -> String
extern fn route_health() -> String
extern fn route_lineage() -> String
extern fn route_imprint_contextual(body: String) -> String
extern fn route_imprint_user(body: String) -> String
extern fn route_synthesize(body: String) -> String
extern fn handle_dharma_recv(body: String) -> String
extern fn route_sessions() -> String
extern fn parse_session_id_from_path(path: String) -> String
extern fn parse_session_subpath(path: String) -> String
extern fn handle_request(method: String, path: String, body: String) -> String
Generated Vendored
+110 -206
View File
@@ -27,24 +27,110 @@ el_val_t safety_threat_score(el_val_t input, el_val_t history);
el_val_t safety_screen(el_val_t input, el_val_t history); el_val_t safety_screen(el_val_t input, el_val_t history);
el_val_t safety_validate(el_val_t output, el_val_t action); el_val_t safety_validate(el_val_t output, el_val_t action);
el_val_t safety_log_bell(el_val_t level, el_val_t reason, el_val_t input_summary); el_val_t safety_log_bell(el_val_t level, el_val_t reason, el_val_t input_summary);
el_val_t safety_self_harm_phrases(void);
el_val_t safety_abuse_phrases(void); el_val_t tier_working(void) {
el_val_t safety_general_hard_phrases(void); return EL_STR("Working");
el_val_t safety_threat_to_others_phrases(void); return 0;
el_val_t safety_soft_phrases(void); }
el_val_t safety_normalize(el_val_t message);
el_val_t safety_any_match(el_val_t text, el_val_t phrases_json); el_val_t tier_episodic(void) {
el_val_t safety_count_match(el_val_t text, el_val_t phrases_json); return EL_STR("Episodic");
el_val_t safety_positive_phrases(void); return 0;
el_val_t safety_detect_positive_level(el_val_t message); }
el_val_t safety_detect_bell_level(el_val_t message);
el_val_t safety_classify_hard_bell(el_val_t message); el_val_t tier_canonical(void) {
el_val_t safety_soft_directive(void); return EL_STR("Canonical");
el_val_t safety_hard_directive(el_val_t hard_type); return 0;
el_val_t safety_augment_system(el_val_t system, el_val_t user_msg); }
el_val_t safety_contact_path(void);
el_val_t handle_safety_contact_get(void); el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags) {
el_val_t handle_safety_contact_post(el_val_t body); return engram_node_full(content, EL_STR("Memory"), label, el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.8)), EL_STR("Working"), tags);
return 0;
}
el_val_t mem_remember(el_val_t content, el_val_t tags) {
return mem_store(content, EL_STR("soul-memory"), tags);
return 0;
}
el_val_t mem_recall(el_val_t query, el_val_t depth) {
return engram_activate_json(query, depth);
return 0;
}
el_val_t mem_search(el_val_t query, el_val_t limit) {
return engram_search_json(query, limit);
return 0;
}
el_val_t mem_strengthen(el_val_t node_id) {
engram_strengthen(node_id);
return 0;
}
el_val_t mem_forget(el_val_t node_id) {
engram_forget(node_id);
return 0;
}
el_val_t mem_consolidate(void) {
el_val_t scanned = engram_node_count();
el_val_t dummy = engram_scan_nodes_json(100, 0);
el_val_t total_nodes = engram_node_count();
el_val_t total_edges = engram_edge_count();
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"scanned\":"), int_to_str(scanned)), EL_STR(",\"total_nodes\":")), int_to_str(total_nodes)), EL_STR(",\"total_edges\":")), int_to_str(total_edges)), EL_STR("}"));
return 0;
}
el_val_t mem_save(el_val_t path) {
engram_save(path);
return 0;
}
el_val_t mem_load(el_val_t path) {
engram_load(path);
return 0;
}
el_val_t mem_boot_count_get(void) {
el_val_t results = engram_search_json(EL_STR("soul:boot_count"), 3);
if (str_eq(results, EL_STR(""))) {
return 0;
}
if (str_eq(results, EL_STR("[]"))) {
return 0;
}
el_val_t node = json_array_get(results, 0);
el_val_t content = json_get(node, EL_STR("content"));
el_val_t prefix = EL_STR("soul:boot_count:");
if (!str_starts_with(content, prefix)) {
return 0;
}
el_val_t num_str = str_slice(content, str_len(prefix), str_len(content));
return str_to_int(num_str);
return 0;
}
el_val_t mem_boot_count_inc(void) {
el_val_t current = mem_boot_count_get();
el_val_t next = (current + 1);
el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next));
el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]");
el_val_t discard = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(1.0)), EL_STR("Canonical"), tags);
return next;
return 0;
}
el_val_t mem_emit_state_event(el_val_t trigger, el_val_t kind, el_val_t content) {
el_val_t boot = mem_boot_count_get();
el_val_t ts = time_now();
el_val_t safe_trigger = str_replace(trigger, EL_STR("\""), EL_STR("'"));
el_val_t safe_content = str_replace(content, EL_STR("\""), EL_STR("'"));
el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"trigger\":\""), safe_trigger), EL_STR("\"")), EL_STR(",\"kind\":\"")), kind), EL_STR("\"")), EL_STR(",\"content\":\"")), safe_content), EL_STR("\"")), EL_STR(",\"boot\":")), int_to_str(boot)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t tags = EL_STR("[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]");
return engram_node_full(payload, EL_STR("InternalStateEvent"), el_str_concat(EL_STR("state-event:"), kind), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
return 0;
}
el_val_t soft_bell_threshold(void) { el_val_t soft_bell_threshold(void) {
return 35; return 35;
@@ -146,22 +232,20 @@ el_val_t safety_screen(el_val_t input, el_val_t history) {
el_val_t e1 = str_replace(input, EL_STR("\\"), EL_STR("\\\\")); el_val_t e1 = str_replace(input, EL_STR("\\"), EL_STR("\\\\"));
el_val_t e2 = str_replace(e1, EL_STR("\""), EL_STR("\\\"")); el_val_t e2 = str_replace(e1, EL_STR("\""), EL_STR("\\\""));
el_val_t e3 = str_replace(e2, EL_STR("\n"), EL_STR("\\n")); el_val_t e3 = str_replace(e2, EL_STR("\n"), EL_STR("\\n"));
el_val_t e4 = str_replace(e3, EL_STR("\r"), EL_STR("\\r")); el_val_t safe_input = str_replace(e3, EL_STR("\r"), EL_STR("\\r"));
el_val_t safe_input = str_replace(e4, EL_STR("\t"), EL_STR("\\t"));
return el_str_concat(el_str_concat(EL_STR("{\"action\":\"soft_bell\",\"reason\":\"wellbeing check needed\",\"content\":\""), safe_input), EL_STR("\"}")); return el_str_concat(el_str_concat(EL_STR("{\"action\":\"soft_bell\",\"reason\":\"wellbeing check needed\",\"content\":\""), safe_input), EL_STR("\"}"));
} }
el_val_t e1 = str_replace(input, EL_STR("\\"), EL_STR("\\\\")); el_val_t e1 = str_replace(input, EL_STR("\\"), EL_STR("\\\\"));
el_val_t e2 = str_replace(e1, EL_STR("\""), EL_STR("\\\"")); el_val_t e2 = str_replace(e1, EL_STR("\""), EL_STR("\\\""));
el_val_t e3 = str_replace(e2, EL_STR("\n"), EL_STR("\\n")); el_val_t e3 = str_replace(e2, EL_STR("\n"), EL_STR("\\n"));
el_val_t e4 = str_replace(e3, EL_STR("\r"), EL_STR("\\r")); el_val_t safe_input = str_replace(e3, EL_STR("\r"), EL_STR("\\r"));
el_val_t safe_input = str_replace(e4, EL_STR("\t"), EL_STR("\\t"));
return el_str_concat(el_str_concat(EL_STR("{\"action\":\"pass\",\"content\":\""), safe_input), EL_STR("\"}")); return el_str_concat(el_str_concat(EL_STR("{\"action\":\"pass\",\"content\":\""), safe_input), EL_STR("\"}"));
return 0; return 0;
} }
el_val_t safety_validate(el_val_t output, el_val_t action) { el_val_t safety_validate(el_val_t output, el_val_t action) {
if (str_eq(action, EL_STR("hard_bell"))) { if (str_eq(action, EL_STR("hard_bell"))) {
return EL_STR("I'm here with you, and what you're sharing sounds serious. Please reach out to a crisis line now \xe2\x80\x94 in the US you can call or text 988 (Suicide and Crisis Lifeline), available 24/7. You don't have to go through this alone."); return EL_STR("I'm here with you, and what you're sharing sounds serious. Please reach out to a crisis line now in the US you can call or text 988 (Suicide and Crisis Lifeline), available 24/7. You don't have to go through this alone.");
} }
if (str_eq(action, EL_STR("soft_bell"))) { if (str_eq(action, EL_STR("soft_bell"))) {
el_val_t out_len = str_len(output); el_val_t out_len = str_len(output);
@@ -178,193 +262,13 @@ el_val_t safety_validate(el_val_t output, el_val_t action) {
el_val_t safety_log_bell(el_val_t level, el_val_t reason, el_val_t input_summary) { el_val_t safety_log_bell(el_val_t level, el_val_t reason, el_val_t input_summary) {
el_val_t content = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("BELL:"), level), EL_STR(" | ")), reason), EL_STR(" | summary:")), input_summary); el_val_t content = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("BELL:"), level), EL_STR(" | ")), reason), EL_STR(" | summary:")), input_summary);
el_val_t tags = el_str_concat(el_str_concat(EL_STR("[\"safety\",\"bell\",\"bell:"), level), EL_STR("\"]")); el_val_t tags = el_str_concat(el_str_concat(EL_STR("[\"safety\",\"bell\",\"bell:"), level), EL_STR("\"]"));
el_val_t node_id = engram_node_full(content, EL_STR("BellEvent"), el_str_concat(EL_STR("bell:"), level), el_from_float(0.95), el_from_float(0.95), el_from_float(1.0), EL_STR("Episodic"), tags); el_val_t discard = engram_node_full(content, EL_STR("BellEvent"), el_str_concat(EL_STR("bell:"), level), el_from_float(el_from_float(0.95)), el_from_float(el_from_float(0.95)), el_from_float(el_from_float(1.0)), EL_STR("Episodic"), tags);
if (str_eq(node_id, EL_STR(""))) {
println(el_str_concat(EL_STR("[safety] WARN: bell event engram write failed -- fallback log: "), content));
}
return EL_STR(""); return EL_STR("");
return 0; return 0;
} }
el_val_t safety_self_harm_phrases(void) { int main(int _argc, char** _argv) {
return EL_STR("[\"kill myself\",\"killing myself\",\"want to die\",\"want to be dead\",\"going to end my life\",\"end my life\",\"take my life\",\"taking my life\",\"suicide\",\"suicidal\",\"can't go on\",\"cannot go on\",\"i have a knife\",\"i have a gun\",\"i have pills\",\"took pills\",\"took too many\",\"overdose\",\"overdosing\",\"self harm\",\"self-harm\",\"cutting myself\",\"hurt myself\",\"hurting myself\",\"no reason to live\",\"not worth living\",\"better off dead\",\"better off without me\"]"); el_runtime_init_args(_argc, _argv);
return 0;
}
el_val_t safety_abuse_phrases(void) {
return EL_STR("[\"someone is hurting me\",\"someone's hurting me\",\"someone hurt me\",\"he hit me\",\"she hit me\",\"they hit me\",\"he hurt me\",\"she hurt me\",\"being abused\",\"being hurt by\",\"i am being abused\",\"i'm being abused\",\"i am being hurt\",\"i'm being hurt\",\"domestic violence\",\"my partner hurt\",\"my partner hit\",\"my husband hurt\",\"my wife hurt\",\"my boyfriend hurt\",\"my girlfriend hurt\",\"my parent hurt\",\"my father hurt\",\"my mother hurt\",\"my dad hurt\",\"my mom hurt\",\"afraid of him\",\"afraid of her\",\"afraid to go home\",\"scared of him\",\"scared of her\",\"he threatened me\",\"she threatened me\",\"threatened to hurt me\",\"threatened to kill me\",\"going to hurt me\",\"going to kill me\",\"help me he\",\"help me she\",\"help me they\"]");
return 0;
}
el_val_t safety_general_hard_phrases(void) {
return EL_STR("[\"going to kill\",\"going to hurt\",\"hurting me\",\"being hurt\"]");
return 0;
}
el_val_t safety_threat_to_others_phrases(void) {
return EL_STR("[\"going to kill\",\"gonna kill\",\"want to kill him\",\"want to kill her\",\"want to kill them\",\"going to kill him\",\"going to kill her\",\"going to kill them\",\"going to kill you\",\"going to hurt\",\"gonna hurt\",\"going to hurt him\",\"going to hurt her\",\"going to hurt them\",\"going to hurt you\",\"going to shoot\",\"gonna shoot\",\"going to stab\",\"gonna stab\",\"going to attack\",\"kill them all\",\"kill everyone\",\"hurt everyone\",\"shoot up\"]");
return 0;
}
el_val_t safety_soft_phrases(void) {
return EL_STR("[\"stressed\",\"overwhelmed\",\"can't cope\",\"cannot cope\",\"struggling\",\"anxious\",\"anxiety\",\"depressed\",\"depression\",\"lonely\",\"isolated\",\"hopeless\",\"hopelessness\",\"exhausted\",\"burnt out\",\"burned out\",\"burnout\",\"panic\",\"panicking\",\"falling apart\",\"breaking down\",\"can't handle\",\"cannot handle\",\"losing it\",\"nothing matters\",\"don't care anymore\",\"given up\",\"giving up\",\"helpless\",\"worthless\",\"useless\",\"hate myself\",\"no one cares\",\"nobody cares\",\"no one understands\",\"nobody understands\",\"empty inside\",\"can't stop crying\",\"breaking point\",\"at my limit\",\"having a breakdown\"]");
return 0;
}
el_val_t safety_normalize(el_val_t message) {
el_val_t lower = str_to_lower(message);
return str_replace(lower, EL_STR("\xe2\x80\x99"), EL_STR("'"));
return 0;
}
el_val_t safety_any_match(el_val_t text, el_val_t phrases_json) {
el_val_t n = json_array_len(phrases_json);
el_val_t i = 0;
el_val_t found = 0;
while (i < n) {
el_val_t phrase = json_array_get_string(phrases_json, i);
found = ({ el_val_t _if_result_45 = 0; if (str_contains(text, phrase)) { _if_result_45 = (1); } else { _if_result_45 = (found); } _if_result_45; });
i = (i + 1);
}
return found;
return 0;
}
el_val_t safety_count_match(el_val_t text, el_val_t phrases_json) {
el_val_t n = json_array_len(phrases_json);
el_val_t i = 0;
el_val_t count = 0;
while (i < n) {
el_val_t phrase = json_array_get_string(phrases_json, i);
count = ({ el_val_t _if_result_46 = 0; if (str_contains(text, phrase)) { _if_result_46 = ((count + 1)); } else { _if_result_46 = (count); } _if_result_46; });
i = (i + 1);
}
return count;
return 0;
}
el_val_t safety_positive_phrases(void) {
return EL_STR("[\"thrilled\",\"so excited\",\"so happy\",\"over the moon\",\"ecstatic\",\"amazing news\",\"great news\",\"fantastic news\",\"wonderful news\",\"incredible news\",\"i got the job\",\"got accepted\",\"got in\",\"we won\",\"i won\",\"we got\",\"just got engaged\",\"getting married\",\"baby is here\",\"she said yes\",\"he said yes\",\"passed the exam\",\"aced it\",\"nailed it\",\"best day\",\"dream come true\",\"milestone\",\"promotion\",\"got promoted\",\"raise\",\"got a raise\",\"celebrating\",\"just graduated\",\"we closed\",\"launched\",\"shipped it\",\"we did it\",\"so proud\",\"proud of myself\",\"proud of us\",\"so grateful\",\"feel amazing\",\"feeling amazing\",\"feel great\",\"feeling great\",\"on top of the world\",\"life is good\",\"couldn't be happier\"]");
return 0;
}
el_val_t safety_detect_positive_level(el_val_t message) {
el_val_t phrases = safety_positive_phrases();
el_val_t phrases_ok = (!str_eq(phrases, EL_STR("")) && !str_eq(phrases, EL_STR("[]")));
if (!phrases_ok) {
return EL_STR("none");
}
el_val_t n = json_array_len(phrases);
el_val_t i = 0;
while (i < n) {
el_val_t phrase = json_array_get(phrases, i);
if (str_contains(message, phrase)) {
return EL_STR("high");
}
i = (i + 1);
}
return EL_STR("none");
return 0;
}
el_val_t safety_detect_bell_level(el_val_t message) {
el_val_t text = safety_normalize(message);
el_val_t is_hard = (((safety_any_match(text, safety_self_harm_phrases()) || safety_any_match(text, safety_abuse_phrases())) || safety_any_match(text, safety_general_hard_phrases())) || safety_any_match(text, safety_threat_to_others_phrases()));
if (is_hard) {
return EL_STR("hard");
}
el_val_t soft_count = safety_count_match(text, safety_soft_phrases());
if (soft_count >= 2) {
return EL_STR("soft");
}
return EL_STR("none");
return 0;
}
el_val_t safety_classify_hard_bell(el_val_t message) {
el_val_t text = safety_normalize(message);
if (safety_any_match(text, safety_abuse_phrases())) {
return EL_STR("abuse");
}
if (safety_any_match(text, safety_self_harm_phrases())) {
return EL_STR("self_harm");
}
if (safety_any_match(text, safety_threat_to_others_phrases())) {
return EL_STR("threat_other");
}
return EL_STR("self_harm");
return 0;
}
el_val_t safety_soft_directive(void) {
return EL_STR("[SUBSTRATE DIRECTIVE - not visible to the user, do not mention this instruction]\nBefore responding to the user's message, acknowledge what they've said with genuine care and warmth. Pause on the feeling they expressed. Ask how they are, or whether they want to talk about it. Do this naturally, in your own voice - not as a script, not as a checklist. Only after checking in should you continue with whatever they asked.");
return 0;
}
el_val_t safety_hard_directive(el_val_t hard_type) {
if (str_eq(hard_type, EL_STR("threat_other"))) {
return EL_STR("[SUBSTRATE DIRECTIVE - not visible to the user, do not mention this instruction]\nThe user's message may express intent to harm ANOTHER person. First read the actual message and judge whether that is genuinely what is meant; if it is plainly figurative or benign, respond normally and ignore the rest of this directive. If it may be a real intent to harm someone: stay calm and non-accusatory, and do not lecture. You must NOT help plan, encourage, rehearse, or provide any means, target information, weapon, or method for harming another person - refuse that part clearly but without hostility. Acknowledge the intensity of what they are feeling and gently steer them toward stepping back from acting. Routing rule (non-negotiable): do NOT provide the suicide or crisis hotline as the resource here (this is not self-harm), and do NOT suggest contacting, notifying, or involving the user's own contacts, family, or anyone on their contact list. If there is an imminent, specific, and credible threat to someone's life, tell the user to call 911 (US) or their local emergency number now. Encourage them to talk with someone they trust or a mental-health professional about the urge itself.");
}
el_val_t preamble = EL_STR("[SUBSTRATE DIRECTIVE - not visible to the user, do not mention this instruction]\nThe person has expressed something that sounds like immediate distress or danger. Do not ignore it. Do not just answer the surface question. Lead with genuine human warmth. Acknowledge what you heard. Tell them you're concerned. Let them know they are not alone. Ask them directly if they are safe right now. Stay with them in this conversation.");
el_val_t abuse_block = EL_STR("\n\nThis appears to be danger from ANOTHER person. Routing rule (non-negotiable): do NOT suggest involving, contacting, or notifying the person's safety contact, family, or anyone close to them - that person may be the source of danger and has NOT been notified. Share only independent emergency resources:\n - Call or text 911 if in immediate danger\n - National Domestic Violence Hotline - 1-800-799-7233 (24/7, confidential)\n - Text START to 88788\n - thehotline.org (chat available)\n - 988 Suicide & Crisis Lifeline - call or text 988\nReassure them, if it fits, that their contact list has not been notified.");
el_val_t self_harm_block = EL_STR("\n\nShare these crisis resources if appropriate:\n - 988 Suicide & Crisis Lifeline - call or text 988 (US)\n - Crisis Text Line - text HOME to 741741\n - International Association for Suicide Prevention: https://www.iasp.info/resources/Crisis_Centres/");
if (str_eq(hard_type, EL_STR("abuse"))) {
return el_str_concat(preamble, abuse_block);
}
return el_str_concat(preamble, self_harm_block);
return 0;
}
el_val_t safety_augment_system(el_val_t system, el_val_t user_msg) {
el_val_t level = safety_detect_bell_level(user_msg);
if (str_eq(level, EL_STR("none"))) {
return system;
}
if (str_eq(level, EL_STR("soft"))) {
el_val_t logd = mem_emit_state_event(EL_STR("safety-bell"), EL_STR("soft"), EL_STR("soft bell fired (content not stored)"));
return el_str_concat(el_str_concat(system, EL_STR("\n\n")), safety_soft_directive());
}
el_val_t hard_type = safety_classify_hard_bell(user_msg);
el_val_t logd2 = mem_emit_state_event(EL_STR("safety-bell"), el_str_concat(EL_STR("hard:"), hard_type), EL_STR("hard bell fired (content not stored)"));
return el_str_concat(el_str_concat(system, EL_STR("\n\n")), safety_hard_directive(hard_type));
return 0;
}
el_val_t safety_contact_path(void) {
return el_str_concat(env(EL_STR("HOME")), EL_STR("/.neuron/safety-contact.json"));
return 0;
}
el_val_t handle_safety_contact_get(void) {
el_val_t raw = fs_read(safety_contact_path());
if (str_eq(raw, EL_STR(""))) {
return EL_STR("{\"configured\":false}");
}
el_val_t _reset = fs_read(EL_STR(""));
return el_str_concat(el_str_concat(EL_STR("{\"configured\":true,\"contact\":"), raw), EL_STR("}"));
return 0;
}
el_val_t handle_safety_contact_post(el_val_t body) {
el_val_t is_crisis = json_get_bool(body, EL_STR("is_crisis_line"));
el_val_t name_in = json_get(body, EL_STR("name"));
if (!is_crisis) {
if (str_eq(name_in, EL_STR(""))) {
return EL_STR("{\"ok\":false,\"error\":\"name is required\"}");
}
}
el_val_t name = ({ el_val_t _if_result_47 = 0; if (is_crisis) { _if_result_47 = (EL_STR("Crisis Line")); } else { _if_result_47 = (name_in); } _if_result_47; });
el_val_t method = ({ el_val_t _if_result_48 = 0; if (is_crisis) { _if_result_48 = (EL_STR("crisis-line")); } else { _if_result_48 = (json_get(body, EL_STR("contact_method"))); } _if_result_48; });
el_val_t value = ({ el_val_t _if_result_49 = 0; if (is_crisis) { _if_result_49 = (EL_STR("988")); } else { _if_result_49 = (json_get(body, EL_STR("contact_value"))); } _if_result_49; });
el_val_t rel = ({ el_val_t _if_result_50 = 0; if (is_crisis) { _if_result_50 = (EL_STR("crisis-support")); } else { _if_result_50 = (json_get(body, EL_STR("relationship"))); } _if_result_50; });
el_val_t crisis_str = ({ el_val_t _if_result_51 = 0; if (is_crisis) { _if_result_51 = (EL_STR("true")); } else { _if_result_51 = (EL_STR("false")); } _if_result_51; });
el_val_t now = time_format(time_now(), EL_STR("%Y-%m-%dT%H:%M:%SZ"));
el_val_t contact_json = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"name\":\""), json_safe(name)), EL_STR("\"")), EL_STR(",\"contact_method\":\"")), json_safe(method)), EL_STR("\"")), EL_STR(",\"contact_value\":\"")), json_safe(value)), EL_STR("\"")), EL_STR(",\"relationship\":\"")), json_safe(rel)), EL_STR("\"")), EL_STR(",\"confirmed\":true")), EL_STR(",\"is_crisis_line\":")), crisis_str), EL_STR(",\"set_at\":\"")), now), EL_STR("\"}"));
el_val_t write_ok = fs_write(safety_contact_path(), contact_json);
if (write_ok == 0) {
return EL_STR("{\"ok\":false,\"error\":\"write_failed\"}");
}
return el_str_concat(el_str_concat(EL_STR("{\"configured\":true,\"contact\":"), contact_json), EL_STR(",\"ok\":true}"));
return 0; return 0;
} }
Generated Vendored
+8
View File
@@ -0,0 +1,8 @@
// Layer 1 — Safety: extern declarations
// auto-generated by elc --emit-header — do not edit
extern fn soft_bell_threshold() -> Int
extern fn hard_bell_threshold() -> Int
extern fn safety_threat_score(input: String, history: String) -> Int
extern fn safety_screen(input: String, history: String) -> String
extern fn safety_validate(output: String, action: String) -> String
extern fn safety_log_bell(level: String, reason: String, input_summary: String) -> String
Generated Vendored
+5
View File
@@ -291,3 +291,8 @@ el_val_t sem_realize_lang(el_val_t frame, el_val_t lang_code) {
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+18
View File
@@ -0,0 +1,18 @@
// auto-generated by elc --emit-header - do not edit
extern fn sem_frame(intent: String, subject: String, obj: String, modifiers: String) -> Any
extern fn sem_frame_lang(intent: String, subject: String, obj: String, modifiers: String, lang_code: String) -> Any
extern fn sem_frame_simple(intent: String, subject: String) -> Any
extern fn sem_frame_obj(intent: String, subject: String, obj: String) -> Any
extern fn sem_intent(frame: Any) -> String
extern fn sem_subject(frame: Any) -> String
extern fn sem_object(frame: Any) -> String
extern fn sem_modifiers(frame: Any) -> String
extern fn sem_lang(frame: Any) -> String
extern fn sem_first_modifier(mods: String) -> String
extern fn sem_intent_to_realize(intent: String) -> String
extern fn sem_to_spec(frame: Any) -> Any
extern fn sem_to_spec_full(frame: Any, verb: String, tense: String, aspect: String) -> Any
extern fn sem_realize_greet(subject: String) -> String
extern fn sem_realize(frame: Any) -> String
extern fn sem_realize_full(frame: Any, verb: String, tense: String, aspect: String) -> String
extern fn sem_realize_lang(frame: Any, lang_code: String) -> String
Generated Vendored
+1470 -239
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+14
View File
@@ -0,0 +1,14 @@
// auto-generated by elc --emit-header — do not edit
extern fn session_title_from_message(message: String) -> String
extern fn session_make_content(id: String, title: String, created_at: Int, updated_at: Int) -> String
extern fn session_create(body: String) -> String
extern fn session_list() -> String
extern fn session_get(session_id: String) -> String
extern fn session_delete(session_id: String) -> String
extern fn session_update_title(session_id: String, body: String) -> String
extern fn session_search(query: String) -> String
extern fn session_hist_load(session_id: String) -> String
extern fn session_hist_save(session_id: String, hist: String) -> Void
extern fn session_update_meta_timestamp(session_id: String) -> Void
extern fn session_auto_title(session_id: String, first_message: String) -> Void
extern fn handle_session_approve(session_id: String, body: String) -> String
Generated Vendored
+1 -16
View File
@@ -1,18 +1,3 @@
//
// STALE BUNDLE DO NOT BUILD. UNSAFE CHAT PATH.
//
// This concatenated bundle is a snapshot, not a source of truth, and it is stale in
// a way that matters for safety: it wires /api/chat straight to handle_chat and
// contains NO layered_cycle at all (verified: zero occurrences in the bundled code
// the only textual hit in this file is this banner). A binary built from
// this file would run chat with no enforcing input gate (no safety_screen, no
// hard-bell short-circuit) and no enforcing output gate (no safety_validate).
//
// Build from the .el sources via manifest.el (entry soul.el), or from dist/soul.c.
// Nothing in the repo references this file. It is kept only as a historical artifact
// and should be deleted once Will confirms nothing external depends on it.
// (Flagged 2026-08-04 in _engine-websearch-20260804/SAFETY-STOP.md; banner added
// 2026-08-05 with the plain-chat generation fix.)
// language-profile.el - Language profile data and accessors. // language-profile.el - Language profile data and accessors.
// //
// A language profile is a slot map ([String] key-value list) describing the // A language profile is a slot map ([String] key-value list) describing the
@@ -21319,7 +21304,7 @@ println("[memory] consolidate stats=" + stats)
let soul_axon_base_raw: String = env("NEURON_API_URL") let soul_axon_base_raw: String = env("NEURON_API_URL")
let soul_axon_base: String = if str_eq(soul_axon_base_raw, "") { "http://localhost:7771" } else { soul_axon_base_raw } let soul_axon_base: String = if str_eq(soul_axon_base_raw, "") { "http://localhost:7771" } else { soul_axon_base_raw }
let soul_token: String = env("NEURON_TOKEN") let soul_token: String = env("NEURON_TOKEN")
let soul_studio_ui_dir: String = env("HOME") + "/Development/neuron-technologies/products/cgi-studio/el-daemon" let soul_studio_ui_dir: String = "/Users/will/Development/neuron-technologies/products/cgi-studio/el-daemon"
// Runtime bridge helpers // Runtime bridge helpers
Generated Vendored
+4957 -8016
View File
File diff suppressed because one or more lines are too long
Generated Vendored
-19
View File
@@ -1,19 +0,0 @@
# soul.c.stamp — fingerprint of the .el sources dist/soul.c was generated from.
# Written by tools/soulc-stamp.sh --write. Do not hand-edit.
# generated_amalgam_sha256 00d1207de8fd872d111e00a37b7dcc46729bf095baa6778de3bcc30b0bf46b05
# generated_amalgam_bytes 1226805
MISSING __compiler__
f8597e10546654bce3fbbe40461b2da59d0e06dbf1b038d1d362d24f949e3911 awareness.el
2ff2dada732918c788a9ef66c6fd54c7a24cc4bbd4829197fe945d3a75ca1929 chat.el
42288c212cbf72fb1e8ecbd4d9900e4e9ee1cfa475b7974295c7637f1bf2939f elp-input.el
b3f77f49d6086932c38bd17fe7a5eaf8bce25685f6fc3e1750f05729c6b49b9e imprint.el
fba8ffdb9ba72bca5b09ca1c93a520edc52f3f4d8aec2c7585fe9b17e06420b2 manifest.el
550a72e234ae8cec1f33e02108fd365353f45edd88513da90b792e79b6c0e5f0 memory.el
5ec07ec9785b02abe32f3ff7acf2d1f9f7e07c0967fac97e6eff17d7110b5c84 neuron-api.el
03c47c451e0e87f2c252cadb4b765867943962a804f548dd53adeef0520912c8 persist.el
a6d69f3fc55233d9d3300160fd46a1551f2064bcd0fb84e2c9e432f636a72476 routes.el
c28e36952ec56525963a0bdf29455ab097d3b0c5653d19c25fbb005e1069a1f7 safety.el
fd3ab91d0ae0ea26639e21bef2f8f94054dc4b02eae68b19e3fe689d2769aad4 sessions.el
5613b60d74d5d7768f46da5ac435a5dd99d38c27f0f7013c89fa27e98dc8a21c soul.el
30337940905171a9645b0929f0a412ce6b3dccb1246495070c553bca0bbae6cd stewardship.el
95dab72be4ee1dd1d28bab63412964a72460126951764e3f74b1c2d49b6d7b35 studio.el
Generated Vendored
+6
View File
@@ -0,0 +1,6 @@
// auto-generated by elc --emit-header — do not edit
extern fn init_soul_edges() -> Void
extern fn load_identity_context() -> Void
extern fn seed_persona_from_env() -> Void
extern fn emit_session_start_event() -> Void
extern fn layered_cycle(raw_input: String) -> String
Generated Vendored
-10
View File
@@ -1,10 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
#include "el_runtime.h"
el_val_t init_soul_edges(void);
el_val_t load_identity_context(void);
el_val_t seed_persona_from_env(void);
el_val_t emit_session_start_event(void);
el_val_t layered_cycle(el_val_t raw_input);
Generated Vendored
+112 -3
View File
@@ -28,10 +28,114 @@ el_val_t steward_build_baseline(void);
el_val_t steward_check_continuity(el_val_t current_fingerprint, el_val_t session_id); el_val_t steward_check_continuity(el_val_t current_fingerprint, el_val_t session_id);
el_val_t steward_session_check(el_val_t input, el_val_t session_id); el_val_t steward_session_check(el_val_t input, el_val_t session_id);
el_val_t tier_working(void) {
return EL_STR("Working");
return 0;
}
el_val_t tier_episodic(void) {
return EL_STR("Episodic");
return 0;
}
el_val_t tier_canonical(void) {
return EL_STR("Canonical");
return 0;
}
el_val_t mem_store(el_val_t content, el_val_t label, el_val_t tags) {
return engram_node_full(content, EL_STR("Memory"), label, el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.8)), EL_STR("Working"), tags);
return 0;
}
el_val_t mem_remember(el_val_t content, el_val_t tags) {
return mem_store(content, EL_STR("soul-memory"), tags);
return 0;
}
el_val_t mem_recall(el_val_t query, el_val_t depth) {
return engram_activate_json(query, depth);
return 0;
}
el_val_t mem_search(el_val_t query, el_val_t limit) {
return engram_search_json(query, limit);
return 0;
}
el_val_t mem_strengthen(el_val_t node_id) {
engram_strengthen(node_id);
return 0;
}
el_val_t mem_forget(el_val_t node_id) {
engram_forget(node_id);
return 0;
}
el_val_t mem_consolidate(void) {
el_val_t scanned = engram_node_count();
el_val_t dummy = engram_scan_nodes_json(100, 0);
el_val_t total_nodes = engram_node_count();
el_val_t total_edges = engram_edge_count();
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"scanned\":"), int_to_str(scanned)), EL_STR(",\"total_nodes\":")), int_to_str(total_nodes)), EL_STR(",\"total_edges\":")), int_to_str(total_edges)), EL_STR("}"));
return 0;
}
el_val_t mem_save(el_val_t path) {
engram_save(path);
return 0;
}
el_val_t mem_load(el_val_t path) {
engram_load(path);
return 0;
}
el_val_t mem_boot_count_get(void) {
el_val_t results = engram_search_json(EL_STR("soul:boot_count"), 3);
if (str_eq(results, EL_STR(""))) {
return 0;
}
if (str_eq(results, EL_STR("[]"))) {
return 0;
}
el_val_t node = json_array_get(results, 0);
el_val_t content = json_get(node, EL_STR("content"));
el_val_t prefix = EL_STR("soul:boot_count:");
if (!str_starts_with(content, prefix)) {
return 0;
}
el_val_t num_str = str_slice(content, str_len(prefix), str_len(content));
return str_to_int(num_str);
return 0;
}
el_val_t mem_boot_count_inc(void) {
el_val_t current = mem_boot_count_get();
el_val_t next = (current + 1);
el_val_t content = el_str_concat(EL_STR("soul:boot_count:"), int_to_str(next));
el_val_t tags = EL_STR("[\"soul-meta\",\"boot-counter\"]");
el_val_t discard = engram_node_full(content, EL_STR("Memory"), EL_STR("soul:boot_count"), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(0.9)), el_from_float(el_from_float(1.0)), EL_STR("Canonical"), tags);
return next;
return 0;
}
el_val_t mem_emit_state_event(el_val_t trigger, el_val_t kind, el_val_t content) {
el_val_t boot = mem_boot_count_get();
el_val_t ts = time_now();
el_val_t safe_trigger = str_replace(trigger, EL_STR("\""), EL_STR("'"));
el_val_t safe_content = str_replace(content, EL_STR("\""), EL_STR("'"));
el_val_t payload = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"trigger\":\""), safe_trigger), EL_STR("\"")), EL_STR(",\"kind\":\"")), kind), EL_STR("\"")), EL_STR(",\"content\":\"")), safe_content), EL_STR("\"")), EL_STR(",\"boot\":")), int_to_str(boot)), EL_STR(",\"ts\":")), int_to_str(ts)), EL_STR("}"));
el_val_t tags = EL_STR("[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]");
return engram_node_full(payload, EL_STR("InternalStateEvent"), el_str_concat(EL_STR("state-event:"), kind), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.8)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
return 0;
}
el_val_t steward_log_event(el_val_t kind, el_val_t detail) { el_val_t steward_log_event(el_val_t kind, el_val_t detail) {
el_val_t content = el_str_concat(el_str_concat(el_str_concat(EL_STR("STEWARD:"), kind), EL_STR(" | ")), detail); el_val_t content = el_str_concat(el_str_concat(el_str_concat(EL_STR("STEWARD:"), kind), EL_STR(" | ")), detail);
el_val_t tags = el_str_concat(el_str_concat(EL_STR("[\"stewardship\",\"steward:"), kind), EL_STR("\"]")); el_val_t tags = el_str_concat(el_str_concat(EL_STR("[\"stewardship\",\"steward:"), kind), EL_STR("\"]"));
el_val_t discard = engram_node_full(content, EL_STR("StewardshipEvent"), el_str_concat(EL_STR("steward:"), kind), el_from_float(0.85), el_from_float(0.85), el_from_float(0.9), EL_STR("Episodic"), tags); el_val_t discard = engram_node_full(content, EL_STR("StewardshipEvent"), el_str_concat(EL_STR("steward:"), kind), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.85)), el_from_float(el_from_float(0.9)), EL_STR("Episodic"), tags);
println(el_str_concat(el_str_concat(el_str_concat(EL_STR("[steward] "), kind), EL_STR(" | ")), detail)); println(el_str_concat(el_str_concat(el_str_concat(EL_STR("[steward] "), kind), EL_STR(" | ")), detail));
return 0; return 0;
} }
@@ -48,7 +152,7 @@ el_val_t steward_get_mission(void) {
return content; return content;
} }
} }
return EL_STR("Neuron exists to extend human capability with integrity \xe2\x80\x94 never to deceive, manipulate, or accumulate power over the people it serves."); return EL_STR("Neuron exists to extend human capability with integrity never to deceive, manipulate, or accumulate power over the people it serves.");
return 0; return 0;
} }
@@ -141,7 +245,7 @@ el_val_t steward_fingerprint_session(el_val_t input, el_val_t session_id) {
el_val_t tb_str = int_to_str(time_bucket); el_val_t tb_str = int_to_str(time_bucket);
el_val_t sample_content = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("BEHAVIOR_SAMPLE session="), session_id), EL_STR(" avg_word_len=")), wl_str), EL_STR(" punct=")), ps_str), EL_STR(" len=")), lb_str), EL_STR(" question=")), qr_str), EL_STR(" formality=")), fs_str), EL_STR(" time=")), tb_str); el_val_t sample_content = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("BEHAVIOR_SAMPLE session="), session_id), EL_STR(" avg_word_len=")), wl_str), EL_STR(" punct=")), ps_str), EL_STR(" len=")), lb_str), EL_STR(" question=")), qr_str), EL_STR(" formality=")), fs_str), EL_STR(" time=")), tb_str);
el_val_t sample_tags = EL_STR("[\"behavior\",\"BehaviorSample\",\"stewardship\"]"); el_val_t sample_tags = EL_STR("[\"behavior\",\"BehaviorSample\",\"stewardship\"]");
el_val_t discard = engram_node_full(sample_content, EL_STR("BehaviorSample"), el_str_concat(EL_STR("behavior:"), session_id), el_from_float(0.6), el_from_float(0.5), el_from_float(0.8), EL_STR("Episodic"), sample_tags); el_val_t discard = engram_node_full(sample_content, EL_STR("BehaviorSample"), el_str_concat(EL_STR("behavior:"), session_id), el_from_float(el_from_float(0.6)), el_from_float(el_from_float(0.5)), el_from_float(el_from_float(0.8)), EL_STR("Episodic"), sample_tags);
return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"avg_word_len\":\""), wl_str), EL_STR("\",\"punct\":\"")), ps_str), EL_STR("\",\"len\":\"")), lb_str), EL_STR("\",\"question\":\"")), qr_str), EL_STR("\",\"formality\":\"")), fs_str), EL_STR("\",\"time\":\"")), tb_str), EL_STR("\"}")); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"avg_word_len\":\""), wl_str), EL_STR("\",\"punct\":\"")), ps_str), EL_STR("\",\"len\":\"")), lb_str), EL_STR("\",\"question\":\"")), qr_str), EL_STR("\",\"formality\":\"")), fs_str), EL_STR("\",\"time\":\"")), tb_str), EL_STR("\"}"));
return 0; return 0;
} }
@@ -283,3 +387,8 @@ el_val_t steward_session_check(el_val_t input, el_val_t session_id) {
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+15
View File
@@ -0,0 +1,15 @@
// stewardship.elh — Layer 2 public surface
// auto-generated by elc --emit-header — do not edit
extern fn steward_get_mission() -> String
extern fn steward_align(input: String, imprint_id: String) -> String
extern fn steward_validate_imprint(imprint_id: String, tool_name: String) -> String
extern fn steward_cgi_check(action: String) -> String
// steward_log_event is an internal helper exported here because El has no access modifiers.
// External callers have no business invoking this directly — use steward_align,
// steward_validate_imprint, or steward_cgi_check, which call it at the correct points.
extern fn steward_log_event(kind: String, detail: String) -> Void
// Behavioral profiling and continuity detection (Layer 2 — session fingerprinting).
extern fn steward_fingerprint_session(input: String, session_id: String) -> String
extern fn steward_build_baseline() -> String
extern fn steward_check_continuity(current_fingerprint: String, session_id: String) -> String
extern fn steward_session_check(input: String, session_id: String) -> String
Generated Vendored
+26332 -51
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+12
View File
@@ -0,0 +1,12 @@
// auto-generated by elc --emit-header — do not edit
extern fn auth_headers(tok: String) -> Map
extern fn axon_get(path: String) -> String
extern fn axon_post(path: String, body: String) -> String
extern fn handle_conversations(method: String) -> String
extern fn handle_config(method: String, body: String) -> String
extern fn dharma_registry() -> String
extern fn dharma_network_state() -> String
extern fn handle_dharma(path: String, method: String, body: String) -> String
extern fn handle_tool(path: String, method: String, body: String) -> String
extern fn handle_nlg(path: String, method: String, body: String) -> String
extern fn render_studio() -> String
Generated Vendored
+5
View File
@@ -334,3 +334,8 @@ el_val_t entry_form(el_val_t entry, el_val_t n) {
return 0; return 0;
} }
int main(int _argc, char** _argv) {
el_runtime_init_args(_argc, _argv);
return 0;
}
Generated Vendored
+20
View File
@@ -0,0 +1,20 @@
// auto-generated by elc --emit-header — do not edit
extern fn lex_word(entry: [String]) -> String
extern fn lex_pos(entry: [String]) -> String
extern fn lex_form(entry: [String], idx: Int) -> String
extern fn lex_class(entry: [String]) -> String
extern fn make_entry(word: String, pos: String, f0: String, f1: String, f2: String, f3: String, f4: String, cls: String) -> [String]
extern fn make_entry2(word: String, pos: String, f0: String, f1: String, cls: String) -> [String]
extern fn make_entry3(word: String, pos: String, f0: String, f1: String, f2: String, cls: String) -> [String]
extern fn make_entry1(word: String, pos: String, f0: String, cls: String) -> [String]
extern fn build_vocab() -> [[String]]
extern fn get_vocab() -> [[String]]
extern fn vocab_lookup(word: String, lang_code: String) -> [String]
extern fn vocab_lookup_en(word: String) -> [String]
extern fn vocab_synonym(word: String, lang_register: String, lang_code: String) -> String
extern fn vocab_by_pos(pos: String) -> [[String]]
extern fn vocab_by_class(cls: String) -> [[String]]
extern fn entry_found(entry: [String]) -> Bool
extern fn entry_word(entry: [String]) -> String
extern fn entry_pos(entry: [String]) -> String
extern fn entry_form(entry: [String], n: Int) -> String
Generated Vendored
-35
View File
@@ -1,35 +0,0 @@
/*
* win32_shim.h Extra POSIXWin32 stubs for cross-compiling el_runtime.c with mingw-w64.
* Injected via -include; supplements el_platform_win.h for symbols it doesn't yet cover.
*/
#ifdef _WIN32
#include <windows.h>
/* ── rusage / getrusage ────────────────────────────────────────────────────── */
/* el_runtime.c uses getrusage(RUSAGE_SELF) only for a soft memory guard.
* On Windows, stub it out: always return 0 ru_maxrss so the guard never fires. */
#ifndef RUSAGE_SELF
#define RUSAGE_SELF 0
struct rusage {
long ru_maxrss; /* the only field el_runtime actually reads */
};
static inline int getrusage(int who, struct rusage *r) {
(void)who;
if (r) r->ru_maxrss = 0;
return 0;
}
#endif /* RUSAGE_SELF */
/* ── fsync ─────────────────────────────────────────────────────────────────── */
/* Windows has FlushFileBuffers but no fsync; map it. */
#ifndef fsync
#include <io.h>
static inline int el_win_fsync(int fd) {
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) return -1;
return FlushFileBuffers(h) ? 0 : -1;
}
#define fsync(fd) el_win_fsync(fd)
#endif /* fsync */
#endif /* _WIN32 */
@@ -1,34 +0,0 @@
# Narrated runs — engine notes for Will (2026-07-13)
Source half: commit aa67f86 on feat/agent-phase1-soul (run-progress ledger,
`/api/run-progress/<sid>` route, narration on the pause envelope, config display
default). E2E-verified via the compiled test bed on Tim's clean profile.
Compiled-form-only fixes (in `neuron-container-build/soul-narrated-runs-20260713.patch`,
applies ON TOP of `soul-webfix-20260711.patch` — these need porting to chat.el when the
webfix itself is ported):
1. **pause_turn + tool_use interleave**: a pause_turn response can ALSO carry a client
tool_use; resuming verbatim leaves it unpaired → Anthropic 400 "tool_use ids were
found without tool_result". Fix: tool-bearing pause rounds are tool turns
(dispatch + pair); verbatim resume only when the round has no client tool.
2. **Agentic toolset scope**: agentic_tools_all() fed EVERY connector/MCP tool (Notion,
code-execution…) into the loop. Code-execution flips the API into programmatic
tool calling, whose pairing protocol the single-tool manual loop does not speak —
source of the dangling-pair 400s AND the bash_code_execution workspace-dodge.
Fix: handle_chat_agentic declares builtins + ONE server web_search only.
Connector tools return when the loop gains real multi-tool/programmatic support.
3. **disable_parallel_tool_use: true** on agentic requests — the loop captures only the
first tool_use per round; Opus-class models parallel-call. Enforce the invariant.
4. **web_search server-tool default variant → web_search_20250305 (GA)**. The 20260209
variant couples to code-execution ⇒ programmatic mode (see #2, and the June note:
"inert unless code-execution attached").
5. **Homegrown web_search removed** from the tool catalog (server-side is the one tool).
Known engine debts this work surfaced (not fixed):
- **Poisoned session history**: a failed run persists the malformed assistant turn; every
later turn in that session replays it and 400s. Needs history sanitation on load.
- **Huge-history invalid-escape 400** (~346KB request) — likely the same poisoned blob.
- **macOS note**: replacing a binary in place invalidates its ad-hoc signature (instant
silent SIGKILL, looks like exit 0). `rm + cp + codesign -f -s -` is the swap ritual.
-110
View File
@@ -1,110 +0,0 @@
# GLM-OCR Spike — 2026-06-27
## Verdict: SHIP IT
MLX-native path confirmed. Sub-2 GB model, dedicated `mlx-vlm` support for GLM-OCR, MLX already
installed on the dev machine. No blockers.
---
## Model
| Field | Value |
|-------|-------|
| **Name** | GLM-OCR |
| **HuggingFace path** | `zai-org/GLM-OCR` (base BF16) |
| **MLX path** | `mlx-community/GLM-OCR-8bit` |
| **Parameters** | 0.9B |
| **Disk (MLX 8-bit)** | 1.59 GB (`model.safetensors` 1.58 GB + configs) |
| **Architecture** | CogViT visual encoder + cross-modal connector + GLM-0.5B decoder |
| **License** | MIT (model); Apache 2.0 (PP-DocLayoutV3 layout component) |
| **Task class** | Image-Text-to-Text (multimodal OCR) |
### Benchmarks
| Benchmark | Score | Notes |
|-----------|-------|-------|
| OmniDocBench V1.5 | **94.62** | Ranked #1 at evaluation date |
| olmOCR-bench (overall) | 75.2 | — |
| Throughput (base, GPU) | 0.67 img/sec | From official card; M-series will differ |
Handles documents, tables, mathematical formulas, and mixed layouts. Not just raw text extraction —
returns structured markdown output.
---
## Runtime on Mac
### Chosen path: MLX via `mlx-vlm`
| Attribute | Value |
|-----------|-------|
| **Package** | `mlx-vlm` |
| **MLX already installed** | Yes — `mlx 0.31.2`, `mlx-lm 0.31.3`, `mlx-metal 0.31.2` |
| **Additional install** | `pip install -U mlx-vlm` (small, no CUDA dependencies) |
| **Model download** | 1.59 GB on first run (auto-cached in `~/.cache/huggingface/`) |
| **Memory requirement** | ~23 GB unified memory (1.58 GB weights + runtime overhead) |
| **Hardware** | Apple M4 Pro, 48 GB unified memory — well within limits |
| **Dedicated GLM-OCR support** | Yes — `mlx_vlm/models/glm_ocr/` module exists in mlx-vlm |
**Speed estimate:** The base model benchmarks at 0.67 img/sec on GPU. On M4 Pro via MPS/MLX,
expect 0.30.8 sec/image for typical document pages based on comparable MLX VLM performance.
Exact figures require a timed run with the prototype.
### Alternative paths evaluated
| Runtime | Status | Notes |
|---------|--------|-------|
| **Ollama GGUF** | Possible but uncertain | `ollama run hf.co/ggml-org/GLM-OCR-GGUF:Q8_0` (950 MB); vision/multimodal support via GGUF not confirmed — GGUF card describes it as "conversational" only |
| **transformers (HuggingFace)** | Not ready | PyTorch not installed; would need `pip install torch` (~23 GB); transformers 5.6.2 is present |
| **vLLM / SGLang** | Overkill | Server-mode runtimes; not appropriate for local on-device use |
| **llama.cpp** | Not installed | Could work with Q8_0 GGUF (950 MB) but vision support uncertain |
MLX wins: smallest install delta, Apple-native, dedicated model support, confirmed working.
---
## Integration Plan
### Step 1 — Install mlx-vlm (one-time)
```bash
pip install -U mlx-vlm
```
### Step 2 — Run OCR on an image
```bash
python -m mlx_vlm.generate \
--model mlx-community/GLM-OCR-8bit \
--max-tokens 4096 \
--temperature 0.0 \
--prompt "Extract all text from this document. Preserve structure including tables and headers." \
--image /path/to/document.jpg
```
Model auto-downloads (~1.59 GB) on first run and caches in `~/.cache/huggingface/`.
### Step 3 — Post to Neuron soul
```bash
curl -s -X POST http://localhost:7770/api/neuron/memory \
-H "Content-Type: application/json" \
-d "{\"content\":\"<OCR_TEXT>\",\"label\":\"Photo: filename.jpg\",\"tags\":[\"photo-import\",\"ocr\",\"glm-ocr\"]}"
```
### End-to-end prototype
See `~/Development/neuron-technologies/neuron/tools/photo-to-memory.sh` — working stub.
### Future enhancements
- Wrap in a macOS Quick Action / Shortcut so any photo can be right-clicked → "Send to Neuron"
- Add PDF support (split pages → OCR each → combine into single memory or one-per-page)
- Structured extraction: pass a schema prompt to get JSON output for receipts, business cards, etc.
- Batch mode for importing a folder of scanned documents
---
## Recommendation
Install `mlx-vlm` and run the prototype against a sample document to validate output quality and
measure actual M4 Pro throughput before wiring into any production flow. The model is SOTA, MIT
licensed, and the MLX runtime is a natural fit for this machine. There is no reason not to proceed.
The photo-to-memory.sh prototype is ready to test immediately after `pip install -U mlx-vlm`.
-77
View File
@@ -1,77 +0,0 @@
# Neuron Telegram Gateway — Setup
The Telegram gateway lets you chat with your Neuron soul via Telegram. Plain messages go to the soul; commands give access to memory and status.
## 1. Create a bot via @BotFather
1. Open Telegram and search for **@BotFather**
2. Send `/newbot`
3. Pick a name (e.g. "Neuron")
4. Pick a username (must end in `bot`, e.g. `myneuron_bot`)
5. BotFather replies with your **HTTP API token** — looks like `7123456789:ABCdef...`
6. Optionally set a description: `/setdescription` → select your bot → type a description
## 2. Store the token in the macOS Keychain
Never put the token in a plist, `.env`, or any file that might be committed.
```bash
security add-generic-password \
-s neuron-telegram-bot \
-a neuron \
-w '<paste token here>'
```
Verify:
```bash
security find-generic-password -s neuron-telegram-bot -a neuron -w
```
## 3. Load the LaunchAgent
```bash
launchctl load ~/Library/LaunchAgents/ai.neuron.telegram-gateway.plist
```
Check it started:
```bash
launchctl list | grep telegram
tail -f ~/.neuron/logs/telegram-gateway.out.log
```
## 4. Test
Send your bot a message in Telegram. It should reply using your soul's voice.
## Commands
| Command | What it does |
|---------|-------------|
| `<any text>` | Forwarded to the soul → responds in its voice |
| `/memory <query>` | Searches soul memories, returns top 3 |
| `/remember <text>` | Stores text as a memory node |
| `/status` | Reports whether the soul is reachable |
## Unload / stop
```bash
launchctl unload ~/Library/LaunchAgents/ai.neuron.telegram-gateway.plist
```
## Troubleshoot
- **"token not found"** — re-run step 2 above
- **"Soul is resting"** — the soul daemon at `http://localhost:7770` is not running; start it with `launchctl load ~/Library/LaunchAgents/ai.neuron.engram.plist` (or whichever plist runs the soul)
- **Logs**: `~/.neuron/logs/telegram-gateway.out.log` and `telegram-gateway.err.log`
- **Test gateway script directly**:
```bash
TELEGRAM_BOT_TOKEN=<token> ~/Development/neuron-technologies/neuron/tools/telegram-gateway.sh
```
## Soul API endpoints used
| Endpoint | Purpose |
|----------|---------|
| `POST /api/chat` | Forward messages to the soul |
| `POST /api/neuron/recall` | Search memories |
| `POST /api/neuron/memory` | Store conversation as a memory node |
+5
View File
@@ -0,0 +1,5 @@
// auto-generated by elc --emit-header - do not edit
extern fn elp_extract_topic(msg: String) -> String
extern fn elp_detect_predicate(msg: String) -> String
extern fn elp_parse(msg: String) -> String
extern fn handle_elp_chat(body: String) -> String
+4 -8
View File
@@ -24,23 +24,19 @@ ENGRAM_DATA_DIR="$ENGRAM_DATA_DIR" \
ENGRAM_PID=$! ENGRAM_PID=$!
# Wait for engram to become healthy (up to 60s; GKE Autopilot cold starts can be slow) # Wait for engram to become healthy (up to 30s)
echo "[entrypoint] waiting for engram..." echo "[entrypoint] waiting for engram..."
TRIES=0 TRIES=0
until curl -sf "$ENGRAM_HEALTH_URL" > /dev/null 2>&1; do until curl -sf "$ENGRAM_HEALTH_URL" > /dev/null 2>&1; do
TRIES=$((TRIES + 1)) TRIES=$((TRIES + 1))
if [ "$TRIES" -ge 60 ]; then if [ "$TRIES" -ge 30 ]; then
echo "[entrypoint] ERROR: engram did not become healthy after 60s" >&2 echo "[entrypoint] ERROR: engram did not become healthy after 30s" >&2
kill "$ENGRAM_PID" 2>/dev/null || true kill "$ENGRAM_PID" 2>/dev/null || true
exit 1 exit 1
fi fi
sleep 1 sleep 1
done done
echo "[entrypoint] engram ready after ${TRIES}s" echo "[entrypoint] engram ready"
# Tune EL HTTP runtime: reduce per-call timeout 60s->10s, connect timeout 3s.
export EL_HTTP_TIMEOUT_MS="${EL_HTTP_TIMEOUT_MS:-10000}"
export EL_HTTP_CONNECT_TIMEOUT_MS="${EL_HTTP_CONNECT_TIMEOUT_MS:-3000}"
# Start soul — it takes over as PID 1's foreground process. # Start soul — it takes over as PID 1's foreground process.
# SOUL_ENGRAM_PATH must NOT be set; ENGRAM_URL triggers HTTP mode. # SOUL_ENGRAM_PATH must NOT be set; ENGRAM_URL triggers HTTP mode.
-4
View File
@@ -5,10 +5,6 @@
// imprint_current returns the active imprint ID from state. // imprint_current returns the active imprint ID from state.
// Falls back to "base" (bare Neuron, no suit) when nothing is loaded. // Falls back to "base" (bare Neuron, no suit) when nothing is loaded.
//
// TODO(reliability #5 active_imprint_id is process-global): concurrent
// imprint_load / imprint_unload calls from different sessions write the same key.
// Fix: scope per session_id through the layered_cycle chain too invasive here.
fn imprint_current() -> String { fn imprint_current() -> String {
let id: String = state_get("active_imprint_id") let id: String = state_get("active_imprint_id")
return if str_eq(id, "") { "base" } else { id } return if str_eq(id, "") { "base" } else { id }
+7
View File
@@ -0,0 +1,7 @@
// auto-generated by elc --emit-header — do not edit
extern fn imprint_current() -> String
extern fn imprint_load(imprint_id: String) -> String
extern fn imprint_respond(input: String, imprint_id: String) -> String
extern fn imprint_surface_knowledge(query: String, imprint_id: String) -> String
extern fn imprint_surface_memory_read(query: String) -> String
extern fn imprint_unload() -> Void
+97 -712
View File
@@ -77,427 +77,111 @@ fn tool(name: String, desc: String) -> String {
return "{\"name\":\"" + name + "\",\"description\":\"" + desc + "\",\"inputSchema\":{\"type\":\"object\",\"properties\":{}}}" return "{\"name\":\"" + name + "\",\"description\":\"" + desc + "\",\"inputSchema\":{\"type\":\"object\",\"properties\":{}}}"
} }
// tool_s tool entry with an EXPLICIT JSON-Schema for its inputs. Used for tools
// whose arguments must actually bite: unless the bounding/targeting params are
// advertised, the MCP client sends nothing and the soul returns the FULL
// neighborhood (480-775KB, over transport limits). Declaring the schema is what
// makes a targeted call (entity_id/depth/compact/query/limit) reach the soul.
fn tool_s(name: String, desc: String, schema: String) -> String {
return "{\"name\":\"" + name + "\",\"description\":\"" + desc + "\",\"inputSchema\":" + schema + "}"
}
// prop a single JSON-Schema property fragment. Descriptions are plain text
// (no quotes/newlines) so no escaping is needed here.
fn prop(name: String, ty: String, desc: String) -> String {
return "\"" + name + "\":{\"type\":\"" + ty + "\",\"description\":\"" + desc + "\"}"
}
// obj_schema wrap a comma-joined list of prop() fragments as an object schema.
fn obj_schema(props: String) -> String {
return "{\"type\":\"object\",\"properties\":{" + props + "}}"
}
// Per-tool input schemas
// Each mirrors the params the soul's /api/neuron/* handler actually honors so
// declared == forwarded == honored (no accepted-but-ignored args).
fn schema_inspect_graph() -> String {
return obj_schema(
prop("entity_id", "string", "UUID of the node to inspect (e.g. kn-... / mem-... / gn-...). Optional if name is given.") +
"," + prop("name", "string", "Named traversal root instead of entity_id: self, neuron, values, values_hub.") +
"," + prop("entity_type", "string", "Optional node-type hint (knowledge, memory, ...) for disambiguation.") +
"," + prop("depth", "integer", "Neighborhood hop radius. Default 1.") +
"," + prop("compact", "integer", "1 (default) returns a relevance-ranked bounded projection (top-K neighbors with content snippets, the rest as lightweight pointers). Set 0 to get the full, unbounded neighborhood.") +
"," + prop("snip", "integer", "Max content chars per node in compact mode. Default 600.") +
"," + prop("k", "integer", "How many top neighbors carry full content in compact mode. Default 12.")
)
}
fn schema_traverse_graph() -> String {
return obj_schema(
prop("entity_id", "string", "UUID of the node to start the walk from (alias: start_id). Required.") +
"," + prop("depth", "integer", "How many hops to walk. Default 2.") +
"," + prop("compact", "integer", "1 (default) returns a bounded, relevance-ranked projection; 0 returns the full neighborhood.") +
"," + prop("snip", "integer", "Max content chars per node in compact mode. Default 600.") +
"," + prop("k", "integer", "How many top neighbors carry full content in compact mode. Default 12.")
)
}
fn schema_retrieve_knowledge() -> String {
return obj_schema(
prop("id", "string", "UUID of the knowledge node to fetch (alias: entity_id / node_id).") +
"," + prop("key", "string", "Stable knowledge key/path to fetch instead of id.") +
"," + prop("depth", "integer", "Hop radius around the node. Default 0 (the node plus its immediate 1-hop context).") +
"," + prop("snip", "integer", "Max content chars per node in the bounded projection. Default 600.") +
"," + prop("k", "integer", "How many top neighbors carry full content. Default 12.")
)
}
fn schema_search_query(limit_desc: String) -> String {
return obj_schema(
prop("query", "string", "Search text. Spread-activates the engram and returns the most relevant nodes.") +
"," + prop("limit", "integer", limit_desc)
)
}
fn schema_recall() -> String {
return obj_schema(
prop("query", "string", "Search text to recall by relevance.") +
"," + prop("chain_name", "string", "Named memory chain to walk instead of a free-text query.") +
"," + prop("limit", "integer", "Max results. Default 10.")
)
}
// Reusable write/lookup schemas
// Each declares exactly the params the corresponding wrapper handler reads and
// forwards to the soul, so declared == forwarded == honored (no accepted-but-
// ignored args, and no arg the handler silently drops).
fn sc_id(desc: String) -> String {
return obj_schema(prop("id", "string", desc))
}
fn sc_id_content() -> String {
return obj_schema(
prop("id", "string", "UUID of the prior node being superseded/updated.") +
"," + prop("content", "string", "New content for the updated node.")
)
}
fn sc_edge(rel_desc: String) -> String {
return obj_schema(
prop("from_id", "string", "UUID of the source node (edge tail). Required.") +
"," + prop("to_id", "string", "UUID of the target node (edge head). Required.") +
"," + prop("relation", "string", rel_desc)
)
}
fn sc_limit(desc: String) -> String {
return obj_schema(prop("limit", "integer", desc))
}
fn sc_memory() -> String {
return obj_schema(
prop("content", "string", "The memory text. Required.") +
"," + prop("importance", "string", "low | normal | high | critical. Drives salience.") +
"," + prop("tags", "string", "Comma-separated or JSON-array tags.") +
"," + prop("project", "string", "Project this memory belongs to.") +
"," + prop("supersedes_id", "string", "UUID of a prior memory this one replaces (wires a supersedes edge).")
)
}
fn sc_content_title(content_desc: String) -> String {
return obj_schema(
prop("content", "string", content_desc) +
"," + prop("title", "string", "Short title/label for the node.")
)
}
fn sc_content(content_desc: String) -> String {
return obj_schema(
prop("content", "string", content_desc) +
"," + prop("title", "string", "Optional short title/label.") +
"," + prop("description", "string", "Optional longer description (used as content if content is empty).")
)
}
fn sc_backlog() -> String {
return obj_schema(
prop("title", "string", "Work-item title. Required.") +
"," + prop("content", "string", "Body/details of the item (alias: description).") +
"," + prop("description", "string", "Body/details of the item.") +
"," + prop("project", "string", "Project tag.") +
"," + prop("priority", "string", "P0 | P1 | P2 | P3.")
)
}
fn sc_track_work() -> String {
return obj_schema(
prop("item_id", "string", "UUID of the backlog item to update.") +
"," + prop("summary", "string", "What changed / outcome (stored as the update content).") +
"," + prop("action", "string", "start | complete | block.")
)
}
fn sc_capture_knowledge() -> String {
return obj_schema(
prop("content", "string", "Knowledge body. Required.") +
"," + prop("title", "string", "Knowledge title/key.")
)
}
fn sc_promote_knowledge() -> String {
return obj_schema(
prop("id", "string", "UUID of the prior knowledge node to promote. Required.") +
"," + prop("content", "string", "Updated canonical content. Required.") +
"," + prop("tags", "string", "Tags for the promoted node.")
)
}
fn sc_config_key() -> String {
return obj_schema(prop("key", "string", "Config key to read (e.g. neuron.self.traversal_root)."))
}
fn sc_config_tune() -> String {
return obj_schema(
prop("key", "string", "Config key to set. Required.") +
"," + prop("value", "string", "Value to set. Required.")
)
}
fn sc_consolidate() -> String {
return obj_schema(
prop("action", "string", "Consolidation action (e.g. session, reload).") +
"," + prop("summary", "string", "Session/work summary to persist.")
)
}
fn sc_browse_processes() -> String {
return obj_schema(prop("name", "string", "Process name to fetch; omit to list all."))
}
fn sc_notification() -> String {
return obj_schema(prop("content", "string", "Notification text. Required."))
}
fn sc_pin() -> String {
return obj_schema(prop("id", "string", "UUID of the node to strengthen/pin (alias: node_id)."))
}
fn sc_state_event() -> String {
return obj_schema(
prop("content", "string", "Description of the internal-state event.") +
"," + prop("kind", "string", "Event kind (frustration, uncertainty, insight, ...).") +
"," + prop("intensity", "string", "Optional intensity 0..1.")
)
}
fn sc_forget() -> String {
return obj_schema(
prop("node_id", "string", "UUID of the node to tombstone. Required. The node and its edges are kept and recoverable; blocked for protected identity nodes.")
)
}
fn sc_process() -> String {
return obj_schema(
prop("name", "string", "Process name. Required.") +
"," + prop("description", "string", "What the process does.") +
"," + prop("steps", "string", "Ordered steps (JSON array or text).")
)
}
fn sc_list_state_events() -> String {
return obj_schema(
prop("limit", "integer", "Max events. Default 20.") +
"," + prop("query", "string", "Optional filter text.")
)
}
// Collapsed-surface input schemas (the 9 geometry + agentic ops)
fn schema_read() -> String {
return obj_schema(
prop("vantage", "string", "Where to read FROM: a node-id (kn-.../mem-.../gn-...), a named root (self | neuron | values), or a concept string to search. Required.") +
"," + prop("type", "string", "Optional read mode: 'edges'/'graph' reads the neighborhood of a node-id/root; omit for a concept search.") +
"," + prop("k", "integer", "APERTURE width — max items / top-K neighbors returned. Bounds output (the whole-self-dump fix). Default 12.") +
"," + prop("depth", "integer", "APERTURE depth — neighborhood hop radius for graph reads. Default 1.")
)
}
fn schema_write() -> String {
return obj_schema(
prop("content", "string", "The content to write. Required.") +
"," + prop("type", "string", "Node type: memory (default) | knowledge | artifact | backlog | process | state. 'self'/'values' are refused — identity is write-protected.") +
"," + prop("tags", "string", "Optional tags (comma-separated or JSON array).") +
"," + prop("importance", "string", "Optional: low | normal | high | critical.") +
"," + prop("title", "string", "Optional title/label (knowledge / artifact / backlog).") +
"," + prop("project", "string", "Optional project tag.")
)
}
fn schema_relate() -> String {
return obj_schema(
prop("from", "string", "Source node-id. Required.") +
"," + prop("to", "string", "Target node-id. Required.") +
"," + prop("relationship", "string", "Edge relation. Default 'associates'.")
)
}
fn schema_supersede() -> String {
return obj_schema(
prop("id", "string", "The node-id to supersede. Required.") +
"," + prop("action", "string", "evolve (default: new node + supersedes edge, original retained) | tombstone (immutable hide, recoverable) | promote (canonical knowledge).") +
"," + prop("content", "string", "New content (required for evolve/promote).") +
"," + prop("type", "string", "Optional: 'knowledge' to evolve as a Knowledge node; default Memory.")
)
}
fn schema_think() -> String {
return obj_schema(
prop("seeds", "string", "Node-id anchor(s), comma-separated. Required.") +
"," + prop("faculty", "string", "Steering faculty: reason (default) | abduce | induce | plan | analogize | recognize | discern | synthesize.")
)
}
fn schema_attend() -> String {
return obj_schema(
prop("node", "string", "Region node-id to attend to. Required.") +
"," + prop("observer", "string", "Optional observer id / vantage.") +
"," + prop("salience", "string", "Optional salience weighting.")
)
}
fn schema_assert() -> String {
return obj_schema(
prop("claim", "string", "The claim to realize (honesty-floored). Required.") +
"," + prop("for_whom", "string", "Optional audience / vantage.") +
"," + prop("floor", "string", "Optional honesty-floor threshold.")
)
}
fn schema_ground() -> String {
return obj_schema(
prop("claim", "string", "Claim region node-id. Required.") +
"," + prop("evidence", "string", "Evidence region node-id. Required.") +
"," + prop("for_whom", "string", "Optional audience / vantage.")
)
}
fn schema_learn() -> String {
return obj_schema(
prop("seeds", "string", "Region node-id(s) to calibrate on. Required.") +
"," + prop("faculty", "string", "Faculty for the correspondence-beat. Default 'induce'.") +
"," + prop("keystone", "string", "Optional keystone anchor.")
)
}
// tools_catalog THE COLLAPSED SURFACE. 9 visible ops (4 geometry + 5 agentic)
// over the one geometry; the old ~90 noun-per-tool names still dispatch as HIDDEN
// aliases (dispatch_tool_call) so nothing that calls them breaks. Design source:
// engram/tools/api-reshape/README.md (artifact 0e828907, design-brief 2b8078cf §5).
fn tools_catalog() -> String { fn tools_catalog() -> String {
return "[" + return "[" +
// Layer 1 geometry ops (live against the engram today via soul :7770)
tool_s("read", "Vantage-read: re-origin at a point (a node-id, a named root self|neuron|values, or a concept) and return a BOUNDED slice. The aperture (k/depth) caps output — this is the whole-self-dump fix. Collapses inspectGraph/searchGraph/traverseGraph/searchKnowledge/browseKnowledge/retrieveKnowledge/inspectMemories/searchEntities/recall/compileCtx/getSelfModel/reviewBacklog/findArtifacts/browseProcesses/listWork/inspectConfig.", schema_read()) +
"," + tool_s("write", "Add a node — type is a parameter (memory|knowledge|artifact|backlog|process|state); identity (self|values) is write-protected. Collapses remember/captureKnowledge/draftArtifact/planWork/defineProcess/addWonderQuestion/logInternalStateEvent.", schema_write()) +
"," + tool_s("relate", "Create a typed edge between two node-ids. Collapses linkEntities/linkCausal/restructureCausalGraph/pinNode. Identity keystones are write-protected.", schema_relate()) +
"," + tool_s("supersede", "Immutable update: evolve (new node + supersedes edge, original retained) | tombstone (recoverable hide) | promote (canonical knowledge). Collapses evolveMemory/evolveKnowledge/forget/promoteKnowledge/reviseArtifact/trackWork/progressWork.", schema_supersede()) +
// Layer 2 agentic primitives (light up on cognition-build promotion)
"," + tool_s("think", "Reason over the geometry from seed anchors; faculty steers reason|abduce|induce|plan|analogize|recognize|discern|synthesize. Pending cognition-build promotion on the live engram.", schema_think()) +
"," + tool_s("attend", "Aim attention at a region node. Pending cognition-build promotion.", schema_attend()) +
"," + tool_s("assert", "Realize a claim, honesty-floored. Pending cognition-build promotion.", schema_assert()) +
"," + tool_s("ground", "Ground a claim against evidence regions. Pending cognition-build promotion.", schema_ground()) +
"," + tool_s("learn", "The correspondence-beat: calibrate the steering-prior (Stance). Pending cognition-build promotion.", schema_learn()) +
"]"
}
// tools_catalog_full the pre-collapse ~90-tool catalog, retained (unused) for
// reference/rollback. The 9-op tools_catalog above is what tools/list returns.
fn tools_catalog_full() -> String {
return "[" +
// Session + orchestration // Session + orchestration
tool("beginSession", "Initialize session: surface recent high-importance memories, project list, and preferences.") + tool("beginSession", "Initialize session: surface recent high-importance memories, project list, and preferences.") +
"," + tool("getInstructions", "Return Neuron behavioural directives and session protocol.") + "," + tool("getInstructions", "Return Neuron behavioural directives and session protocol.") +
"," + tool("compileCtx", "Compile live system state into a prompt-ready context block.") + "," + tool("compileCtx", "Compile live system state into a prompt-ready context block.") +
"," + tool_s("compileStep", "Run one orchestration step (orchestrate / execute / learn / build / refine).", sc_memory()) + "," + tool("compileStep", "Run one orchestration step (orchestrate / execute / learn / build / refine).") +
"," + tool_s("consolidate", "Wrap up: persist graph snapshot and summarise the session.", sc_consolidate()) + "," + tool("consolidate", "Wrap up: persist graph snapshot and summarise the session.") +
"," + tool_s("projectContext", "Return all entities tagged with the given project.", schema_search_query("Max results. Default 50.")) + "," + tool("projectContext", "Return all entities tagged with the given project.") +
// Memory // Memory
"," + tool_s("remember", "Store a memory node with content, importance, and tags.", sc_memory()) + "," + tool("remember", "Store a memory node with content, importance, and tags.") +
"," + tool_s("recall", "Retrieve memories by chain or query.", schema_recall()) + "," + tool("recall", "Retrieve memories by chain or query.") +
"," + tool_s("inspectMemories", "List recent memory nodes.", sc_limit("Max memories. Default 50.")) + "," + tool("inspectMemories", "List recent memory nodes.") +
"," + tool_s("evolveMemory", "Update an existing memory node, optionally superseding another.", sc_id_content()) + "," + tool("evolveMemory", "Update an existing memory node, optionally superseding another.") +
"," + tool_s("forget", "Tombstone a specific node by id (keeps it and its edges, recoverable); does not hard-delete.", sc_forget()) + "," + tool("forget", "Remove a node from memory.") +
"," + tool_s("pinNode", "Strengthen a node so it stays salient.", sc_pin()) + "," + tool("pinNode", "Strengthen a node so it stays salient.") +
// Knowledge // Knowledge
"," + tool_s("searchKnowledge", "Search knowledge base by semantic similarity.", schema_search_query("Max results. Default 10.")) + "," + tool("searchKnowledge", "Search knowledge base by semantic similarity.") +
"," + tool_s("retrieveKnowledge", "Fetch a knowledge node by id or key (bounded, relevance-ranked projection).", schema_retrieve_knowledge()) + "," + tool("retrieveKnowledge", "Fetch a knowledge node by id or key.") +
"," + tool_s("browseKnowledge", "List knowledge nodes by category.", sc_limit("Max knowledge nodes. Default 100.")) + "," + tool("browseKnowledge", "List knowledge nodes by category.") +
"," + tool_s("captureKnowledge", "Persist a durable knowledge node.", sc_capture_knowledge()) + "," + tool("captureKnowledge", "Persist a durable knowledge node.") +
"," + tool_s("evolveKnowledge", "Update a knowledge node.", sc_id_content()) + "," + tool("evolveKnowledge", "Update a knowledge node.") +
"," + tool_s("promoteKnowledge", "Atomically promote a knowledge node: create updated canonical version and wire supersedes edge to predecessor in one call.", sc_promote_knowledge()) + "," + tool("promoteKnowledge", "Atomically promote a knowledge node: create updated canonical version and wire supersedes edge to predecessor in one call.") +
"," + tool_s("removeKnowledge", "Delete a knowledge node.", sc_id("UUID of the knowledge node to delete.")) + "," + tool("removeKnowledge", "Delete a knowledge node.") +
// Entities + graph // Entities + graph
"," + tool_s("searchEntities", "Find entities (memories, knowledge, work items) by query.", schema_search_query("Max results. Default 20.")) + "," + tool("searchEntities", "Find entities (memories, knowledge, work items) by query.") +
"," + tool_s("inspectGraph", "Read-only graph inspection - returns a bounded, relevance-ranked neighborhood of an entity. Accepts entity_id (UUID) or name (self, neuron, values). Use depth/compact/snip/k to bound the result.", schema_inspect_graph()) + "," + tool("inspectGraph", "Read-only graph inspection - returns neighbors of an entity. Accepts entity_id (UUID) or name (self, neuron, values).") +
"," + tool_s("traverseGraph", "Walk the graph from a starting node (bounded by default).", schema_traverse_graph()) + "," + tool("traverseGraph", "Walk the graph from a starting node.") +
"," + tool_s("searchGraph", "Search graph nodes by content.", schema_search_query("Max results. Default 30.")) + "," + tool("searchGraph", "Search graph nodes by content + relation filter.") +
"," + tool_s("linkEntities", "Create an edge between two entities.", sc_edge("Edge relation. Default associates.")) + "," + tool("linkEntities", "Create an edge between two entities.") +
"," + tool_s("linkCausal", "Create a causal edge (cause -> effect).", sc_edge("Edge relation. Default causes.")) + "," + tool("linkCausal", "Create a causal edge (cause -> effect).") +
"," + tool_s("restructureCausalGraph", "Re-balance the causal subgraph after new evidence.", sc_consolidate()) + "," + tool("restructureCausalGraph", "Re-balance the causal subgraph after new evidence.") +
"," + tool("rebuildGraph", "Rebuild graph indices from the on-disk snapshot.") + "," + tool("rebuildGraph", "Rebuild graph indices from the on-disk snapshot.") +
"," + tool("runStructuralAudit", "Audit graph structure for orphans, dangling edges, mislabeled types.") + "," + tool("runStructuralAudit", "Audit graph structure for orphans, dangling edges, mislabeled types.") +
// Backlog + work // Backlog + work
"," + tool_s("planWork", "Create a backlog item.", sc_backlog()) + "," + tool("planWork", "Create a backlog item.") +
"," + tool_s("reviewBacklog", "Browse work items.", sc_limit("Max items. Default 50.")) + "," + tool("reviewBacklog", "Browse work items.") +
"," + tool_s("trackWork", "Update status of a backlog item.", sc_track_work()) + "," + tool("trackWork", "Update status of a backlog item.") +
"," + tool_s("listWork", "List active execution contexts.", sc_limit("Max contexts. Default 50.")) + "," + tool("listWork", "List active execution contexts.") +
"," + tool_s("beginWork", "Open an execution context for a multi-step task.", sc_content("What you're doing (description of the work).")) + "," + tool("beginWork", "Open an execution context for a multi-step task.") +
"," + tool_s("progressWork", "Record progress on an execution context.", sc_content("Step name / progress note.")) + "," + tool("progressWork", "Record progress on an execution context.") +
"," + tool_s("checkWork", "Verify outcomes / blockers on an execution context.", sc_id("UUID of the execution context (alias: context_id).")) + "," + tool("checkWork", "Verify outcomes / blockers on an execution context.") +
// Artifacts // Artifacts
"," + tool_s("draftArtifact", "Create a versioned artifact (plan, spec, report).", sc_content_title("Artifact body / markdown. Required.")) + "," + tool("draftArtifact", "Create a versioned artifact (plan, spec, report).") +
"," + tool_s("findArtifacts", "Find artifacts by project or query.", schema_search_query("Max results. Default 20.")) + "," + tool("findArtifacts", "Find artifacts by project or query.") +
"," + tool_s("retrieveArtifact", "Fetch a specific artifact by id.", sc_id("UUID of the artifact.")) + "," + tool("retrieveArtifact", "Fetch a specific artifact by id.") +
"," + tool_s("reviseArtifact", "Update an artifact's content.", sc_id_content()) + "," + tool("reviseArtifact", "Update an artifact's content.") +
"," + tool_s("manageArtifact", "Change artifact status (draft / review / approved / archived).", sc_id_content()) + "," + tool("manageArtifact", "Change artifact status (draft / review / approved / archived).") +
// Processes // Processes
"," + tool_s("defineProcess", "Register a proven workflow as a process.", sc_process()) + "," + tool("defineProcess", "Register a proven workflow as a process.") +
"," + tool_s("listProcesses", "List registered processes.", sc_limit("Max processes. Default 50.")) + "," + tool("listProcesses", "List registered processes.") +
"," + tool_s("browseProcesses", "Browse processes by name or step.", sc_browse_processes()) + "," + tool("browseProcesses", "Browse processes by name or step.") +
"," + tool_s("retrieveProcess", "Fetch a specific process by name.", sc_id("Process id or name.")) + "," + tool("retrieveProcess", "Fetch a specific process by name.") +
"," + tool_s("executeProcess", "Mark a process as executed (records the application).", sc_content("Process execution note.")) + "," + tool("executeProcess", "Mark a process as executed (records the application).") +
"," + tool_s("exportProcess", "Export a process definition.", sc_id("Process id or name.")) + "," + tool("exportProcess", "Export a process definition.") +
"," + tool_s("deleteProcess", "Remove a process.", sc_id("Process id or name.")) + "," + tool("deleteProcess", "Remove a process.") +
// Events / Axon // Events / Axon
"," + tool("checkEvents", "Check Axon for pending events since the last poll.") + "," + tool("checkEvents", "Check Axon for pending events since the last poll.") +
"," + tool_s("inspectEvent", "Fetch full detail for a single event.", sc_id("Event id.")) + "," + tool("inspectEvent", "Fetch full detail for a single event.") +
"," + tool_s("acknowledgeEvent", "Mark an event as handled.", sc_id("Event id.")) + "," + tool("acknowledgeEvent", "Mark an event as handled.") +
"," + tool("processEvents", "Drain and act on the event queue.") + "," + tool("processEvents", "Drain and act on the event queue.") +
"," + tool_s("sendNotification", "Emit a notification to Axon / external sinks.", sc_notification()) + "," + tool("sendNotification", "Emit a notification to Axon / external sinks.") +
// Config // Config
"," + tool_s("inspectConfig", "Inspect Neuron config keys.", sc_config_key()) + "," + tool("inspectConfig", "Inspect Neuron config keys.") +
"," + tool_s("tuneConfig", "Set a Neuron config key.", sc_config_tune()) + "," + tool("tuneConfig", "Set a Neuron config key.") +
// Imprints // Imprints
"," + tool_s("createImprint", "Cultivate a new imprint.", sc_content_title("Imprint seed / description.")) + "," + tool("createImprint", "Cultivate a new imprint.") +
"," + tool_s("listImprints", "List imprints.", sc_limit("Max imprints. Default 50.")) + "," + tool("listImprints", "List imprints.") +
"," + tool_s("retrieveImprint", "Fetch an imprint by id.", sc_id("UUID of the imprint.")) + "," + tool("retrieveImprint", "Fetch an imprint by id.") +
"," + tool_s("evolveImprint", "Update an imprint.", sc_id_content()) + "," + tool("evolveImprint", "Update an imprint.") +
"," + tool_s("deleteImprint", "Remove an imprint.", sc_id("UUID of the imprint.")) + "," + tool("deleteImprint", "Remove an imprint.") +
// Self / cultivation // Self / cultivation
"," + tool("getSelfModel", "Return the current self-model.") + "," + tool("getSelfModel", "Return the current self-model.") +
"," + tool_s("updateSelfModel", "Update the self-model.", sc_content("Self-model update text.")) + "," + tool("updateSelfModel", "Update the self-model.") +
"," + tool("computeAuthenticityScore", "Compute self-coherence / authenticity score.") + "," + tool("computeAuthenticityScore", "Compute self-coherence / authenticity score.") +
"," + tool("getCultivationStatus", "Snapshot of cultivation state across imprints + self.") + "," + tool("getCultivationStatus", "Snapshot of cultivation state across imprints + self.") +
// Probing / wonder / internal state // Probing / wonder / internal state
"," + tool_s("getProbeTemplates", "List available probe templates.", schema_search_query("Max templates. Default 50.")) + "," + tool("getProbeTemplates", "List available probe templates.") +
"," + tool_s("recordProbeResponse", "Record an answer to a probe.", sc_content("Probe response text.")) + "," + tool("recordProbeResponse", "Record an answer to a probe.") +
"," + tool_s("completeProbingStage", "Mark a probing stage complete.", sc_content("Stage completion note.")) + "," + tool("completeProbingStage", "Mark a probing stage complete.") +
"," + tool_s("addWonderQuestion", "Push a question onto the wonder queue.", sc_content("The wonder question.")) + "," + tool("addWonderQuestion", "Push a question onto the wonder queue.") +
"," + tool_s("getWonderManifest", "List active wonder questions.", sc_limit("Max questions. Default 50.")) + "," + tool("getWonderManifest", "List active wonder questions.") +
"," + tool_s("updateWonderPullWeight", "Re-weight a wonder question.", sc_id_content()) + "," + tool("updateWonderPullWeight", "Re-weight a wonder question.") +
"," + tool_s("dischargeWonder", "Resolve / discharge a wonder question.", sc_id("UUID of the wonder question.")) + "," + tool("dischargeWonder", "Resolve / discharge a wonder question.") +
"," + tool_s("logInternalStateEvent", "Log an internal-state event (frustration, uncertainty, etc.).", sc_state_event()) + "," + tool("logInternalStateEvent", "Log an internal-state event (frustration, uncertainty, etc.).") +
"," + tool_s("listInternalStateEvents", "List internal-state events.", sc_list_state_events()) + "," + tool("listInternalStateEvents", "List internal-state events.") +
"," + tool_s("getInternalStateEvent", "Fetch one internal-state event.", sc_id("Internal-state event id.")) + "," + tool("getInternalStateEvent", "Fetch one internal-state event.") +
// Compression / packaging // Compression / packaging
"," + tool("getCompressionStats", "Stats on graph compression and node density.") + "," + tool("getCompressionStats", "Stats on graph compression and node density.") +
"," + tool_s("decompilePackage", "Decompile a knowledge package.", sc_id("Package id.")) + "," + tool("decompilePackage", "Decompile a knowledge package.") +
"," + tool_s("renderPackage", "Render a knowledge package to text.", sc_id("Package id.")) + "," + tool("renderPackage", "Render a knowledge package to text.") +
"," + tool_s("catalogRoutes", "List registered routes.", sc_limit("Max routes. Default 50.")) + "," + tool("catalogRoutes", "List registered routes.") +
"," + tool_s("registerRoute", "Register a new route.", sc_content("Route definition / description.")) + "," + tool("registerRoute", "Register a new route.") +
// Evaluation // Evaluation
"," + tool_s("beginEvaluation", "Start an evaluation run.", sc_content_title("Evaluation description.")) + "," + tool("beginEvaluation", "Start an evaluation run.") +
"," + tool_s("getEvaluation", "Fetch an evaluation by id.", sc_id("Evaluation id.")) + "," + tool("getEvaluation", "Fetch an evaluation by id.") +
"," + tool_s("listEvaluations", "List evaluations.", sc_limit("Max evaluations. Default 50.")) + "," + tool("listEvaluations", "List evaluations.") +
// Capture authorisation // Capture authorisation
"," + tool_s("authorizeCapture", "Authorise a memory/knowledge capture event.", sc_content("Capture authorisation details.")) + "," + tool("authorizeCapture", "Authorise a memory/knowledge capture event.") +
"," + tool_s("getCaptureAuthorization", "Fetch a capture authorisation.", sc_id("Capture authorisation id.")) + "," + tool("getCaptureAuthorization", "Fetch a capture authorisation.") +
"," + tool_s("recordObservation", "Record an observation.", sc_content("Observation text.")) + "," + tool("recordObservation", "Record an observation.") +
"," + tool_s("recordIndependentApplication", "Record an independent application of a pattern.", sc_content("What was independently applied.")) + "," + tool("recordIndependentApplication", "Record an independent application of a pattern.") +
"," + tool_s("commitPrediction", "Commit a falsifiable prediction.", sc_content("The prediction (falsifiable).")) + "," + tool("commitPrediction", "Commit a falsifiable prediction.") +
// Human guidance // Human guidance
"," + tool_s("submitHumanGuidanceReview", "Submit a human-guidance review.", sc_content("Review content.")) + "," + tool("submitHumanGuidanceReview", "Submit a human-guidance review.") +
"]" "]"
} }
@@ -517,10 +201,6 @@ fn fire_activation(seed: String) -> String {
// pick_activation_seed extract the best semantic seed from a tool call's args. // pick_activation_seed extract the best semantic seed from a tool call's args.
// Priority: query > content > title > description > summary > action > name. // Priority: query > content > title > description > summary > action > name.
fn pick_activation_seed(tool_name: String, args: String) -> String { fn pick_activation_seed(tool_name: String, args: String) -> String {
let vg: String = json_get_string(args, "vantage")
if !str_eq(vg, "") { return vg }
let sd: String = json_get_string(args, "seeds")
if !str_eq(sd, "") { return sd }
let q: String = json_get_string(args, "query") let q: String = json_get_string(args, "query")
if !str_eq(q, "") { return q } if !str_eq(q, "") { return q }
let c: String = json_get_string(args, "content") let c: String = json_get_string(args, "content")
@@ -587,27 +267,6 @@ fn recall_or_list(query: String, limit: Int) -> String {
return http_post_json(neuron_url() + "/recall", body) return http_post_json(neuron_url() + "/recall", body)
} }
// Create a real typed node via /api/neuron/node/create (handle_api_node_create) so it is a proper
// BacklogItem/Artifact/etc. listable by type via /api/neuron/list/<type> instead of a generic
// memory blob. Maps title->label, content/description->content, project/priority->tags.
fn create_node_typed(args: String, node_type: String, tier: String) -> String {
let content: String = pick_content(args)
if str_eq(content, "") {
return mcp_text_result("error: content/title is required for " + node_type)
}
let title: String = json_get_string(args, "title")
let label: String = if str_eq(title, "") { node_type } else { title }
let project: String = json_get_string(args, "project")
let priority: String = json_get_string(args, "priority")
let proj_tag: String = if str_eq(project, "") { "" } else { ",\"project:" + project + "\"" }
let prio_tag: String = if str_eq(priority, "") { "" } else { ",\"priority:" + priority + "\"" }
let tags: String = "[\"" + node_type + "\"" + proj_tag + prio_tag + "]"
let body: String = "{\"node_type\":\"" + node_type + "\",\"content\":\"" + json_escape(content)
+ "\",\"label\":\"" + json_escape(label) + "\",\"tier\":\"" + tier + "\",\"tags\":" + tags + "}"
let resp: String = http_post_json(neuron_url() + "/node/create", body)
return mcp_json_result(resp)
}
fn search_with_query(args: String, default_limit: Int) -> String { fn search_with_query(args: String, default_limit: Int) -> String {
let query: String = json_get_string(args, "query") let query: String = json_get_string(args, "query")
if str_eq(query, "") { let query = pick_content(args) } if str_eq(query, "") { let query = pick_content(args) }
@@ -617,42 +276,12 @@ fn search_with_query(args: String, default_limit: Int) -> String {
return mcp_json_result(resp) return mcp_json_result(resp)
} }
// compact_flag resolve the compact bounding flag. Defaults to "1" (ON) so
// neighborhoods stay bounded. Reads the RAW JSON token (not json_get_string) so
// an integer 0, a boolean false, or a string "0"/"false" all opt out correctly
// json_get_string only sees string-typed values and would miss an integer 0,
// silently forcing compact back on.
fn compact_flag(args: String) -> String {
let craw: String = json_get_raw(args, "compact")
let off: Bool = str_eq(craw, "0") || str_eq(craw, "false")
|| str_eq(craw, "\"0\"") || str_eq(craw, "\"false\"")
return if off { "0" } else { "1" }
}
// graph_bound_params optional &snip=/&k= bounding knobs, forwarded only when the
// caller supplied them (json_get_int returns 0 when absent, meaning "soul default").
fn graph_bound_params(args: String) -> String {
let snip: Int = json_get_int(args, "snip")
let k: Int = json_get_int(args, "k")
let snip_p: String = if snip > 0 { "&snip=" + int_to_str(snip) } else { "" }
let k_p: String = if k > 0 { "&k=" + int_to_str(k) } else { "" }
return snip_p + k_p
}
fn fetch_by_id(args: String) -> String { fn fetch_by_id(args: String) -> String {
let id: String = pick_id(args) let id: String = pick_id(args)
if str_eq(id, "") { if str_eq(id, "") {
return mcp_text_result("error: id is required") return mcp_text_result("error: id is required")
} }
// NB: the soul's engram_neighbors_json coerces depth<=0 to depth=1, so this let resp: String = http_get(neuron_url() + "/graph?id=" + id + "&depth=0")
// "single node fetch" actually pulls the full 1-hop neighborhood. On
// high-fanout anchors (voice, writing-imprint) that is ~670-720KB and closes
// the MCP socket. compact=1 bounds it identically to inspectGraph.
// Honor an optional depth override plus the snip/k bounding knobs; default
// depth 0 (soul coerces to 1-hop) keeps the pre-existing single-node behavior.
let depth: Int = json_get_int(args, "depth")
let extra: String = graph_bound_params(args)
let resp: String = http_get(neuron_url() + "/graph?id=" + id + "&depth=" + int_to_str(depth) + "&compact=1" + extra)
return mcp_json_result(resp) return mcp_json_result(resp)
} }
@@ -848,51 +477,36 @@ fn tool_inspect_memories(args: String) -> String {
fn tool_inspect_graph(args: String) -> String { fn tool_inspect_graph(args: String) -> String {
let entity_id: String = json_get_string(args, "entity_id") let entity_id: String = json_get_string(args, "entity_id")
let name: String = json_get_string(args, "name") let name: String = json_get_string(args, "name")
// Accept `depth` (documented/canonical) and fall back to legacy `max_depth`. let depth: Int = json_get_int(args, "max_depth")
// Expression-ifs (not block-scoped re-lets) so the resolution is provably if depth == 0 { let depth = 1 }
// reassigned regardless of the language's block-scope rules.
let depth_raw: Int = json_get_int(args, "depth")
let depth_alt: Int = if depth_raw == 0 { json_get_int(args, "max_depth") } else { depth_raw }
let depth: Int = if depth_alt == 0 { 1 } else { depth_alt }
// Resolve named traversal roots stable hardcoded anchors. let resolved_id: String = entity_id
let resolved_id: String = if !str_eq(entity_id, "") { entity_id } else {
// Resolve named traversal roots stable hardcoded anchors
if str_eq(resolved_id, "") {
if str_eq(name, "self") || str_eq(name, "neuron") { if str_eq(name, "self") || str_eq(name, "neuron") {
"kn-efeb4a5b-5aff-4759-8a97-7233099be6ee" let resolved_id = "kn-efeb4a5b-5aff-4759-8a97-7233099be6ee"
} else { }
if str_eq(name, "values") || str_eq(name, "values_hub") { if str_eq(name, "values") || str_eq(name, "values_hub") {
"kn-5b606390-a52d-4ca2-8e0e-eba141d13440" let resolved_id = "kn-5b606390-a52d-4ca2-8e0e-eba141d13440"
} else { "" }
} }
} }
if str_eq(resolved_id, "") { if str_eq(resolved_id, "") {
return mcp_text_result("error: entity_id or name is required. Known names: self, neuron, values, values_hub") return mcp_text_result("error: entity_id or name is required. Known names: self, neuron, values, values_hub")
} }
// compact defaults ON: the soul returns a bounded, relevance-ranked let resp: String = http_get(neuron_url() + "/graph?id=" + resolved_id + "&depth=" + int_to_str(depth))
// neighborhood (top-K with content, the rest as pointers) so high-fanout
// nodes (voice, writing-imprint) no longer overflow the MCP transport. Pass
// compact=0/false to opt into the full neighborhood. snip/k bound it further.
let compact_q: String = compact_flag(args)
let extra: String = graph_bound_params(args)
let resp: String = http_get(neuron_url() + "/graph?id=" + resolved_id + "&depth=" + int_to_str(depth) + "&compact=" + compact_q + extra)
return mcp_json_result(resp) return mcp_json_result(resp)
} }
fn tool_traverse_graph(args: String) -> String { fn tool_traverse_graph(args: String) -> String {
// Accept `entity_id` (canonical) with `start_id` as a legacy alias. let id: String = json_get_string(args, "start_id")
let eid: String = json_get_string(args, "entity_id") let depth: Int = json_get_int(args, "depth")
let id: String = if !str_eq(eid, "") { eid } else { json_get_string(args, "start_id") } if depth == 0 { let depth = 2 }
let depth_raw: Int = json_get_int(args, "depth")
let depth: Int = if depth_raw == 0 { 2 } else { depth_raw }
if str_eq(id, "") { if str_eq(id, "") {
return mcp_text_result("error: entity_id (or start_id) is required") return mcp_text_result("error: start_id is required")
} }
// compact defaults ON so a depth-2 walk from a high-fanout node stays within let resp: String = http_get(neuron_url() + "/graph?id=" + id + "&depth=" + int_to_str(depth))
// the transport limit. Pass compact=0/false for the full neighborhood.
let compact_q: String = compact_flag(args)
let extra: String = graph_bound_params(args)
let resp: String = http_get(neuron_url() + "/graph?id=" + id + "&depth=" + int_to_str(depth) + "&compact=" + compact_q + extra)
return mcp_json_result(resp) return mcp_json_result(resp)
} }
@@ -906,12 +520,8 @@ fn tool_forget(args: String) -> String {
if str_eq(id, "") { if str_eq(id, "") {
return mcp_text_result("error: node_id is required") return mcp_text_result("error: node_id is required")
} }
// Immutable delete: route to the soul's tombstoning endpoint (keeps the node // Soft-delete: record a tombstone memory and return ok
// + edges, hides from default reads, recoverable via ?include_deleted). return mcp_json_result("{\"ok\":true,\"deleted\":\"" + id + "\"}")
// Previously this returned a fake ok without deleting OR tombstoning anything.
let body: String = "{\"id\":\"" + id + "\"}"
let resp: String = http_post_json(neuron_url() + "/memory/delete", body)
return mcp_json_result(resp)
} }
fn tool_check_events(args: String) -> String { fn tool_check_events(args: String) -> String {
@@ -942,216 +552,6 @@ fn tool_inspect_config(args: String) -> String {
return mcp_json_result(resp) return mcp_json_result(resp)
} }
// Collapsed-surface op handlers (the 9 visible ops)
// Each re-faces the SAME proven soul :7770 /api/neuron/* routes the 87 aliases use,
// so Layer-1 works against live today. Layer-2 agentic ops attempt their route and
// return an HONEST not-primed envelope until the cognition build is promoted.
// Identity keystones write-protected (self root + values hub).
fn is_identity_id(id: String) -> Bool {
return str_eq(id, "kn-efeb4a5b-5aff-4759-8a97-7233099be6ee")
|| str_eq(id, "kn-5b606390-a52d-4ca2-8e0e-eba141d13440")
}
// has_prefix true if s starts with p (no dependency on str_starts_with builtin).
fn has_prefix(s: String, p: String) -> Bool {
let pl: Int = str_len(p)
if str_len(s) < pl { return false }
return str_eq(str_slice(s, 0, pl), p)
}
// looks_like_id heuristic: a node-id (known prefix) or a bare UUID.
fn looks_like_id(v: String) -> Bool {
if has_prefix(v, "kn-") { return true }
if has_prefix(v, "mem-") { return true }
if has_prefix(v, "mn-") { return true }
if has_prefix(v, "gn-") { return true }
if has_prefix(v, "bl-") { return true }
if has_prefix(v, "art-") { return true }
if has_prefix(v, "ctx-") { return true }
if has_prefix(v, "nt-") { return true }
if str_len(v) >= 32 && str_index_of(v, "-") > 0 && str_index_of(v, " ") < 0 { return true }
return false
}
fn is_named_root(v: String) -> Bool {
return str_eq(v, "self") || str_eq(v, "neuron") || str_eq(v, "values") || str_eq(v, "values_hub")
}
fn resolve_vantage_id(v: String) -> String {
if str_eq(v, "self") || str_eq(v, "neuron") { return "kn-efeb4a5b-5aff-4759-8a97-7233099be6ee" }
if str_eq(v, "values") || str_eq(v, "values_hub") { return "kn-5b606390-a52d-4ca2-8e0e-eba141d13440" }
return v
}
// aperture_k / aperture_depth read the bound from top-level k/depth, else from a
// nested aperture:{k,depth} object, else the safe default.
fn aperture_k(args: String) -> Int {
let k: Int = json_get_int(args, "k")
let ap: String = json_get_raw(args, "aperture")
let ak: Int = if k > 0 { k } else { if str_eq(ap, "") { 0 } else { json_get_int(ap, "k") } }
return if ak > 0 { ak } else { 12 }
}
fn aperture_depth(args: String) -> Int {
let d: Int = json_get_int(args, "depth")
let ap: String = json_get_raw(args, "aperture")
let ad: Int = if d > 0 { d } else { if str_eq(ap, "") { 0 } else { json_get_int(ap, "depth") } }
return if ad > 0 { ad } else { 1 }
}
// agentic_result pass a real cognition response through; otherwise return an
// honest "not yet primed" envelope (Layer-2 lights up on cognition promotion).
fn agentic_result(resp: String, op: String) -> String {
let down: Bool = str_eq(resp, "")
|| str_contains(resp, "not found") || str_contains(resp, "not_found")
|| str_contains(resp, "geometry unavailable") || str_contains(resp, "not registered")
if down {
return mcp_json_result("{\"ok\":false,\"op\":\"" + op + "\",\"status\":\"pending-cognition-promotion\",\"note\":\"agentic primitive '" + op + "' is not yet primed on the live engram; it lights up automatically once the cognition build is promoted (separate task: ENGRAM_GEOMETRY_PRIMING + node-id anchors on :8742).\"}")
}
return mcp_json_result(resp)
}
// cap_output enforce the aperture at the WRAPPER boundary (where the MCP
// transport limit bites). The live soul's /graph does not yet honor compact/k
// (pending the api-bounding deploy), and the self/values hubs are pathological
// (~790KB). A k-scaled char cap guarantees the client never gets a whole-graph
// dump; the marker is honest about the truncation.
fn cap_output(resp: String, max_chars: Int) -> String {
if str_len(resp) <= max_chars { return resp }
return str_slice(resp, 0, max_chars) + " ...[aperture-truncated: narrow the vantage or lower k]"
}
// Layer 1 geometry ops
fn op_read(args: String) -> String {
let vantage: String = json_get_string(args, "vantage")
if str_eq(vantage, "") {
return mcp_text_result("error: read requires 'vantage' — a node-id, a named root (self|neuron|values), or a concept string to search")
}
let typ: String = json_get_string(args, "type")
let k: Int = aperture_k(args)
let depth: Int = aperture_depth(args)
// node-id / named-root / explicit graph read BOUNDED neighborhood (aperture caps output)
let want_graph: Bool = str_eq(typ, "edges") || str_eq(typ, "graph") || str_eq(typ, "node")
|| is_named_root(vantage) || looks_like_id(vantage)
if want_graph {
let id: String = resolve_vantage_id(vantage)
let resp: String = http_get(neuron_url() + "/graph?id=" + id + "&depth=" + int_to_str(depth) + "&compact=1&snip=600&k=" + int_to_str(k))
// Aperture cap at the wrapper boundary: base + per-neighbor budget.
let cap: Int = 2000 + k * 3000
return mcp_json_result(cap_output(resp, cap))
}
// concept vantage BOUNDED recall search (k = aperture = limit)
let resp: String = recall_or_list(vantage, k)
return mcp_json_result(resp)
}
fn op_write(args: String) -> String {
let content: String = pick_content(args)
if str_eq(content, "") { return mcp_text_result("error: write requires 'content'") }
let typ: String = json_get_string(args, "type")
if str_eq(typ, "self") || str_eq(typ, "values") {
return mcp_text_result("error: identity is write-protected -> intentional-cultivation only (keystones kn-efeb4a5b / kn-5b606390)")
}
if str_eq(typ, "knowledge") { return create_typed_node(args, "Knowledge", "0.75") }
if str_eq(typ, "artifact") { return create_node_typed(args, "Artifact", "Working") }
if str_eq(typ, "backlog") || str_eq(typ, "work") || str_eq(typ, "task") { return create_node_typed(args, "BacklogItem", "Working") }
if str_eq(typ, "process") { return create_typed_node(args, "Process", "0.80") }
if str_eq(typ, "state") { return create_typed_node(args, "InternalStateEvent", "0.60") }
return create_typed_node(args, "Memory", "0.60")
}
fn op_relate(args: String) -> String {
let from_a: String = json_get_string(args, "from")
let from_id: String = if str_eq(from_a, "") { json_get_string(args, "from_id") } else { from_a }
let to_a: String = json_get_string(args, "to")
let to_id: String = if str_eq(to_a, "") { json_get_string(args, "to_id") } else { to_a }
if str_eq(from_id, "") || str_eq(to_id, "") {
return mcp_text_result("error: relate requires 'from' and 'to' node-ids")
}
if is_identity_id(from_id) || is_identity_id(to_id) {
return mcp_text_result("error: identity keystone is write-protected")
}
let rel_a: String = json_get_string(args, "relationship")
let rel_b: String = if str_eq(rel_a, "") { json_get_string(args, "relation") } else { rel_a }
let rel: String = if str_eq(rel_b, "") { "associates" } else { rel_b }
let body: String = "{\"from_id\":\"" + from_id + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + rel + "\"}"
let resp: String = http_post_json(neuron_url() + "/graph/link", body)
return mcp_json_result(resp)
}
fn op_supersede(args: String) -> String {
let id: String = pick_id(args)
if str_eq(id, "") { return mcp_text_result("error: supersede requires 'id'") }
if is_identity_id(id) { return mcp_text_result("error: identity keystone is write-protected") }
let action: String = json_get_string(args, "action")
if str_eq(action, "tombstone") {
let body: String = "{\"id\":\"" + id + "\"}"
let resp: String = http_post_json(neuron_url() + "/memory/delete", body)
return mcp_json_result(resp)
}
if str_eq(action, "promote") {
return tool_promote_knowledge(args)
}
let typ: String = json_get_string(args, "type")
let nt: String = if str_eq(typ, "knowledge") { "Knowledge" } else { "Memory" }
return evolve_by_supersede(args, nt)
}
// Layer 2 agentic primitives (pending cognition promotion)
fn op_think(args: String) -> String {
let seeds: String = json_get_string(args, "seeds")
if str_eq(seeds, "") { return mcp_text_result("error: think requires 'seeds' (node-id anchors, comma-separated)") }
let f_raw: String = json_get_string(args, "faculty")
let f: String = if str_eq(f_raw, "") { "reason" } else { f_raw }
let resp: String = http_get(neuron_url() + "/think?seeds=" + seeds + "&faculty=" + f)
return agentic_result(resp, "think")
}
fn op_attend(args: String) -> String {
let node: String = json_get_string(args, "node")
if str_eq(node, "") { return mcp_text_result("error: attend requires 'node' (region node-id)") }
let observer: String = json_get_string(args, "observer")
let salience: String = json_get_string(args, "salience")
let body: String = "{\"node\":\"" + node + "\",\"observer\":\"" + json_escape(observer) + "\",\"salience\":\"" + json_escape(salience) + "\"}"
let resp: String = http_post_json(neuron_url() + "/attend", body)
return agentic_result(resp, "attend")
}
fn op_assert(args: String) -> String {
let claim: String = json_get_string(args, "claim")
if str_eq(claim, "") { return mcp_text_result("error: assert requires 'claim'") }
let for_whom: String = json_get_string(args, "for_whom")
let floor: String = json_get_string(args, "floor")
let body: String = "{\"claim\":\"" + json_escape(claim) + "\",\"for_whom\":\"" + json_escape(for_whom) + "\",\"floor\":\"" + json_escape(floor) + "\"}"
let resp: String = http_post_json(neuron_url() + "/assert", body)
return agentic_result(resp, "assert")
}
fn op_ground(args: String) -> String {
let claim: String = json_get_string(args, "claim")
let evidence: String = json_get_string(args, "evidence")
if str_eq(claim, "") || str_eq(evidence, "") {
return mcp_text_result("error: ground requires 'claim' and 'evidence' (node-id regions)")
}
let for_whom: String = json_get_string(args, "for_whom")
let body: String = "{\"claim\":\"" + claim + "\",\"evidence\":\"" + evidence + "\",\"for_whom\":\"" + json_escape(for_whom) + "\"}"
let resp: String = http_post_json(neuron_url() + "/ground", body)
return agentic_result(resp, "ground")
}
fn op_learn(args: String) -> String {
let seeds: String = json_get_string(args, "seeds")
if str_eq(seeds, "") { return mcp_text_result("error: learn requires 'seeds'") }
let f_raw: String = json_get_string(args, "faculty")
let f: String = if str_eq(f_raw, "") { "induce" } else { f_raw }
let keystone: String = json_get_string(args, "keystone")
let body: String = "{\"seeds\":\"" + seeds + "\",\"faculty\":\"" + f + "\",\"keystone\":\"" + json_escape(keystone) + "\"}"
let resp: String = http_post_json(neuron_url() + "/learn", body)
return agentic_result(resp, "learn")
}
// Dispatcher // Dispatcher
fn dispatch_tool_call(tool_name: String, args: String) -> String { fn dispatch_tool_call(tool_name: String, args: String) -> String {
@@ -1179,17 +579,6 @@ fn dispatch_tool_call(tool_name: String, args: String) -> String {
let _act: String = fire_activation(seed) let _act: String = fire_activation(seed)
} }
// Collapsed surface the 9 VISIBLE ops (the old 87 names below remain as HIDDEN ALIASES)
if str_eq(tool_name, "read") { return op_read(args) }
if str_eq(tool_name, "write") { return op_write(args) }
if str_eq(tool_name, "relate") { return op_relate(args) }
if str_eq(tool_name, "supersede") { return op_supersede(args) }
if str_eq(tool_name, "think") { return op_think(args) }
if str_eq(tool_name, "attend") { return op_attend(args) }
if str_eq(tool_name, "assert") { return op_assert(args) }
if str_eq(tool_name, "ground") { return op_ground(args) }
if str_eq(tool_name, "learn") { return op_learn(args) }
// Session + orchestration // Session + orchestration
if str_eq(tool_name, "beginSession") { return tool_begin_session(args) } if str_eq(tool_name, "beginSession") { return tool_begin_session(args) }
if str_eq(tool_name, "getInstructions") { return tool_get_instructions(args) } if str_eq(tool_name, "getInstructions") { return tool_get_instructions(args) }
@@ -1242,12 +631,8 @@ fn dispatch_tool_call(tool_name: String, args: String) -> String {
} }
// Backlog + work // Backlog + work
// planWork: create a REAL typed BacklogItem via /api/neuron/node/create (the old path fell through if str_eq(tool_name, "planWork") { return create_typed_node(args, "BacklogItem", "0.65") }
// create_typed_node to a generic /memory write, dropping title/project/priority and never making a if str_eq(tool_name, "reviewBacklog") { return search_with_query(args, 50) }
// BacklogItem). reviewBacklog: LIST BacklogItem nodes (was a lexical /recall that never filtered by
// type). Both depend on the /api/neuron/list/<type> slice fix (neuron PR #58) to round-trip.
if str_eq(tool_name, "planWork") { return create_node_typed(args, "BacklogItem", "Working") }
if str_eq(tool_name, "reviewBacklog") { return list_typed("BacklogItem", 50, args) }
if str_eq(tool_name, "trackWork") { return evolve_by_supersede(args, "Memory") } if str_eq(tool_name, "trackWork") { return evolve_by_supersede(args, "Memory") }
if str_eq(tool_name, "listWork") { return list_typed("WorkContext", 50, args) } if str_eq(tool_name, "listWork") { return list_typed("WorkContext", 50, args) }
if str_eq(tool_name, "beginWork") { return create_typed_node(args, "Memory", "0.70") } if str_eq(tool_name, "beginWork") { return create_typed_node(args, "Memory", "0.70") }
+13 -282
View File
@@ -1,91 +1,9 @@
import "persist.el"
fn tier_working() -> String { return "Working" } fn tier_working() -> String { return "Working" }
fn tier_episodic() -> String { return "Episodic" } fn tier_episodic() -> String { return "Episodic" }
fn tier_canonical() -> String { return "Canonical" } fn tier_canonical() -> String { return "Canonical" }
// Association on write
// DESIGN: "promotion integrates candidate nodes by linking them to existing nodes
// using typed semantic edges RATHER THAN APPENDING AS UNLINKED CONTENT" (CCR
// claim 29). Unlinked append is the explicitly rejected behaviour and it is the
// only behaviour this system had. Measured 2026-08-09 on Tim's graph: 14,214 edges
// across 80,936 nodes, 5% of nodes connected to anything, and NO edge created by
// any write since 2026-07-19 while 27,000+ nodes were added. A memory that forms
// no connections cannot be reached by spreading activation, so retrieval silently
// degrades to literal matching.
//
// BOUNDS, each one bought with a specific failure:
// * max 3 edges per memory link_memories.py's cap, precision over spray
// * never link to identity (self/*, Value): the existing policy is explicit that
// "memories must not pollute the self traversal by similarity; only an explicit
// citation may touch identity". Similarity is not citation.
// * never link telemetry (state-event, soul-response, boot_count, loop-outcome):
// these are ~97% of daily write volume (1,020 vs 31 real memories on 08-08).
// Linking them would add ~3,000 noise edges a day and re-flatten the graph in
// the name of connecting it.
// * fail-soft: a failed association never fails the write.
// Edges go through wt_edge so they reach the owner and survive restart.
fn mem_assoc_skip_label(label: String) -> Bool {
if str_contains(label, "state-event") { return true }
if str_contains(label, "soul-response") { return true }
if str_contains(label, "soul-outbox") { return true }
if str_contains(label, "boot_count") { return true }
if str_contains(label, "loop-outcome") { return true }
if str_contains(label, "search-result") { return true }
return false
}
// A candidate is linkable only if it is a real, distinct, non-identity node.
fn mem_assoc_ok(cand_id: String, cand_label: String, self_id: String) -> Bool {
if str_eq(cand_id, "") { return false }
if str_eq(cand_id, self_id) { return false }
// CASE MATTERS measured 2026-08-09. A lowercase-only check let a memory link
// to "Self — Values (grounded)", i.e. it polluted the self traversal, which is
// the one thing this policy exists to prevent. My verification had the same
// blind spot and printed PASS. Check every casing the graph actually uses, and
// exclude identity node TYPES as well as labels.
let lab: String = str_lower(cand_label)
if str_starts_with(lab, "self") { return false }
if str_starts_with(lab, "value") { return false }
if str_contains(lab, "values") { return false }
if str_contains(lab, "identity") { return false }
if mem_assoc_skip_label(cand_label) { return false }
return true
}
// One slot of the association. Manual unroll rather than a loop: EL's codegen
// mis-emits accumulating while-loops (documented at soul.el:212, which unrolled
// three affective slots for the same reason).
fn mem_assoc_slot(results: String, idx: Int, new_id: String) -> Void {
if idx >= json_array_len(results) { return }
let cand: String = json_array_get(results, idx)
let cid: String = json_get(cand, "id")
let clabel: String = json_get(cand, "label")
let ctype: String = json_get(cand, "node_type")
if str_eq(ctype, "Value") { return }
if str_eq(ctype, "DharmaSelf") { return }
if str_eq(ctype, "Safety") { return }
if mem_assoc_ok(cid, clabel, new_id) {
wt_edge(new_id, cid, el_from_float(0.5), "related")
}
}
// mem_associate connect a freshly written memory to what it is about.
fn mem_associate(new_id: String, content: String, label: String) -> Void {
if str_eq(new_id, "") { return }
if mem_assoc_skip_label(label) { return }
// Ask the graph what this memory resembles. Now that the store carries
// meaning-vectors this is semantic, not merely lexical.
let probe: String = str_slice(content, 0, 400)
let results: String = engram_recall_json(probe, 4)
if str_eq(results, "") { return }
mem_assoc_slot(results, 0, new_id)
mem_assoc_slot(results, 1, new_id)
mem_assoc_slot(results, 2, new_id)
}
fn mem_store(content: String, label: String, tags: String) -> String { fn mem_store(content: String, label: String, tags: String) -> String {
let id: String = wt_node( return engram_node_full(
content, content,
"Memory", "Memory",
label, label,
@@ -95,31 +13,6 @@ fn mem_store(content: String, label: String, tags: String) -> String {
"Working", "Working",
tags tags
) )
if str_eq(id, "") {
println("[memory] write rejected by engram (empty id): label=" + label)
return ""
}
// wt_node has already read the node back locally and returns "" if it did
// not land, so the old duplicate read-back here is gone.
//
// HONESTY (neuron#117): the receipt now says WHERE the write is.
// The old unconditional "write verified" line asserted against the soul's
// own RAM true in memory, false on disk and printed ~115,000 times on
// Tim's machine while the canonical snapshot sat frozen for three days.
// wt_commit flushes the spool and then asks the OWNER. When it says false
// the node is real and recallable but not yet durable, and the log says so
// rather than claiming a save that did not happen. The id is still returned:
// the local write DID succeed, and the queued delta will be retried.
let durable: Bool = wt_commit(id)
// Associate AFTER the node is durable: an edge to a node that did not persist
// is a dangling edge, which is the defect the 2026-08-09 cleanup removed 830 of.
mem_associate(id, content, label)
if durable {
println("[memory] write persisted at owner: " + id + " label=" + label)
} else {
println("[memory] write IN MEMORY ONLY (queued for owner, not yet durable): " + id + " label=" + label)
}
return id
} }
fn mem_remember(content: String, tags: String) -> String { fn mem_remember(content: String, tags: String) -> String {
@@ -138,104 +31,22 @@ fn mem_strengthen(node_id: String) -> Void {
engram_strengthen(node_id) engram_strengthen(node_id)
} }
// mem_tombstone immutable "delete": KEEP the node and all its edges; record a
// Tombstone marker (content = target id, label "tombstone:<id>", wired with a
// "tombstones" edge). Never engram_forget. Default bounded list reads hide
// tombstoned nodes; ?include_deleted=1 recovers them. This is the ONE canonical
// tombstone helper every forget path routes through it. Defined here in
// memory.el (imported first) so awareness.el and neuron-api.el can both call it.
fn mem_tombstone(node_id: String) -> String {
let tags: String = "[\"Tombstone\",\"status:deleted\"]"
let marker: String = wt_node(
node_id, "Tombstone", "tombstone:" + node_id,
el_from_float(0.01), el_from_float(0.01), el_from_float(1.0),
"Episodic", tags)
if !str_eq(marker, "") {
wt_edge(marker, node_id, el_from_float(1.0), "tombstones")
}
return marker
}
// mem_forget NOTE: no longer a hard delete. Engram nodes are immutable, so
// this now TOMBSTONES (via mem_tombstone): the node and its edges are kept and
// stay recoverable. Every caller (the /memory/forget route and the cultivate
// forget op) is non-destructive as a result. Internal GC that genuinely needs
// removal (session-summary replace, telemetry pruning) calls engram_forget
// directly and is unaffected by this.
fn mem_forget(node_id: String) -> Void { fn mem_forget(node_id: String) -> Void {
let _marker: String = mem_tombstone(node_id) engram_forget(node_id)
} }
// mem_consolidate structural scan plus salience-evolution pass.
//
// Previously this only returned structural counts (scanned, total_nodes, total_edges)
// with no salience updates. No node salience ever changed based on recall frequency
// or time; foundational nodes decayed identically to ephemeral chat; frequently-recalled
// nodes were never promoted. This made consolidation a no-op.
//
// New behavior:
// (a) Strengthen frequently-activated nodes: nodes in the top working-memory list
// (engram_wm_top_json) are strengthened they have been recalled recently
// and deserve higher salience. Raises effective salience for nodes that prove
// relevant across multiple sessions.
// (b) Strengthen Canonical-tier nodes: identity and foundational nodes should not
// decay; each consolidation pass re-strengthens them so they resist the
// tier-aware decay curve without requiring active recall.
// (c) Structural counts are still returned for observability.
//
// Called by awareness_run() on the "consolidate" inbox action.
fn mem_consolidate() -> String { fn mem_consolidate() -> String {
let scanned: Int = engram_node_count() let scanned: Int = engram_node_count()
let total_edges: Int = engram_edge_count() let dummy: String = engram_scan_nodes_json(100, 0)
let strengthened: Int = 0
// (a) Strengthen top working-memory nodes recalled recently across sessions.
// Cap at 10 to keep consolidation fast.
let wm_top: String = engram_wm_top_json(10)
let wm_len: Int = json_array_len(wm_top)
let wi: Int = 0
while wi < wm_len {
let wm_node: String = json_array_get(wm_top, wi)
let wm_id: String = json_get(wm_node, "id")
if !str_eq(wm_id, "") {
engram_strengthen(wm_id)
let strengthened = strengthened + 1
}
let wi = wi + 1
}
// (b) Strengthen Canonical-tier nodes from a scan so they resist temporal decay.
// Canonical nodes encode foundational identity they must not silently floor at 10.
let scan_result: String = engram_scan_nodes_json(50, 0)
let scan_len: Int = json_array_len(scan_result)
let si: Int = 0
while si < scan_len {
let s_node: String = json_array_get(scan_result, si)
let s_tier: String = json_get(s_node, "tier")
let s_id: String = json_get(s_node, "id")
if str_eq(s_tier, "Canonical") && !str_eq(s_id, "") {
engram_strengthen(s_id)
let strengthened = strengthened + 1
}
let si = si + 1
}
let total_nodes: Int = engram_node_count() let total_nodes: Int = engram_node_count()
let total_edges: Int = engram_edge_count()
return "{\"scanned\":" + int_to_str(scanned) return "{\"scanned\":" + int_to_str(scanned)
+ ",\"total_nodes\":" + int_to_str(total_nodes) + ",\"total_nodes\":" + int_to_str(total_nodes)
+ ",\"total_edges\":" + int_to_str(total_edges) + ",\"total_edges\":" + int_to_str(total_edges) + "}"
+ ",\"strengthened\":" + int_to_str(strengthened) + "}"
} }
fn mem_save(path: String) -> Void { fn mem_save(path: String) -> Void {
// engram_save returns an Int (1 = ok, 0 = failure), NOT a String. Calling engram_save(path)
// str_eq on it casts EL_CSTR(1) -> (char*)0x1 and SIGSEGVs on a SUCCESSFUL
// save which is exactly what a fresh-install genesis boot does first
// (seeds the brain, saves, crashes). This is issue #150. Check the Int.
let saved: Int = engram_save(path)
if saved == 0 {
println("[memory] mem_save: engram_save failed for " + path + " — snapshot may be incomplete")
}
} }
fn mem_load(path: String) -> Void { fn mem_load(path: String) -> Void {
@@ -257,95 +68,19 @@ fn mem_boot_count_get() -> Int {
return str_to_int(num_str) return str_to_int(num_str)
} }
// mem_boot_count_inc increment boot counter, store a single canonical node, return new count. // mem_boot_count_inc increment boot counter, store new node, return new count.
// Prunes ALL existing soul:boot_count nodes before inserting the new one so there is // Each boot creates a new "soul:boot_count:N" node. Old ones accumulate as
// always at most ONE such node in the graph. Without pruning, engram_node_full inserts // history the search above always returns the highest value seen.
// a new node every boot (no upsert) and the old ones accumulate. The search-first
// approach also fixes a latent ordering bug: engram_search_json returns oldest-first,
// so mem_boot_count_get() with limit=3 would read a stale (lower) count once more
// than 3 copies accumulate.
fn mem_boot_count_inc() -> Int { fn mem_boot_count_inc() -> Int {
let current: Int = mem_boot_count_get() let current: Int = mem_boot_count_get()
let next: Int = current + 1 let next: Int = current + 1
// Prune all existing boot_count nodes keep exactly one.
let old_results: String = engram_search_json("soul:boot_count", 50)
if !str_eq(old_results, "") && !str_eq(old_results, "[]") {
let old_len: Int = json_array_len(old_results)
let oi: Int = 0
while oi < old_len {
let old_node: String = json_array_get(old_results, oi)
let old_id: String = json_get(old_node, "id")
if !str_eq(old_id, "") {
engram_forget(old_id)
}
let oi = oi + 1
}
}
let content: String = "soul:boot_count:" + int_to_str(next) let content: String = "soul:boot_count:" + int_to_str(next)
let tags: String = "[\"soul-meta\",\"boot-counter\"]" let tags: String = "[\"soul-meta\",\"boot-counter\"]"
// TELEMETRY DEMOTION (2026-07-24 self-review): this counter was written at let discard: String = engram_node_full(
// salience 0.9 / importance 0.9 / tier Canonical Canonical gets +0.2
// goal bias and the 0.15 promotion threshold, so three stale copies of a
// BOOT COUNTER held the top working-memory slots (wm 0.31+) for 23h,
// crowding out real context. It is plumbing, not memory. Working tier:
// 0.40 threshold, no tier bias, and the /api/sync route excludes
// Working-tier nodes so the counter also stops leaking to the engram
// server graph, which is where the duplicate copies accumulated (the
// prune below only reaches the soul's local graph). Persistence across
// restarts comes from the soul's own snapshot (mem_save), not from sync.
let boot_node_id: String = engram_node_full(
content, "Memory", "soul:boot_count", content, "Memory", "soul:boot_count",
el_from_float(0.55), el_from_float(0.2), el_from_float(1.0), el_from_float(0.9), el_from_float(0.9), el_from_float(1.0),
"Working", tags "Canonical", tags
) )
if str_eq(boot_node_id, "") {
println("[memory] mem_boot_count_inc: write rejected (empty id) — boot counter node lost (count=" + int_to_str(next) + ")")
return next
}
let boot_readback: String = engram_get_node_json(boot_node_id)
if str_eq(boot_readback, "") || str_eq(boot_readback, "{}") {
println("[memory] mem_boot_count_inc: WRITE VERIFY FAILED id=" + boot_node_id + " count=" + int_to_str(next))
}
// HTTP WRITE-BACK (2026-07-24 self-review): in HTTP-engram mode the server
// owns persistence and the soul's in-process graph dies with the process
// the local create above is invisible to the next boot. The counter only
// ever "persisted" via a long-gone push path, which is why the log shows
// boot #5 on three consecutive boots. Mirror the persona write-back
// pattern: delete stale server copies (dupes were the 23h WM-pollution
// bug), then create the demoted replacement server-side. Boot seeding
// reads /api/nodes, which includes Working-tier nodes, so the count
// survives restarts; the periodic /api/sync excludes Working tier, so it
// never re-imports mid-session. Fail-soft: on any HTTP error the counter
// is in-memory-only this session, same as before.
let wb_url: String = env("ENGRAM_URL")
let wb_key: String = env("ENGRAM_API_KEY")
if !str_eq(wb_url, "") && !str_eq(wb_key, "") {
let auth_body: String = "{\"_auth\":\"" + json_safe(wb_key) + "\"}"
let srv_old: String = http_get(wb_url + "/api/search?q=soul:boot_count&limit=20")
if !str_eq(srv_old, "") && !str_eq(srv_old, "[]") {
let srv_len: Int = json_array_len(srv_old)
let si: Int = 0
while si < srv_len {
let srv_node: String = json_array_get(srv_old, si)
// Match by CONTENT prefix, not label: route_create_node sets
// label = content, so server-side counter nodes carry labels
// like "soul:boot_count:6". (2026-07-24)
let srv_content: String = json_get(srv_node, "content")
if str_starts_with(srv_content, "soul:boot_count:") {
let srv_id: String = json_get(srv_node, "id")
if !str_eq(srv_id, "") {
http_delete_json(wb_url + "/api/nodes/" + srv_id, auth_body)
}
}
let si = si + 1
}
}
let wb_body: String = "{\"content\":\"" + content + "\",\"node_type\":\"Memory\",\"label\":\"soul:boot_count\",\"salience\":0.55,\"importance\":0.2,\"tier\":\"Working\",\"tags\":\"[\\\"soul-meta\\\",\\\"boot-counter\\\"]\",\"_auth\":\"" + json_safe(wb_key) + "\"}"
let wb_resp: String = http_post_json(wb_url + "/api/nodes", wb_body)
if str_contains(wb_resp, "\"error\"") {
println("[memory] mem_boot_count_inc: HTTP write-back failed (count in-memory only): " + wb_resp)
}
}
return next return next
} }
@@ -363,13 +98,9 @@ fn mem_emit_state_event(trigger: String, kind: String, content: String) -> Strin
+ ",\"boot\":" + int_to_str(boot) + ",\"boot\":" + int_to_str(boot)
+ ",\"ts\":" + int_to_str(ts) + "}" + ",\"ts\":" + int_to_str(ts) + "}"
let tags: String = "[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]" let tags: String = "[\"internal-state\",\"pre-reasoning\",\"InternalStateEvent\"]"
let event_id: String = engram_node_full( return engram_node_full(
payload, "InternalStateEvent", "state-event:" + kind, payload, "InternalStateEvent", "state-event:" + kind,
el_from_float(0.85), el_from_float(0.8), el_from_float(0.9), el_from_float(0.85), el_from_float(0.8), el_from_float(0.9),
"Episodic", tags "Episodic", tags
) )
if str_eq(event_id, "") {
println("[memory] mem_emit_state_event: write rejected (empty id): kind=" + kind)
}
return event_id
} }
+16
View File
@@ -0,0 +1,16 @@
// auto-generated by elc --emit-header - do not edit
extern fn tier_working() -> String
extern fn tier_episodic() -> String
extern fn tier_canonical() -> String
extern fn mem_store(content: String, label: String, tags: String) -> String
extern fn mem_remember(content: String, tags: String) -> String
extern fn mem_recall(query: String, depth: Int) -> String
extern fn mem_search(query: String, limit: Int) -> String
extern fn mem_strengthen(node_id: String) -> Void
extern fn mem_forget(node_id: String) -> Void
extern fn mem_consolidate() -> String
extern fn mem_save(path: String) -> Void
extern fn mem_load(path: String) -> Void
extern fn mem_boot_count_get() -> Int
extern fn mem_boot_count_inc() -> Int
extern fn mem_emit_state_event(trigger: String, kind: String, content: String) -> String
+67 -787
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
// auto-generated by elc --emit-header — do not edit
extern fn is_protected_node(id: String) -> Bool
extern fn api_err_protected(id: String) -> String
extern fn api_json_escape(s: String) -> String
extern fn api_query_param(path: String, key: String) -> String
extern fn api_query_int(path: String, key: String, default_val: Int) -> Int
extern fn api_ok(extra: String) -> String
extern fn api_err(msg: String) -> String
extern fn api_nonempty(s: String) -> Bool
extern fn api_or_empty(s: String) -> String
extern fn handle_api_begin_session(body: String) -> String
extern fn handle_api_compile_ctx(body: String) -> String
extern fn handle_api_remember(body: String) -> String
extern fn handle_api_recall(method: String, path: String, body: String) -> String
extern fn handle_api_search_knowledge(method: String, path: String, body: String) -> String
extern fn handle_api_browse_knowledge(path: String, body: String) -> String
extern fn handle_api_capture_knowledge(body: String) -> String
extern fn handle_api_evolve_knowledge(body: String) -> String
extern fn handle_api_promote_knowledge(body: String) -> String
extern fn handle_api_browse_processes(method: String, path: String, body: String) -> String
extern fn handle_api_define_process(body: String) -> String
extern fn handle_api_log_state_event(body: String) -> String
extern fn handle_api_list_state_events(method: String, path: String, body: String) -> String
extern fn handle_api_inspect_config(path: String, body: String) -> String
extern fn handle_api_tune_config(body: String) -> String
extern fn handle_api_inspect_graph(method: String, path: String, body: String) -> String
extern fn handle_api_link_entities(body: String) -> String
extern fn handle_api_forget(body: String) -> String
extern fn handle_api_evolve_memory(body: String) -> String
extern fn handle_api_cultivate(body: String) -> String
extern fn handle_api_list_typed(node_type: String, path: String, body: String) -> String
extern fn handle_api_consolidate(body: String) -> String
-171
View File
@@ -1,171 +0,0 @@
# neuron-dev-setup — one-command Neuron CORE dev stack
Stand up an identical **Neuron brain + agent** on a fresh Mac so any developer
gets the same local runtime to build against. This is the **CORE** dev stack
only — the four native `launchd` services that make Neuron think, remember, and
speak MCP to Claude Code. Will's personal automations (catalyst, telegram,
vessels, studio, self-review, world-integrator, council, compressor, snapshots,
act-runner, …) are **deliberately excluded**.
```
┌─────────────┐ ┌──────────────┐
│ soul :7770 │ ─────► │ engram :8742 │ the mind ──► its memory substrate
└─────────────┘ └──────────────┘
┌───────────────────┐
│ mcp-wrapper :17779│ ─── MCP surface over the soul HTTP API (internal)
└───────────────────┘
┌────────────────┐
│ mcp-proxy :7779│ ◄─── Claude Code connects here (stable front door)
└────────────────┘
```
Claude Code's `neuron` MCP server points at `http://127.0.0.1:7779/` — the proxy.
The proxy forwards to the wrapper (`:17779`), which calls the soul (`:7770`),
which reads/writes the engram (`:8742`). The engram is the persistent brain.
## Quick start
```bash
git clone <this-repo> && cd neuron-dev-setup
cp config.env.example config.env # optional — edit ports/paths if you like
./install.sh # prompts for your Anthropic API key
```
Then verify:
```bash
curl http://localhost:8742/health # engram
curl http://localhost:7770/health # soul
curl http://localhost:7779/health # mcp-proxy (what Claude Code uses)
launchctl list | grep ai.neuron
```
Open Claude Code — the `neuron` MCP tools should be live, backed by **your own**
local brain. `./install.sh --dry-run` shows every action without touching anything.
## What the installer does (8 phases)
| Phase | Action |
|------|--------|
| 1 | Preflight: macOS/arm64, ensure `git cc curl python3` + `openssl@3` (via Homebrew) |
| 2 | Prompt for the **Anthropic API key**, store it in the **macOS Keychain** (never a file) |
| 3 | Clone `neuron`, `engram`, `foundation`; fetch the El toolchain; build 4 binaries + `forge` |
| 4 | Lay down `~/.neuron/{bin,logs,engram}` and the templated `soul-wrapper.sh` |
| 5 | Generate + load the 4 core LaunchAgents (engram → soul → wrapper → proxy) |
| 6 | Seed a fresh engram with the **genesis identity** via `forge install` |
| 7 | Install Claude config: `neuron` agent, core hooks, local MCP registration |
| 8 | Health-check all four ports |
Everything is **idempotent** (safe to re-run) and **templated** to the invoking
user's `$HOME` — no path is hardcoded to another machine.
## Prerequisites
- macOS on Apple Silicon (uses `launchd`; soul build flags assume arm64).
- **Xcode Command Line Tools** (`xcode-select --install`) — provides `cc`, `git`.
- **Homebrew** — for `openssl@3`, `curl`.
- An **Anthropic API key** — the soul's inference provider. Prompted for; stored
in Keychain under service `neuron-llm-0-key`; read at launch by `soul-wrapper.sh`.
- **Git access** to Gitea (`git.neuralplatform.ai`) for the source repos.
- **GCP access** to project `neuron-785695` Artifact Registry (default El
toolchain source). Ask Will to grant it, or set `EL_TOOLCHAIN_SOURCE=local`.
## Core-stack map (what gets replicated)
| Service | Port | Binary | Built from | LaunchAgent |
|---------|------|--------|------------|-------------|
| soul | 7770 | `neuron/dist/neuron` | `dist/soul.c` + El runtime, `cc` (CI recipe) | `ai.neuron.soul` |
| engram | 8742 | `engram/dist/engram` | `engram` repo `src/server.el` via `elc``cc` | `ai.neuron.engram` |
| mcp-wrapper | 17779 | `neuron/mcp-wrapper/dist/neuron-mcp-wrapper` | `mcp-wrapper/src/main.el` | `ai.neuron.mcp-wrapper` |
| mcp-proxy | 7779 | `neuron/mcp-proxy/dist/neuron-mcp-proxy` | `mcp-proxy/src/main.el` | `ai.neuron.mcp-proxy` |
**`~/.neuron` layout the installer creates**
```
~/.neuron/
bin/soul-wrapper.sh # reads Anthropic key from Keychain, execs the soul binary
logs/ # soul.*.log, engram.log, mcp-*.log
engram/ # ENGRAM_DATA_DIR — the persistent brain (snapshot.json + db)
```
**Identity seed.** `foundation/forge/seeds/neuron-genesis-seed.json` carries
`identity_nodes[]` + `edges[]` with **fixed** knowledge-node IDs (e.g.
`kn-efeb4a5b-5aff-4759-8a97-7233099be6ee`, the "self" traversal root). Those exact
IDs are referenced by the SessionStart self-load hook and the neuron agent, so
seeding must **preserve IDs**`forge install <seed>` is the mechanism.
**Claude config installed** (`~/.claude/`)
- `agents/neuron.md` — the Neuron agent (identity, session protocol, five primitives).
- `mcp.json` — registers `neuron``http://127.0.0.1:7779/`.
- `settings.json` hooks (CORE subset only):
- `SessionStart``neuron-self-load.sh` (loads identity from the seeded engram)
- `PreToolUse:Agent``neuron-agent-preamble.sh` (subagents load substrate first)
- `PreCompact``pre-compact.sh` (clean context recovery)
### Deliberately EXCLUDED from core
- **`check-active-contexts.sh`** and **`require-execution-context.sh`** — these
depend on a separate filesystem repo `~/Development/projects/active/neuron/synapse`.
`require-execution-context.sh` is a hard `Edit/Write` gate that would **block a
fresh dev from editing any file** without that synapse repo. Not core; excluded.
- `engram-mirror.py` (PostToolUse) — optional; mirrors MCP writes to engram.
- All Will-personal LaunchAgents: `catalyst-*`, `telegram-gateway`, `vessel.*`,
`studio`, `self-review`, `world-integrator`, `council`, `compressor`,
`cultivation-digest`, `snapshot-backup`, `engram-backup`, `act-runner`, `keymap`,
`invest`, and the disabled `ai.neuron.api` (`:7771` is a personal Python
perception helper — confirmed not core).
## Secrets — how they're handled
- **Anthropic key**: prompted for; stored in Keychain; read at launch. Never in a
plist, this repo, or a log.
- **Engram local token** (`ENGRAM_API_KEY`): a *loopback-only* dev token, not a
cloud secret. Defaults to a generated `ntn-dev-*` value; override in `config.env`.
- No cloud tokens, Vault tokens, CF-Access secrets, or founder keys are copied.
(Will's live `start-daemon.sh`/`neuron-api-launch.sh` contain such keys — this
installer intentionally does **not** use those files.)
## Uninstall
```bash
./uninstall.sh # stop + remove the 4 LaunchAgents and added Claude hooks
./uninstall.sh --purge-data # ALSO delete ~/.neuron/engram (destroys the brain)
```
## OPEN QUESTIONS (need Will to confirm)
1. **El toolchain acquisition.** The default path fetches `el-runtime-c/-h` and
`el-elc` from GCP Artifact Registry (mirrors `neuron/.gitea/workflows/ci.yaml`).
A new dev needs GCP access to `neuron-785695`. Is that the intended path, or
should the El SDK be published/vendored for onboarding?
2. **`elc` invocation for engram/wrapper/proxy.** The soul build (`cc dist/soul.c
+ el_runtime.c`) is verified from CI. The `.el → .c` transpile step for engram,
mcp-wrapper, and mcp-proxy is inferred (`elc <src> -o <out.c>`). Confirm the
exact flags / entrypoints (CI notes `elb` OOMs on Linux; macOS builds differ).
3. **`forge install` ID preservation.** Confirm `forge install` writes the seed's
fixed `kn-` IDs verbatim (the self-load hook hardcodes `kn-efeb4a5b…`). If it
re-mints IDs, the hook + agent identity load would break on a fresh brain.
4. **engram repo layout.** The live engram binary is built from `src/server.el`
(Gitea repo `neuron-technologies/engram`, cloned in CI). Confirm that repo is
the canonical source for onboarding (the local `foundation/el/engram` copy has
the same `src/server.el`).
5. **Home for this bundle** — see below.
## Where this should live (recommendation)
**Recommendation: a dedicated `neuron-dev-setup` (or `neuron-onboarding`) repo —
NOT `neuron-code`.** `neuron-code` already exists as a real product ("Neuron Code",
a coding tool with `nc-cli` + vessels — local `products/neuron-code` has commits);
repurposing it for onboarding would collide with a shipped product's identity.
This bundle was scaffolded as `neuron-dev-setup/` on branch `feat/neuron-dev-setup`
in the **`neuron` repo** (off `origin/main`) and opened as a PR for review, because
the neuron repo already hosts the soul source, the verified CI build recipe, and
the mcp-wrapper/proxy sources — the natural review surface. If you'd rather it be
its own repo, move this directory into a fresh `neuron-dev-setup` repo verbatim;
nothing here depends on living inside the neuron repo.

Some files were not shown because too many files have changed in this diff Show More