65dd2cf097
The architecture docs describe four things the design spec has since ruled out, and each one is a supervisor invented for something that should be a property of the substrate: grounding modelled as a subsystem rather than as the edge weight it already is; faculties modelled as parameters of a read when abduce is a write; wonder materialized as a maintained manifest when it is the boundary of the structure; and consolidation implemented eleven times behind tickers when a brain has no cron job. Left standing rather than deleted, per the repo's own supersession discipline — the trail of how the understanding matured is the point. Each stale passage is marked inline and points at a new 06 §12 that transcribes the corrections and records the measured consolidation inventory. Authority: foundation/el, branch design/correspondence-and-censorship, lang/spec/correspondence-and-censorship.md.
182 lines
13 KiB
Markdown
182 lines
13 KiB
Markdown
# 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.
|
|
> **Shape is known-wrong (2026-08-16) — see `docs/architecture/06-cognitive-architecture.md` §12.2.**
|
|
> `faculty=` as a keyword argument models a **faculty as a parameter**. Faculties
|
|
> are **operations**, distinguished by what they change: `reason` changes the
|
|
> estimate (a read), `induce` changes the parameters (this call — the
|
|
> correspondence-beat, which already exists and measurably works), `abduce`
|
|
> changes the structure (a write). **A write cannot be a parameter of a read**,
|
|
> and `engram_think()`'s output type has no field in which a structural change
|
|
> could be returned. `faculty="induce"` happens to be the one value that is
|
|
> honest here; treat the parameter itself as sequenced for removal, and do not
|
|
> add faculties to it. The surface residue is
|
|
> `mcp-wrapper/src/main.el:409`.
|
|
|
|
## 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.
|