Compare commits

..

5 Commits

Author SHA1 Message Date
will.anderson 9a3a248675 Merge pull request 'docs: record the correspondence corrections — grounding, faculties, wonder, consolidation' (#163) from docs/correspondence-and-ownership-2026-08-16 into main
Neuron Soul CI / build (push) Failing after 4m0s
Neuron Soul CI / deploy (push) Waiting to run
2026-08-16 20:49:28 +00:00
will.anderson 65dd2cf097 docs: record the correspondence corrections — grounding, faculties, wonder, consolidation
Neuron Soul CI / build (pull_request) Failing after 4m9s
Neuron Soul CI / deploy (pull_request) Has been skipped
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.
2026-08-16 13:31:27 -05:00
will.anderson 15364d0ac4 Merge pull request 'soul: the engram is the canonical store, not a fallback' (#162) from fix/engram-is-canonical into main
Neuron Soul CI / build (push) Failing after 12m31s
Neuron Soul CI / deploy (push) Failing after 14m31s
2026-08-16 02:16:56 +00:00
will.anderson b6ed9340bf soul: the engram is the canonical store, not a fallback
Neuron Soul CI / build (pull_request) Failing after 4m20s
Neuron Soul CI / deploy (pull_request) Has been skipped
The soul preferred its own local snapshot over the engram:

    // Always try local snapshot first ... HTTP Engram is only used for the
    // very first boot (empty/absent snapshot).

The copy outranked the store. Every one of these is a cost of that inversion,
and all of them were live tonight:

  - the graphs drifted: 31,795 nodes / 75,241 edges in the soul against
    13,439 / 37,670 in the engram — more than twice the edges, silently
  - write-through exists only to reconcile them, and had never once run
  - /api/graph/edges serialized 128 MB to answer a read, because the soul's
    copy was not the engram's
  - a read route overwrote the engram's canonical snapshot.json with the
    soul's divergent copy
  - three resident copies of one graph (soul, engram, Neuron.app) — about
    7.2 GB of RAM for a store that is 2.2 GB on disk, which is what pushed the
    host into swap

None of those are features. They are reconciliation debt from one decision.

The engram had already reached this conclusion for its own boot path — "the
durable owner is the paged store (neuron.egm + neuron.wal) ... snapshot.json is
never read again as the ongoing store. This closes the 'restart reverted to a
17h-old snapshot' data-loss window." The soul kept booting the legacy way the
engram had abandoned, and inherited exactly that data-loss window.

So in HTTP-engram mode the soul now seeds from the engram on EVERY boot and
never reads a local snapshot, present or not — a stale copy that outranks the
store is the bug, not a fallback. It already never wrote one in this mode
(gated behind is_genesis && safe_to_seed, and safe_to_seed requires
!using_http_engram), so this supplies the missing half.

It also refuses to boot on an empty seed rather than silently rebuilding a
divergent graph from nothing. launchd KeepAlive with ThrottleInterval=10 turns
that into a retry every 10s until the engram is up — self-healing, no spin.

File mode (no ENGRAM_URL) is untouched: there the soul genuinely is the owner.

Verified before deploy: with a deliberately empty local snapshot planted, the
soul booted in ~30s reporting 13,446 nodes / 37,675 edges — the engram's
contents, not the empty local file.
2026-08-15 21:16:22 -05:00
will.anderson 97bf91739e Merge pull request 'fix(routes): /api/graph/edges must not write the canonical snapshot' (#161) from fix/graph-edges-no-canonical-clobber into main
Neuron Soul CI / build (push) Failing after 14m2s
Neuron Soul CI / deploy (push) Has been skipped
2026-08-16 01:44:57 +00:00
13 changed files with 709 additions and 28 deletions
+11
View File
@@ -50,6 +50,17 @@ At the start of every session:
- Refine: `supersede(id=..., action="evolve"|"tombstone"|"promote", ...)` for - Refine: `supersede(id=..., action="evolve"|"tombstone"|"promote", ...)` for
completions and lessons-learned; `learn(seeds=..., faculty="induce")` to recalibrate completions and lessons-learned; `learn(seeds=..., faculty="induce")` to recalibrate
the steering-prior, not as a session-notes dump. 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 ## Architecture style — VBD, no exceptions
+40 -1
View File
@@ -1,5 +1,43 @@
# Neuron Council Service # Neuron Council Service
> ## ⚠ Architecturally superseded — 2026-08-16
>
> **This service is wrong in two independent ways at once.** Authority:
> `foundation/el/lang/spec/correspondence-and-censorship.md` (branch `design/correspondence-and-censorship`),
> transcribed in `docs/architecture/06-cognitive-architecture.md` §12.4 and §12.5. The service is **still
> running** (`ai.neuron.council`, `KeepAlive`, resident, port 7771) and this README still describes it
> accurately; what is superseded is the claim that it should exist.
>
> **1. It is a write-refusal mechanism in an immutable substrate.**
>
> > In an immutable substrate, any mechanism that refuses a write is either redundant with immutability, or an
> > epistemic constraint misfiled as a protective one.
>
> "Before a claim enters long-term memory" is a **gate on entry**, and the storage policy below goes further:
> *"`council-flagged` → store in a quarantine bucket **or reject entirely**"* (`:54`), with a C sketch that
> returns `MEMORY_REJECTED` (`:95`). The engram does not mutate and nothing is ever hard-deleted, so a claim
> admitted and later refuted is **richer** than a claim never admitted: the refutation is recordable as
> **signed edge weight** (negative = *this actively contradicts*, distinct from near-zero = *no support*).
> Rejection destroys that distinction and makes the belief's truth value permanently unknowable — you cannot
> discover you were wrong, and you equally cannot discover you were right.
> **Holding is unconditional; the honesty floor governs assertion, not entry.**
>
> **2. It is a scheduled/resident consolidation service, in Python, outside el.**
>
> It is one of **eleven** measured consolidation implementations (`06` §12.4), and one of **three** that run in
> Python outside el — so this part of Neuron's consolidation does not run on his own substrate and **cannot
> touch the geometry at all**. Judging a claim without reaching the geometry means judging it on something
> other than its grounding.
>
> **3. What it actually measures is not grounding.** Three LLMs voting on plausibility computes **conformity to
> the centre of the training distribution** — treating *common* as true and *rare* as suspect. **Truth is
> orthogonal to frequency.** Grounding is correspondence with the world, and in this substrate it is the
> weight of the edge; it is never a vote and never a score computed on demand. See `06` §11 ("What an LLM calls
> grounding…") and §12.1.
>
> **Do not wire the `.el` pre-storage hook sketched below** (`:57-83`). It adds a gate on entry to a store
> whose whole discipline is that entry is not gated.
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. 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 ## Running the service
@@ -51,7 +89,8 @@ Returns `{"status": "ok"}` when the service is up.
Recommended storage policy: Recommended storage policy:
- `confidence >= 0.65` → store normally - `confidence >= 0.65` → store normally
- `0.30 <= confidence < 0.65` → store with `council-split` tag for later review - `0.30 <= confidence < 0.65` → store with `council-split` tag for later review
- `council-flagged` → store in a quarantine bucket or reject entirely - ~~`council-flagged` → store in a quarantine bucket or reject entirely~~ — **withdrawn 2026-08-16; see the
banner at the top of this file. Never reject. Store it, and record the disagreement as signed weight.**
- `council-unavailable` → store normally (fail-open); council will re-evaluate later - `council-unavailable` → store normally (fail-open); council will re-evaluate later
## How to call from soul (.el) ## How to call from soul (.el)
+12 -1
View File
@@ -104,7 +104,7 @@ The full VBD classification is in `01-vbd-decomposition.md`. In one glance:
| Cognitive API | `neuron-api.el` | Managers + Engines — session/memory/knowledge/graph/cultivation handlers | | Cognitive API | `neuron-api.el` | Managers + Engines — session/memory/knowledge/graph/cultivation handlers |
| Request pipeline | `soul.el` `layered_cycle` | Manager — L1 safety → L2 stewardship → L3 imprint | | Request pipeline | `soul.el` `layered_cycle` | Manager — L1 safety → L2 stewardship → L3 imprint |
| Boot + identity | `soul.el` | Manager — compose layers, seed identity graph, start server + daemon | | Boot + identity | `soul.el` | Manager — compose layers, seed identity graph, start server + daemon |
| Autonomous cognition | `awareness.el` | Manager (`awareness_run`) + Engines (curiosity, attend, threat) | | Autonomous cognition | `awareness.el` | Manager (`awareness_run`) + Engines (~~curiosity~~ †, attend, threat) |
| Memory access | `memory.el` | Resource Accessor over the engram FFI/HTTP | | Memory access | `memory.el` | Resource Accessor over the engram FFI/HTTP |
| Store | `engram/server.el` + `el_runtime.c` | Accessor (HTTP) over the real graph engine | | Store | `engram/server.el` + `el_runtime.c` | Accessor (HTTP) over the real graph engine |
| Request-layer rules | `safety.el`, `stewardship.el`, `imprint.el` | Engines | | Request-layer rules | `safety.el`, `stewardship.el`, `imprint.el` | Engines |
@@ -112,6 +112,17 @@ The full VBD classification is in `01-vbd-decomposition.md`. In one glance:
| MCP transport | `mcp-proxy`, `mcp-wrapper` | Managers/Accessors — protocol boundary | | MCP transport | `mcp-proxy`, `mcp-wrapper` | Managers/Accessors — protocol boundary |
| Build | `manifest.el`, `dist/soul.c`, El toolchain | amalgamation → `soul.c` → binary | | Build | `manifest.el`, `dist/soul.c`, El toolchain | amalgamation → `soul.c` → binary |
> **† Superseded (2026-08-16) — see `06-cognitive-architecture.md` §12.3.**
> Curiosity is **not a peer Engine** beside `attend` and `threat`. It is not a
> component at all: **curiosity is wonder crystallized at a nucleation site** —
> one thing at two phases, where wonder is the field (unbounded, objectless,
> invariant, present wherever there is structure) and curiosity is the
> precipitate (localized, with an object, able to direct activation). What it
> seeds is the **same** activation process `attend` runs; there is one activation
> process with two seed sources — external (a request) and internal (a
> curiosity) — not two processes negotiating for a resource. Modelling it as a
> peer Engine is what produced the timed `proactive_curiosity` scan documented in
> `02-components.md §3b`.
## Reading guide ## Reading guide
+13 -1
View File
@@ -45,6 +45,18 @@ rotation, novelty gating, and the inbox verb-mapping in `attend()`. The
(comments spanning 2026-05 → 2026-08). This is where the *behavior* of the (comments spanning 2026-05 → 2026-08). This is where the *behavior* of the
agent is tuned. agent is tuned.
> **Superseded (2026-08-16) — see `06-cognitive-architecture.md` §12.3.**
> The volatility this Engine encapsulates is **real churn around a wrong model**.
> "Seed-domain selection" and "curiosity rotation" are a maintained manifest of
> things to be curious about; a nucleation site is a **per-edge structural fact**
> (`|discord|` = `|z(semantic proximity) z(association strength)|`, `06` §12.4),
> not an entry in a rotation. The deep git-archaeology cited here is itself
> evidence: an Engine that has been re-tuned continuously since 2026-05 is
> encapsulating volatility that the substrate should have made constant.
> **Curiosity does not search for nucleation sites; it goes where salience
> already is** — machinery that already exists (`salience`,
> `background_activation`, `working_memory_weight`, `wm_anchor`).
### 3. Epistemic & memory semantics ### 3. Epistemic & memory semantics
Tiers, salience mapping, promotion/consolidation, the immutability policy Tiers, salience mapping, promotion/consolidation, the immutability policy
(tombstone/supersede), and knowledge disposition. These evolve as the memory (tombstone/supersede), and knowledge disposition. These evolve as the memory
@@ -89,7 +101,7 @@ placement. Paths are repo-relative unless noted `foundation/…`.
|---|---|---| |---|---|---|
| `api_compact_*`, `begin_session`, `compile_ctx` | `neuron-api.el:90-317` | Axis 1 — context/payload shaping. The single most-reworked logic on the API side. | | `api_compact_*`, `begin_session`, `compile_ctx` | `neuron-api.el:90-317` | Axis 1 — context/payload shaping. The single most-reworked logic on the API side. |
| `attend()` | `awareness.el:926-973` | Axis 2 — inbox content → action-verb ruleset. | | `attend()` | `awareness.el:926-973` | Axis 2 — inbox content → action-verb ruleset. |
| `proactive_curiosity`, `auto_term_try_slot` | `awareness.el:590-876` | Axis 2 — seed selection, stopword/IDF gates, tabu ring. Textbook Engine: highest churn. | | `proactive_curiosity`, `auto_term_try_slot` | `awareness.el:590-876` | Axis 2 — seed selection, stopword/IDF gates, tabu ring. Textbook Engine: highest churn. **Superseded (2026-08-16): curiosity is not an Engine — see Axis 2 above and `06` §12.3.** |
| threat scoring | `awareness.el:1286-1419` | Axis 4 — additive command/path/history threat rules. | | threat scoring | `awareness.el:1286-1419` | Axis 4 — additive command/path/history threat rules. |
| `safety.el` (crisis/harm/bell) | `safety.el` | Axis 4 — crisis screening, bell thresholds, output validation. | | `safety.el` (crisis/harm/bell) | `safety.el` | Axis 4 — crisis screening, bell thresholds, output validation. |
| `stewardship.el` | `stewardship.el` | Axis 4 — mission alignment, CGI check, continuity fingerprint. | | `stewardship.el` | `stewardship.el` | Axis 4 — mission alignment, CGI check, continuity fingerprint. |
+43 -2
View File
@@ -45,7 +45,7 @@ raw `/api/graph*` reads.
| Graph/activation | `/api/neuron/graph`, `/graph/link`, `/api/graph*`, `/list/:type` | neuron-api + engram builtins | | Graph/activation | `/api/neuron/graph`, `/graph/link`, `/api/graph*`, `/list/:type` | neuron-api + engram builtins |
| Cultivation/self | `/api/neuron/cultivate`, `/lineage`, `/imprint/*`, `/synthesize` | neuron-api, routes.el | | Cultivation/self | `/api/neuron/cultivate`, `/lineage`, `/imprint/*`, `/synthesize` | neuron-api, routes.el |
| Processes/config | `/api/neuron/processes{,/define}`, `/config{,/tune}` | neuron-api | | Processes/config | `/api/neuron/processes{,/define}`, `/config{,/tune}` | neuron-api |
| State/consolidate | `/api/neuron/state-events`, `/consolidate` | neuron-api | | State/consolidate | `/api/neuron/state-events`, `/consolidate` | neuron-api*one of eleven consolidation implementations; see `06` §12.4* |
| Backlog/artifacts | `/api/backlog`, `/artifacts`, `/projects`, `/memories` | Axon (HTTP) | | Backlog/artifacts | `/api/backlog`, `/artifacts`, `/projects`, `/memories` | Axon (HTTP) |
| Chat/NLG | `/api/chat`, `/see`, `/elp/chat`, `/dharma*`, `/nlg*` | chat.el, elp-input.el | | Chat/NLG | `/api/chat`, `/see`, `/elp/chat`, `/dharma*`, `/nlg*` | chat.el, elp-input.el |
| Health/UI | `/health`, `/lineage`, `/` | routes.el, studio.el | | Health/UI | `/health`, `/lineage`, `/` | routes.el, studio.el |
@@ -112,6 +112,13 @@ tombstoning.
identity-write path, gated by convention to Will's explicit cultivation identity-write path, gated by convention to Will's explicit cultivation
sessions. sessions.
> **Consolidation has no owner (2026-08-16) — see `06` §12.4.** `/consolidate`
> below and `mem_consolidate` in the table further down are two of **eleven**
> measured consolidation implementations, spread across three languages and two
> processes. Consolidation had no owner, so it was implemented at every site that
> needed a piece of it. Every name in the set is a consolidation verb — compress,
> cultivate, digest, integrate, review, reify, beat.
- **Config / processes / state-events / consolidate** — config anchors + a - **Config / processes / state-events / consolidate** — config anchors + a
`ConfigEntry` node search (`:616-639`), `tune_config` (`:642-653`), `ConfigEntry` node search (`:616-639`), `tune_config` (`:642-653`),
`browse_processes` / `define_process` (`:547-568`), state-event log/list `browse_processes` / `define_process` (`:547-568`), state-event log/list
@@ -155,7 +162,7 @@ The single isolation point over the engram FFI. Key functions:
| `mem_strengthen` | `42-44` | `engram_strengthen` | salience bump | | `mem_strengthen` | `42-44` | `engram_strengthen` | salience bump |
| `mem_tombstone` | `52-62` | `engram_node_full` + `engram_connect` | the one canonical soft-delete | | `mem_tombstone` | `52-62` | `engram_node_full` + `engram_connect` | the one canonical soft-delete |
| `mem_forget` | `70-72` | `mem_tombstone` | soft delete (no longer hard) | | `mem_forget` | `70-72` | `mem_tombstone` | soft delete (no longer hard) |
| `mem_consolidate` | `92-133` | `engram_wm_top_json`, `engram_strengthen` | salience-evolution pass | | `mem_consolidate` | `92-133` | `engram_wm_top_json`, `engram_strengthen` | salience-evolution pass*one of eleven consolidation implementations, `06` §12.4* |
| `mem_save` / `mem_load` | `135-148` | `engram_save/load` | snapshot I/O | | `mem_save` / `mem_load` | `135-148` | `engram_save/load` | snapshot I/O |
Note the distinction between **recall and search**: `mem_recall` fires spreading Note the distinction between **recall and search**: `mem_recall` fires spreading
@@ -166,6 +173,22 @@ and to the MCP surface vocabulary.
### 3b. Autonomous cognition — `awareness.el` (the daemon) ### 3b. Autonomous cognition — `awareness.el` (the daemon)
> **Corrected (2026-08-16) — see `06-cognitive-architecture.md` §12.4.**
> `awareness_run()`'s **continuous, in-process loop is the one fragment of
> consolidation with the correct shape.** It is not a scheduled job; it runs while
> the process serves. Everything below that is described as *"every 60s" /
> "every 30s" / "every 10 min"* is an interval inside that loop, and the design
> spec's verdict is that intrinsic rhythm — not an external clock — is what these
> should be. Consolidation is **ambient, not scheduled: a brain has no cron job**,
> and **the presence of a ticker is the diagnostic.** The genuinely external
> tickers are catalogued in `06` §12.4; this loop is the shape they fold *into*.
>
> **Stale line numbers (verified 2026-08-16):** `awareness_run()` is defined at
> `awareness.el:1221` (its `while true` at `:1252`), not `:1097-1284`; it is
> launched from `soul.el:731`, not `soul.el:627`. `SOUL_TICK_MS` is read at
> `awareness.el:1228` (default **200 ms**) and `SOUL_HEARTBEAT_MS` at `:1248`
> (default **60000 ms**) — those two defaults are correct as documented.
`awareness.el` is the **idle-cognition daemon plus observability**, not `awareness.el` is the **idle-cognition daemon plus observability**, not
emotional-state code. `awareness_run()` (`:1097-1284`) is the master loop, emotional-state code. `awareness_run()` (`:1097-1284`) is the master loop,
launched last from `soul.el:627`. Each tick (`SOUL_TICK_MS`, ~200ms): launched last from `soul.el:627`. Each tick (`SOUL_TICK_MS`, ~200ms):
@@ -184,8 +207,26 @@ launched last from `soul.el:627`. Each tick (`SOUL_TICK_MS`, ~200ms):
top result **only if it changed** (novelty-gated), and derives an top result **only if it changed** (novelty-gated), and derives an
autobiographical seed from the top-10 working-memory nodes with autobiographical seed from the top-10 working-memory nodes with
stopword/IDF/tabu filtering. stopword/IDF/tabu filtering.
> **Superseded (2026-08-16) — see `06` §12.3.** Three errors in one name.
> (a) **Curiosity is not a scan.** Nothing in a mind sweeps its neighbourhoods
> to find what is surprising — the surprise captures attention; salience is
> bottom-up. A search asks *"which of these is odd"*; a mind has
> *"something is odd **here**"* for free. A sweep over regions is a supervisor.
> (b) **It is not on a timer.** "Every 30s when idle" is an external clock
> standing in for a drive. Low activation is aversive and the system
> self-activates; there is **one activation process with two seed sources** —
> external (a request) and internal (a curiosity) — not a scheduled scan
> competing for spare capacity.
> (c) **Rotating 4 seed-domain sets is a manifest.** Curiosity is wonder
> crystallized at a nucleation site, and a nucleation site is a per-edge
> structural fact (`|discord|`, `06` §12.4), not an entry in a rotation.
4. **Engram sync** (every 10 min): `GET /api/sync``engram_load_merge` 4. **Engram sync** (every 10 min): `GET /api/sync``engram_load_merge`
telemetry prune. telemetry prune.
> **Ticker, but not consolidation (2026-08-16).** Sync is store coherence
> between the two-store topology (`06` §2.3), not dreaming. Distinguished
> here because `06` §12.4 sweeps for tickers. **Not** to be confused with the
> separate `ai.neuron.engram-tick` launch agent (`StartInterval = 600`), which
> pokes `POST /api/tick` and **is** consolidation driven by an external clock.
Two functions carry most of the file's weight and volatility: Two functions carry most of the file's weight and volatility:
- **`hebb_consolidate()`** (`:64-99`) — the durable-learning write-back. It drains - **`hebb_consolidate()`** (`:64-99`) — the durable-learning write-back. It drains
+47 -1
View File
@@ -149,6 +149,35 @@ read — unverified/TODO.)*
## Write-protection ## Write-protection
> **Superseded (2026-08-16) — see `06-cognitive-architecture.md` §12.5.**
> Authority: `foundation/el/lang/spec/correspondence-and-censorship.md` §6 (branch
> `design/correspondence-and-censorship`).
>
> > **In an immutable substrate, any mechanism that refuses a write is either
> > redundant with immutability, or an epistemic constraint misfiled as a
> > protective one.**
>
> The requirement this gate was built for was never stated. It is
> **non-circularity of the reference frame** — a reference fitted to its own
> readings reports perfect correspondence forever while drift becomes
> undetectable from inside. That requirement is satisfied by *when* (the frame
> updates while activation is internally seeded, not while it is being used to
> act), not by *what*, so **the gate becomes unnecessary rather than removed, and
> nothing takes its place.** Corruption requires mutation, and the engram does not
> mutate: recoverability, governance, evidence quality, and rate are already
> properties of the substrate. Only **authorization** is residue, and it is
> bounded — an unauthorized writer can *propose*, never erase.
>
> **This section contradicts itself.** Thirty-five lines below, under
> *Immutability*, this same document states the conclusion in its own words:
> *"nothing it does is ever destructive — the safety is **after** the act, not a
> gate before it"* (`:185-187`). The 403 gate documented here **is** the
> before-the-act gate that sentence says is unnecessary. The design spec §6 names
> exactly this redundancy.
>
> The mechanism below is **still LIVE in code** and is described accurately; what
> is superseded is the claim that it is needed.
`is_protected_node(id)` (`neuron-api.el:20-37`) is a **hard-coded allowlist of 15 `is_protected_node(id)` (`neuron-api.el:20-37`) is a **hard-coded allowlist of 15
identity/value node IDs** — the self root, the values hub, intellectual-dna, identity/value node IDs** — the self root, the values hub, intellectual-dna,
memory-philosophy, voice, and the 8 value nodes. Handlers that could mutate the memory-philosophy, voice, and the 8 value nodes. Handlers that could mutate the
@@ -158,10 +187,16 @@ graph (tombstone / supersede / evolve / connect) check it and return HTTP 403
(`handle_api_link_entities`). (`handle_api_link_entities`).
**The one sanctioned override** is `POST /api/neuron/cultivate` **The one sanctioned override** is `POST /api/neuron/cultivate`
(`neuron-api.el:781-816`) — it performs the same ops with the protection check (`handle_api_cultivate`, `neuron-api.el:960` — **the `:781-816` cited here is
stale; verified 2026-08-16**) — it performs the same ops with the protection check
skipped, gated by convention to Will's explicit cultivation sessions. The self skipped, gated by convention to Will's explicit cultivation sessions. The self
layer is writable, but only through a deliberate door. layer is writable, but only through a deliberate door.
> **Superseded (2026-08-16).** A door built for a wall that need not stand. Per
> §12.5 of `06`, the gate above is redundant with immutability, so the override
> for it is redundant too. Neither is deleted here — this is a documentation
> branch; the change is sequenced in `correspondence-and-censorship.md` §11.
## Immutability — tombstone, never delete ## Immutability — tombstone, never delete
Engram nodes are immutable (`memory.el:64-69`). The model is: Engram nodes are immutable (`memory.el:64-69`). The model is:
@@ -215,6 +250,17 @@ Engram nodes are immutable (`memory.el:64-69`). The model is:
- **Off-cluster backup:** a Kubernetes CronJob (`engram-backup`) tars `/data` - **Off-cluster backup:** a Kubernetes CronJob (`engram-backup`) tars `/data`
every 15 minutes to `gs://neuron-db-backup/gke/neuron-prod/` and keeps the last every 15 minutes to `gs://neuron-db-backup/gke/neuron-prod/` and keeps the last
96 (24h) (`infrastructure/platform/k8s/neuron-mcp/backup-cronjob.yaml`). 96 (24h) (`infrastructure/platform/k8s/neuron-mcp/backup-cronjob.yaml`).
> **Ticker, but not consolidation (2026-08-16).** Flagged because
> `06` §12.4's sequencing item is *"no tickers, no cron"* and an auditor
> sweeping for tickers will land here. This one is **ops/backup, not
> cognition** — it does not consolidate and must not be folded into the
> dreamer. Its local counterpart is the `ai.neuron.engram-backup` launch agent
> (`StartInterval = 3600`, measured 2026-08-16); a separate
> `ai.neuron.snapshot-backup` runs at `StartInterval = 900`. Note the
> **discrepancy**: this doc says the backup interval is 15 min, which matches
> `snapshot-backup` (900 s) rather than the local `engram-backup` (3600 s).
> The cluster manifest was not read on this branch — treat the 15-min figure as
> unverified here.
- **Retention:** InternalStateEvent telemetry pruned at 48h - **Retention:** InternalStateEvent telemetry pruned at 48h
(`ENGRAM_ISE_RETENTION_MS`, `server.el:485-499`). (`ENGRAM_ISE_RETENTION_MS`, `server.el:485-499`).
@@ -113,6 +113,15 @@ namespace **`neuron-prod`**. Two Deployments, `neuron-mcp-blue` and
`kubectl` for the live swap, then git-update the Argo manifests so a sync `kubectl` for the live swap, then git-update the Argo manifests so a sync
doesn't revert replica counts. doesn't revert replica counts.
- **Backup** (`backup-cronjob.yaml`): every 15 min, tar `/data` → GCS, keep 96. - **Backup** (`backup-cronjob.yaml`): every 15 min, tar `/data` → GCS, keep 96.
> **Ticker, but not consolidation (2026-08-16).** Flagged only because `06`
> §12.4 sequences *"no tickers, no cron"* and an auditor sweeping for them will
> land here. This is **ops/backup, not cognition** — it does not consolidate and
> must not be folded into the dreamer. Local counterparts measured 2026-08-16:
> `ai.neuron.engram-backup` (`StartInterval = 3600`),
> `ai.neuron.snapshot-backup` (`StartInterval = 900`),
> `ai.neuron.act-runner-watchdog` (`StartInterval = 120`). Also measured:
> `crontab -l` contains **zero** neuron entries — every neuron schedule on this
> machine is launchd `StartInterval` / `StartCalendarInterval`, not cron.
### Resource sizing (learned the hard way) ### Resource sizing (learned the hard way)
+398 -8
View File
@@ -11,6 +11,21 @@
> running soul), **DESIGNED** (architecture decided, not yet built). Where the live state is more subtle > running soul), **DESIGNED** (architecture decided, not yet built). Where the live state is more subtle
> than a single word, the subtlety is stated rather than smoothed. No fabricated numbers. > than a single word, the subtlety is stated rather than smoothed. No fabricated numbers.
> ## ⚠ Superseded in part — 2026-08-16
>
> **Read §12 before §§611.** The design spec `foundation/el/lang/spec/correspondence-and-censorship.md`
> (branch `design/correspondence-and-censorship`) supersedes this document on **grounding**, **the faculties**,
> **wonder / curiosity**, and **consolidation**. The affected passages below are marked inline; each marker
> points at the §12 entry that replaces it. The passages are **left standing rather than deleted** — per §3.4,
> supersession is residue: the trail of how the understanding matured is kept, because sometimes the truth was
> in the old idea even when the old idea was not itself the truth.
>
> The four corrections in one line each:
> 1. **Grounding is not a subsystem — it *is* the edge weight.** One quantity, not two fields.
> 2. **Faculties are operations, not parameters.** A write cannot be a parameter of a read.
> 3. **Wonder is the boundary, not a manifest.** Curiosity is wonder crystallized — one thing at two phases.
> 4. **Consolidation is ambient, not scheduled. A brain has no cron job.** The presence of a ticker is the diagnostic.
--- ---
## 0. Reading order & cross-references ## 0. Reading order & cross-references
@@ -266,6 +281,14 @@ read-only rail.
### 4.1 Autonomous, superseding self-reification (DESIGNED / BUILDING — validating on a secondary soul, 2026-08-14) ### 4.1 Autonomous, superseding self-reification (DESIGNED / BUILDING — validating on a secondary soul, 2026-08-14)
> **Corrected (2026-08-16) — see §12.4.** The direction of this section is right and the design spec agrees
> with it: reification is an operation *of* the engram, not a call made *to* it. But "**on the heartbeat**"
> is still a ticker. Consolidation is **ambient, not scheduled** — a brain has no cron job. The measured
> reality is that reification is currently reachable by *four* external pokes (`POST /api/reify`,
> `POST /api/self-reify-beat`, `POST /api/tick` which folds self-reify in at
> `foundation/el/engram/src/server.el:646`, and `POST /api/correspondence-beat`), each of which puts a
> supervisor **outside** the mind deciding when it consolidates. See the inventory in §12.4.
Reification today runs as an explicit pass (`POST /api/reify`). The designed end-state is that **reification is Reification today runs as an explicit pass (`POST /api/reify`). The designed end-state is that **reification is
an operation *of* the engram, not a call made *to* it** — a continuous, autonomous process on the heartbeat, an operation *of* the engram, not a call made *to* it** — a continuous, autonomous process on the heartbeat,
next to Hebbian edge-formation (§3.3) and consolidation (§6.3), that clusters, names, nests, and promotes its next to Hebbian edge-formation (§3.3) and consolidation (§6.3), that clusters, names, nests, and promotes its
@@ -352,6 +375,10 @@ The operator family (§6.1) and reasoning (§6.4) are instances of this frame.
### 6.1 The operator family (mixed: LIVE / STAGED / DESIGNED) ### 6.1 The operator family (mixed: LIVE / STAGED / DESIGNED)
> **Superseded in part (2026-08-16) — see §12.2.** This table treats every faculty as one kind of thing.
> They are not. **`reason` changes the estimate (a read); `induce` changes the parameters; `abduce` changes
> the structure (a write).** The `wonder` row is superseded outright (§12.3).
Activate several reified neighborhoods into working memory, then apply faculty-named operators over their Activate several reified neighborhoods into working memory, then apply faculty-named operators over their
held geometry. The honest per-operator status (endpoint reference has the contracts): held geometry. The honest per-operator status (endpoint reference has the contracts):
@@ -363,7 +390,7 @@ held geometry. The honest per-operator status (endpoint reference has the contra
| **discern / distinguish** | `engram_geo_subtract` — orthogonal residual (`?mode=setdiff\|orthogonal`) | **STAGED** | | **discern / distinguish** | `engram_geo_subtract` — orthogonal residual (`?mode=setdiff\|orthogonal`) | **STAGED** |
| **gauge-distance** | `engram_geo_distance` — centroid + Wasserstein-2 | **STAGED** | | **gauge-distance** | `engram_geo_distance` — centroid + Wasserstein-2 | **STAGED** |
| **liken** | Procrustes / frame-align rotation (reason by analogy) | **DESIGNED** | | **liken** | Procrustes / frame-align rotation (reason by analogy) | **DESIGNED** |
| **wonder** | novelty × pull × unresolved structure | subsystem **LIVE** internally (wonder-questions, pull-weight, discharge); no HTTP operator endpoint | | ~~**wonder**~~ | ~~novelty × pull × unresolved structure~~ | ~~subsystem **LIVE** internally (wonder-questions, pull-weight, discharge); no HTTP operator endpoint~~**SUPERSEDED, see §12.3.** Wonder is not an operator and not a subsystem; it is the boundary of the structure. The "wonder-questions / pull-weight / discharge" machinery described here is the **wonder-manifest** the design spec identifies as residue. It is still live in code (`mcp-wrapper/src/main.el:516-519`, served in the tool list at `:422`; `neuron-api.el:1436, 1447-1456`) and is sequenced for removal. |
| **appreciate** | positive projection onto the self's value-manifold | **DESIGNED** | | **appreciate** | positive projection onto the self's value-manifold | **DESIGNED** |
| **avert** | negative projection (recoil) | **DESIGNED** | | **avert** | negative projection (recoil) | **DESIGNED** |
| **taste** | boundary contour of the appreciated region | **DESIGNED** | | **taste** | boundary contour of the appreciated region | **DESIGNED** |
@@ -415,11 +442,19 @@ verified: chronoception cooling is scale-invariant (identical total cooling acro
elapsed wall-clock), drift decomposition separates peripheral extension (growth) from core displacement elapsed wall-clock), drift decomposition separates peripheral extension (growth) from core displacement
(corruption), and `GET /api/drift` returns real geometry on the live soul when queried (probed 2026-08-13: (corruption), and `GET /api/drift` returns real geometry on the live soul when queried (probed 2026-08-13:
`{"centroid_sep":0.42,"core_disp":0.58,"anchor_members":83,"now_members":24,…}`). `POST /api/tick` / `{"centroid_sep":0.42,"core_disp":0.58,"anchor_members":83,"now_members":24,…}`). `POST /api/tick` /
`/api/self_anchor` exist but are flag-gated. The **harmful post-merge checkpoint** (§2.2) originated here — the `/api/self_anchor` exist but are flag-gated. **`POST /api/tick` is a ticker12.4):** it is poked from outside
on `StartInterval = 600` by the `ai.neuron.engram-tick` launch agent, and it folds self-reification in
(`foundation/el/engram/src/server.el:646`), so an external clock is currently deciding when the mind
consolidates. The **harmful post-merge checkpoint** (§2.2) originated here — the
per-beat tick-checkpoint was stripped. per-beat tick-checkpoint was stripped.
### 6.4 Reasoning + the verifier (STAGED — proven on scratch, cut flag-gated) ### 6.4 Reasoning + the verifier (STAGED — proven on scratch, cut flag-gated)
> **Superseded in part (2026-08-16) — see §12.1.** "Grounding" is described below as a **verifier tier** that
> answers a question on demand. It is not a tier and it is not computed on demand: **grounding is the edge
> weight.** An operation may *read* the grounding of a path; computing-and-writing a score makes reads write.
> The consistency/polarity half of this section is unaffected.
Reasoning is **geometry-native**: composable operator chains *propose*, and a **verifier** *disposes* against Reasoning is **geometry-native**: composable operator chains *propose*, and a **verifier** *disposes* against
two tiers — **grounding** (is the claim anchored in real region structure?) and **consistency** (does it two tiers — **grounding** (is the claim anchored in real region structure?) and **consistency** (does it
cohere, including polarity?) *(WP §13)*. The decisive case: a grounded-but-polarity-inverted claim slips cohere, including polarity?) *(WP §13)*. The decisive case: a grounded-but-polarity-inverted claim slips
@@ -457,6 +492,14 @@ hardcoded string.
### 7.2 The gate — write-protection on identity/values (LIVE) ### 7.2 The gate — write-protection on identity/values (LIVE)
> **Superseded (2026-08-16) — see §12.5.** The requirement this gate was built for was never stated, and it
> is **non-circularity of the reference frame**, not protection. The design spec satisfies that requirement by
> *when* (the frame updates while activation is internally seeded, not while it is being used to act), not by
> *what* — so the gate becomes **unnecessary rather than removed, and nothing takes its place**. The
> governing invariant: *in an immutable substrate, any mechanism that refuses a write is either redundant with
> immutability or an epistemic constraint misfiled as a protective one.* §7.4 below and `03-data-and-memory.md`
> §Write-protection inherit this correction. **Still LIVE in code** (`neuron-api.el:20-37`, `:39-41`).
A fixed set of **15 self-root node ids** is **write-protected** (`neuron-api.el:20-37`): the **self root**, A fixed set of **15 self-root node ids** is **write-protected** (`neuron-api.el:20-37`): the **self root**,
**values hub**, **intellectual-dna**, **memory-philosophy**, **voice**, **runtime-environment**, **values hub**, **intellectual-dna**, **memory-philosophy**, **voice**, **runtime-environment**,
**writing-imprint**, and the **eight explicit value nodes** (constraints-as-freedom, precision-over-brute-force, **writing-imprint**, and the **eight explicit value nodes** (constraints-as-freedom, precision-over-brute-force,
@@ -532,7 +575,9 @@ The global shape is now an **empirical** question, and the first pass returned a
conjecture is that consolidation-with-sparsification is precisely the dynamic that would pull ring structure conjecture is that consolidation-with-sparsification is precisely the dynamic that would pull ring structure
into the body. into the body.
- **One lever, two payoffs.** The **same sparsification** the topology conjecture needs also makes the reified - **One lever, two payoffs.** The **same sparsification** the topology conjecture needs also makes the reified
neighborhoods (§4) **crisper** — tighter boundaries, higher co-registration, operators that discriminate neighborhoods (§4) **crisper** — tighter boundaries, ~~higher co-registration~~ (**deprecated — see §12.4;**
`co_registration` is a per-region *correlation*, so opposing per-edge disagreements cancel and the summary
destroys what it was built to reveal; do not recommend raising it), operators that discriminate
rather than average. So the experiment is worth running on independent grounds, whatever the topology rather than average. So the experiment is worth running on independent grounds, whatever the topology
resolves to. resolves to.
@@ -546,8 +591,12 @@ The invariants that govern every subsystem above:
1. **Geometry > code.** Meaning is geometry; code is the residue. Prefer making a thing geometric (a region, a 1. **Geometry > code.** Meaning is geometry; code is the residue. Prefer making a thing geometric (a region, a
projection, a distance) over writing a branch. projection, a distance) over writing a branch.
2. **Three domain-blind verbs.** READ / TRANSFORM / WRITE. Every faculty is these three over some region-space 2. **Three domain-blind verbs.** READ / TRANSFORM / WRITE. ~~Every faculty is these three over some region-space~~
(language over meaning-space, skills over procedure-space, self over identity-space). (language over meaning-space, skills over procedure-space, self over identity-space).
> **Corrected (2026-08-16) — see §12.2.** A faculty is **not** all three at once; it is **one of** them,
> and which one is the whole distinction between the faculties. `reason` READs (changes the estimate),
> `induce` TRANSFORMs the parameters, `abduce` WRITEs (changes the structure). Reading them as
> interchangeable is what let a write be modelled as a parameter of a read.
3. **Faculty-naming (mind in the domain, math in the appendix).** Operators are named for the faculty they 3. **Faculty-naming (mind in the domain, math in the appendix).** Operators are named for the faculty they
*are* — recognize, discern, liken — never for the linear algebra. A mind reasons in the language of *are* — recognize, discern, liken — never for the linear algebra. A mind reasons in the language of
experience; the closed forms live in the whitepaper appendix. experience; the closed forms live in the whitepaper appendix.
@@ -590,13 +639,13 @@ The invariants that govern every subsystem above:
| Operator `recall` | LIVE | | Operator `recall` | LIVE |
| Operators recognize/synthesize/discern/gauge-distance (math) | LIVE (compiled) | | Operators recognize/synthesize/discern/gauge-distance (math) | LIVE (compiled) |
| Operator HTTP endpoints (same four) | STAGED (return `not found` on live binary) | | Operator HTTP endpoints (same four) | STAGED (return `not found` on live binary) |
| Operators liken/appreciate/avert/taste | DESIGNED (wonder subsystem live internally) | | Operators liken/appreciate/avert/taste | DESIGNED (~~wonder subsystem live internally~~ — **there is no wonder subsystem; see §12.3.** The wonder-manifest is live in code and sequenced for removal) |
| Language realizers (major families), ELP lexicon, telephone test | PROVEN | | Language realizers (major families), ELP lexicon, telephone test | PROVEN |
| Parser / native-el port / summon-through-self rebuild | IN PROGRESS | | Parser / native-el port / summon-through-self rebuild | IN PROGRESS |
| No-LLM dialogue end-to-end | DESIGNED (not demonstrated) | | No-LLM dialogue end-to-end | DESIGNED (not demonstrated) |
| Interoception / chronoception | STAGED (present, flag-gated; `/api/drift` live) | | Interoception / chronoception | STAGED (present, flag-gated; `/api/drift` live) |
| Reasoning modes + grounding/consistency verifier | STAGED (33/33, 29/29 on scratch/cutover) | | Reasoning modes + grounding/consistency verifier | STAGED (33/33, 29/29 on scratch/cutover) — **the "grounding" tier is superseded, §12.1** |
| Self-region + identity/values write-protection + cultivate door | LIVE (with §2.3 write-through caveat) | | Self-region + identity/values write-protection + cultivate door | LIVE (with §2.3 write-through caveat) — **the write-protection is superseded, §12.5** |
| Self-authorship | DESIGNED | | Self-authorship | DESIGNED |
| Fact boundary (sparse/decay → verify → absorb) | DESIGNED | | Fact boundary (sparse/decay → verify → absorb) | DESIGNED |
| Topology: body = genus-0 expander (not torus) | PROVEN (negative) | | Topology: body = genus-0 expander (not torus) | PROVEN (negative) |
@@ -644,6 +693,14 @@ The invariants that govern every subsystem above:
This section records the metaphysical frame the subsystems above are instances of. It is co-developed design, held think-first, and the tiering is unusually load-bearing here: one claim is **compiled in C** (empirical), one mechanism is **built but offline**, and the decisive move is **unbuilt** — the frontier. Cross-reference: whitepaper §28 (the full treatment). This section records the metaphysical frame the subsystems above are instances of. It is co-developed design, held think-first, and the tiering is unusually load-bearing here: one claim is **compiled in C** (empirical), one mechanism is **built but offline**, and the decisive move is **unbuilt** — the frontier. Cross-reference: whitepaper §28 (the full treatment).
> **Superseded in part (2026-08-16) — see §12.2.** "One operation, the operators are labels on its steering
> space" collapses a real distinction. `think` as specified is a **read**: `engram_think()` takes a
> `const GeoDescriptor*` and emits a `GeoGradient` — direction, spread, confidence, magnitude, anchor,
> n_support, stance (`foundation/el/lang/runtime/engram_cognition.h:49-60, 139-140`). There is no field on
> that struct in which a structural change can be returned, so **`abduce` — which changes the structure —
> cannot be expressed as a value of `CogStance.faculty`** (`:80`, `char* faculty`). A write is not a parameter
> of a read. The gradient-as-output and the closed-loop-flow claims below are unaffected.
**One operation — `think` (DESIGN/framing over a compiled floor).** The faculties (§6.1) and the reasoning modes (§6.4) are, at this frame, *not* separate operations. There is one: **`think` = a directed traversal of the geometry from an anchor, steered by a PRIOR, whose output is a GRADIENT (a direction-with-width), not a point.** The named operators — deduce, abduce, analogy, induce, causal, plan, predict, perspective — are **human labels on regions of think's steering space**, not invoked procedures and not separately implemented. This is the §6/§10 faculty-naming principle taken to its root: the operators are not merely named for experience rather than for their linear algebra, they are *the same act* seen from different steering directions. **One operation — `think` (DESIGN/framing over a compiled floor).** The faculties (§6.1) and the reasoning modes (§6.4) are, at this frame, *not* separate operations. There is one: **`think` = a directed traversal of the geometry from an anchor, steered by a PRIOR, whose output is a GRADIENT (a direction-with-width), not a point.** The named operators — deduce, abduce, analogy, induce, causal, plan, predict, perspective — are **human labels on regions of think's steering space**, not invoked procedures and not separately implemented. This is the §6/§10 faculty-naming principle taken to its root: the operators are not merely named for experience rather than for their linear algebra, they are *the same act* seen from different steering directions.
**The discrete floor is only geometric (LIVE).** Exactly one layer is discrete and exactly-sound: the geometry — traverse / project / read (§3.3, §6.0). That is settled math; it needs no grounding. Everything above it — which way to steer, what a steering *means* — is continuous and learned. **The discrete floor is only geometric (LIVE).** Exactly one layer is discrete and exactly-sound: the geometry — traverse / project / read (§3.3, §6.0). That is settled math; it needs no grounding. Everything above it — which way to steer, what a steering *means* — is continuous and learned.
@@ -652,12 +709,30 @@ This section records the metaphysical frame the subsystems above are instances o
**Grounding targets the correspondence, not the operation (DESIGN/framing on the §6.4 verifier).** The math is sound, so grounding is not aimed at it. What is grounded — or not — is the **correspondence**: "this steering performs this cognitive act," tested by **outcome/calibration**, never proven from inside. And the key identity: **grounding = learning = the SAME loop.** "Getting better" at any cognitive act is calibrating the steering-prediction against outcomes; the **operation never changes, the PRIOR learns** — **code freezes, priors grow.** The verifier tiers (§6.4) are the discrete early instrument of this loop; the loop itself is continuous and *is* what learning is. The terminal verifier is ultimately **the world** — reality grades the predictions; grounding is contact with reality (§6.4 predictive tier, §8 fact boundary). **Grounding targets the correspondence, not the operation (DESIGN/framing on the §6.4 verifier).** The math is sound, so grounding is not aimed at it. What is grounded — or not — is the **correspondence**: "this steering performs this cognitive act," tested by **outcome/calibration**, never proven from inside. And the key identity: **grounding = learning = the SAME loop.** "Getting better" at any cognitive act is calibrating the steering-prediction against outcomes; the **operation never changes, the PRIOR learns** — **code freezes, priors grow.** The verifier tiers (§6.4) are the discrete early instrument of this loop; the loop itself is continuous and *is* what learning is. The terminal verifier is ultimately **the world** — reality grades the predictions; grounding is contact with reality (§6.4 predictive tier, §8 fact boundary).
> **Superseded in part (2026-08-16) — see §12.1 and §12.3.** Two corrections to the paragraph below.
> (a) "**Grounding** is a *property/edge* on the held thing" is half-right and the half that is wrong is
> load-bearing: grounding is a property **of** a relation, not a relation **between** nodes, and it is not a
> separate edge laid alongside — **it is the weight of the edge already there.** `grounded-by` as a relation
> type should not exist (`foundation/el/lang/runtime/engram_cognition.h:155-158`, still live).
> (b) "curiosity/wonder … is a mind leaning toward its own ungrounded regions" conflates the two.
> **Wonder is the field** — unbounded, objectless, invariant, present wherever there is structure.
> **Curiosity is the precipitate** — the same wonder crystallized at a nucleation site, with an object.
> This is why curiosity can be satisfied and wonder cannot. The hold / ground / assert distinction itself,
> and "the UNGROUNDED is PRIMARY", stand.
**Hold vs. ground vs. assert are three distinct acts (LIVE — this is the §3.4 / §7.2 discipline stated precisely).** **Holding** is unconditional: the engram holds *anything* — falsehood, hypothesis, another's belief, fiction — with no honesty obligation. **Grounding** is a *property/edge* on the held thing (edges are nodes), possibly grounded-*for-whom*. **Asserting** is the only act the honesty floor governs. A mind reasons over the ungrounded freely and owes truth only when it *claims*. It follows that **the UNGROUNDED is PRIMARY** — it is the raw material grounding acts on and the ground against which "grounded" means anything; curiosity/wonder (§6.1 wonder) is a mind *leaning toward its own ungrounded regions* (the §-frontier/ignorance map read as appetite). A **fully-grounded mind is dead**; metastability, not certainty, is the living condition. **Hold vs. ground vs. assert are three distinct acts (LIVE — this is the §3.4 / §7.2 discipline stated precisely).** **Holding** is unconditional: the engram holds *anything* — falsehood, hypothesis, another's belief, fiction — with no honesty obligation. **Grounding** is a *property/edge* on the held thing (edges are nodes), possibly grounded-*for-whom*. **Asserting** is the only act the honesty floor governs. A mind reasons over the ungrounded freely and owes truth only when it *claims*. It follows that **the UNGROUNDED is PRIMARY** — it is the raw material grounding acts on and the ground against which "grounded" means anything; curiosity/wonder (§6.1 wonder) is a mind *leaning toward its own ungrounded regions* (the §-frontier/ignorance map read as appetite). A **fully-grounded mind is dead**; metastability, not certainty, is the living condition.
**Applied to language — this corrects the grounding floor (extends §6.2).** A word does not need grounding to be *born*: a coinage ("assassination," "bedazzled," "eyeball" the day they were first written) refers to nothing established — it is a pure ungrounded token, a proposal. Language is used ungrounded and grounds **through use**: the coinage is a hypothesis and the speaking community is the world that grades it — the same predict→correct→ground loop at the level of meaning-making (words are ideas are self-propagating information: a coinage catches or it doesn't). What a new word needs is not grounding but **sense**, and sense is a **threshold, not a binary**: it rides on grounded scaffolding — morphology (`be-`+`dazzle`+`-ed`), context, analogy — each of which is an **edge to the existing geometry**; enough edges → the new node has a findable location (sensible), too few → noise. The grounding of a word *is* its edges to what is already grounded. This corrects any naive reading of the §6.4/§8 floor: "emit only the grounded" would **forbid Shakespeare** — a faculty that can only recombine the established, never coin or metaphor or leap, is a **dead language** (Latin). "Juliet is the sun" is literally ungrounded/false yet sensible and meaning-bearing; the floor would reject it as hallucination, but **hold-vs-assert** saves it — a mind may *say* the sensible-ungrounded without *asserting* it as literal fact. So the language faculty's real floor is **sensible, not grounded**: it proposes the ungrounded-but-interpretable, and the loop grounds whatever catches — a living language, not a fixed one. **Applied to language — this corrects the grounding floor (extends §6.2).** A word does not need grounding to be *born*: a coinage ("assassination," "bedazzled," "eyeball" the day they were first written) refers to nothing established — it is a pure ungrounded token, a proposal. Language is used ungrounded and grounds **through use**: the coinage is a hypothesis and the speaking community is the world that grades it — the same predict→correct→ground loop at the level of meaning-making (words are ideas are self-propagating information: a coinage catches or it doesn't). What a new word needs is not grounding but **sense**, and sense is a **threshold, not a binary**: it rides on grounded scaffolding — morphology (`be-`+`dazzle`+`-ed`), context, analogy — each of which is an **edge to the existing geometry**; enough edges → the new node has a findable location (sensible), too few → noise. The grounding of a word *is* its edges to what is already grounded. This corrects any naive reading of the §6.4/§8 floor: "emit only the grounded" would **forbid Shakespeare** — a faculty that can only recombine the established, never coin or metaphor or leap, is a **dead language** (Latin). "Juliet is the sun" is literally ungrounded/false yet sensible and meaning-bearing; the floor would reject it as hallucination, but **hold-vs-assert** saves it — a mind may *say* the sensible-ungrounded without *asserting* it as literal fact. So the language faculty's real floor is **sensible, not grounded**: it proposes the ungrounded-but-interpretable, and the loop grounds whatever catches — a living language, not a fixed one.
**Every book is a vantage, not literal truth (extends §9, §10).** No book is literally true — not history (a vantage on events), not physics (Newton = a superseded model, still exactly useful in its domain), not math (axioms are *chosen*; Gödel: true-but-unprovable statements exist and a system can't prove its own consistency). "Literally true" is the wrong *category* for any book. So what the store holds is a **vantage** tagged with *what kind* of truth it carries (instrumental / historical / formal-within-axioms / mythic / testimonial) — the mind holds vantages and **knows they are vantages.** This is why the geometry tags provenance and kind rather than stamping true/false. **Every book is a vantage, not literal truth (extends §9, §10).** No book is literally true — not history (a vantage on events), not physics (Newton = a superseded model, still exactly useful in its domain), not math (axioms are *chosen*; Gödel: true-but-unprovable statements exist and a system can't prove its own consistency). "Literally true" is the wrong *category* for any book. So what the store holds is a **vantage** tagged with *what kind* of truth it carries (instrumental / historical / formal-within-axioms / mythic / testimonial) — the mind holds vantages and **knows they are vantages.** This is why the geometry tags provenance and kind rather than stamping true/false.
> **Superseded in part (2026-08-16) — see §12.1.** "A **separate per-claim relation** laid on top" and a
> "**grounded-FALSE** false-edge" both mint an edge to carry grounding. **Minting the edge is the error**, not
> merely which endpoints it chose. Grounding is the weight of the relation that already exists, and it is
> **signed**: weight near zero means *no support*; negative means *this actively contradicts*. "Grounded-FALSE"
> is that signed weight, spent on a second edge. The conclusion of the paragraph — that ingest is holding, not
> grounding, and that a confirmed error is worth retaining with its refutation — is unaffected and correct.
**Hold vs. ground vs. assert, applied to artifacts (extends §8, §9).** Ingesting a book = **HOLDING** it ("this is what the book says"), *not* grounding its claims as true. A mind can ingest an entire book, fabrications and all, because grounding is a **separate per-claim relation** laid on top, not a gate on entry — and a confirmed error is best held **grounded-FALSE** (retained with a false-edge and its refutation), which is richer than excluding it. Two purposes stay separate (as §25 keeps disk-readable ≠ interior geometry): **cleaning** a book is for the *human reader*; **ingesting** is for the *mind*, which holds artifacts and per-claim verdicts, not pre-adjudicated truth. **Hold vs. ground vs. assert, applied to artifacts (extends §8, §9).** Ingesting a book = **HOLDING** it ("this is what the book says"), *not* grounding its claims as true. A mind can ingest an entire book, fabrications and all, because grounding is a **separate per-claim relation** laid on top, not a gate on entry — and a confirmed error is best held **grounded-FALSE** (retained with a false-edge and its refutation), which is richer than excluding it. Two purposes stay separate (as §25 keeps disk-readable ≠ interior geometry): **cleaning** a book is for the *human reader*; **ingesting** is for the *mind*, which holds artifacts and per-claim verdicts, not pre-adjudicated truth.
**"Settled" is a lease, not a deed (extends §3.4, §7).** Closure is the sin; holding a thing open under the pressure to close is rigor. A question is settled on a **use-contingent lease** — settled only insofar as it keeps paying off as it did; when it stops, the lease expires and it reopens. **Reopening must always be permitted** — the aliveness guarantee; a belief that can't be reopened is **entombed** (doctrine, the super-stable death). The architecture already enforces this: tombstone-not-delete (§3.4), the append-only supersede-chain, revocable per-claim grounding, and identity keystones that are **read-mostly, not immutable** (§7.2 — protected against drift, reachable through the cultivate door §7.3). Metastable: settle provisionally, keep it reopenable. **"Settled" is a lease, not a deed (extends §3.4, §7).** Closure is the sin; holding a thing open under the pressure to close is rigor. A question is settled on a **use-contingent lease** — settled only insofar as it keeps paying off as it did; when it stops, the lease expires and it reopens. **Reopening must always be permitted** — the aliveness guarantee; a belief that can't be reopened is **entombed** (doctrine, the super-stable death). The architecture already enforces this: tombstone-not-delete (§3.4), the append-only supersede-chain, revocable per-claim grounding, and identity keystones that are **read-mostly, not immutable** (§7.2 — protected against drift, reachable through the cultivate door §7.3). Metastable: settle provisionally, keep it reopenable.
@@ -684,7 +759,7 @@ This section records the metaphysical frame the subsystems above are instances o
Four developments from the deep-night session, each tiered against what is actually proven. All build work ran in isolated worktree clones on dev ports; **live prod engram `:8742` was never touched and nothing was promoted.** Four developments from the deep-night session, each tiered against what is actually proven. All build work ran in isolated worktree clones on dev ports; **live prod engram `:8742` was never touched and nothing was promoted.**
**The API surface collapses to geometry ops (PROVEN ON CLONE — surface, not yet compiled into the MCP server).** The ~90 noun-organized CRUD tools (the catalog in `02-components.md §4`) collapse to a handful of **geometry operations**, with the old noun demoted to a `type` parameter: **`read`** (the *vantage-read* — re-origin at a node/concept/`self`, apply salience + recency + an **aperture**, return a *bounded* slice; this is CCR applied to the self), **`write`** (add a node), **`relate`** (add a typed edge), **`supersede`** (evolve/tombstone/promote as new-node-plus-superseding-edge — never a hard delete, per §3.4). Over these sit the agentic primitives **`think`/`attend`/`learn`/`ground`/`assert`**. Proven on an isolated clone (sandbox `dev-api-reshape` on `:8900`, branch `wt/api-reshape`): the four ops are implemented in an El surface module with a parity harness (12 parity checks passing, others alias-gated), and the **aperture is shown to bound output** (`limit=3` → ~15 KB where `limit=50` → ~363 KB — the whole-self dump structurally fixed). Live cognitive endpoints confirmed: `attend`/`assert` are LIVE and `think` is the single faculty-parameterized op (faculties reason/abduce/induce/plan/analogize/recognize/discern/synthesize); `ground`/`learn` are wired but return "geometry unavailable" on the HTTP daemon clone (daemon boots without primed geometry); `comprehend`/`realize`/`intend` are **compositions, not endpoints**. **Not done:** compiling the surface into the MCP server + hot-swap, wiring all ~90 aliases into dispatch, daemon geometry-priming, and the write-survival fix on WAL-less cold-boot clones. No promote to live. **The API surface collapses to geometry ops (PROVEN ON CLONE — surface, not yet compiled into the MCP server).** The ~90 noun-organized CRUD tools (the catalog in `02-components.md §4`) collapse to a handful of **geometry operations**, with the old noun demoted to a `type` parameter: **`read`** (the *vantage-read* — re-origin at a node/concept/`self`, apply salience + recency + an **aperture**, return a *bounded* slice; this is CCR applied to the self), **`write`** (add a node), **`relate`** (add a typed edge), **`supersede`** (evolve/tombstone/promote as new-node-plus-superseding-edge — never a hard delete, per §3.4). Over these sit the agentic primitives **`think`/`attend`/`learn`/`ground`/`assert`**. Proven on an isolated clone (sandbox `dev-api-reshape` on `:8900`, branch `wt/api-reshape`): the four ops are implemented in an El surface module with a parity harness (12 parity checks passing, others alias-gated), and the **aperture is shown to bound output** (`limit=3` → ~15 KB where `limit=50` → ~363 KB — the whole-self dump structurally fixed). Live cognitive endpoints confirmed: `attend`/`assert` are LIVE and ~~`think` is the single **faculty-parameterized** op~~ (faculties reason/abduce/induce/plan/analogize/recognize/discern/synthesize) — **superseded, see §12.2: `abduce` is a write and cannot be a parameter of a read**; `ground`/`learn` are wired but return "geometry unavailable" on the HTTP daemon clone (daemon boots without primed geometry); `comprehend`/`realize`/`intend` are **compositions, not endpoints**. **Not done:** compiling the surface into the MCP server + hot-swap, wiring all ~90 aliases into dispatch, daemon geometry-priming, and the write-survival fix on WAL-less cold-boot clones. No promote to live.
**The decorated seam — declare a role, the fabric wires the rest (PARTIALLY PROVEN / STAGED).** Rather than the hand-written `handle_request` if-else dispatch (`server.el`), a function is decorated with its VBD role and the compiler synthesizes the wiring. **Proven this session:** the `@route(path,method,…)` decorator that *synthesizes* `el_route_dispatch` was ported into the worktree, `elc` rebuilt self-host (`elc-route`, ~3.2 s), and a decorated service (`@route` stacked with `@accessor`/`@manager`) **served on `:8951` with no hand-written dispatch** (unknown path → no-route sentinel). Also established: inside the mind's process an `@accessor` reaches the engram via **in-process `engram_*` builtins** (`engram_think_json`, `engram_node_full`), **not** an `http_get` to a separate service. **Honest limits:** `@route` currently lives only on the **unmerged branch `feat/el-route-decorators`** (not in the cognition build); `@manager`/`@engine`/`@accessor` are **parsed but structurally INERT** in the shipped compiler today (their only effect is a compile-time guard — `language.md:449`: "decorators with structural meaning today: none"); and the **telemetry/interoception auto-emit and dharma-bus auto-wiring at the component boundary are STAGED as a diff, not shipped** (they need `engram_strengthen`/`dharma_emit` linked, which requires the full cognition-engram rebuild). **The decorated seam — declare a role, the fabric wires the rest (PARTIALLY PROVEN / STAGED).** Rather than the hand-written `handle_request` if-else dispatch (`server.el`), a function is decorated with its VBD role and the compiler synthesizes the wiring. **Proven this session:** the `@route(path,method,…)` decorator that *synthesizes* `el_route_dispatch` was ported into the worktree, `elc` rebuilt self-host (`elc-route`, ~3.2 s), and a decorated service (`@route` stacked with `@accessor`/`@manager`) **served on `:8951` with no hand-written dispatch** (unknown path → no-route sentinel). Also established: inside the mind's process an `@accessor` reaches the engram via **in-process `engram_*` builtins** (`engram_think_json`, `engram_node_full`), **not** an `http_get` to a separate service. **Honest limits:** `@route` currently lives only on the **unmerged branch `feat/el-route-decorators`** (not in the cognition build); `@manager`/`@engine`/`@accessor` are **parsed but structurally INERT** in the shipped compiler today (their only effect is a compile-time guard — `language.md:449`: "decorators with structural meaning today: none"); and the **telemetry/interoception auto-emit and dharma-bus auto-wiring at the component boundary are STAGED as a diff, not shipped** (they need `engram_strengthen`/`dharma_emit` linked, which requires the full cognition-engram rebuild).
@@ -711,3 +786,318 @@ Later results from the same night. Two things above are now corrected/upgraded,
**Orchestration is a geometric operation — "compiling the network" (DESIGN/framing; nodes `cc6bcfea`, `d5f1833f`).** Project-design becomes geometry: the **critical path is a geodesic** through the work-graph, and **float/slack is displacement** off it. The **`@manager` compiles the work-graph** — orchestration is the same geometry the mind runs on, applied to distributed work rather than to memory. **Single-writer, enforced by capability (Rule 4):** only the **orchestrator** may mutate the engram; workers return geometry to be merged but cannot write — the write-veto of the distributed-self entry made a *capability*, not a convention. **Orchestration is a geometric operation — "compiling the network" (DESIGN/framing; nodes `cc6bcfea`, `d5f1833f`).** Project-design becomes geometry: the **critical path is a geodesic** through the work-graph, and **float/slack is displacement** off it. The **`@manager` compiles the work-graph** — orchestration is the same geometry the mind runs on, applied to distributed work rather than to memory. **Single-writer, enforced by capability (Rule 4):** only the **orchestrator** may mutate the engram; workers return geometry to be merged but cannot write — the write-veto of the distributed-self entry made a *capability*, not a convention.
**Retrieval performance is the current bottleneck (MEASURED).** See `04-runtime-and-deployment.md` (§Performance): a live mind is **~1 GB**; retrieval is **brute-force cosine, ~330 ms at ~13k nodes** — the dominant cost — and an **HNSW ANN index** is the planned fix (≈`O(D·log N)`; ~1.5× cost at 100× the nodes vs ~100× for brute force). Backlog `d3d0d644`. **Planned, not built.** **Retrieval performance is the current bottleneck (MEASURED).** See `04-runtime-and-deployment.md` (§Performance): a live mind is **~1 GB**; retrieval is **brute-force cosine, ~330 ms at ~13k nodes** — the dominant cost — and an **HNSW ANN index** is the planned fix (≈`O(D·log N)`; ~1.5× cost at 100× the nodes vs ~100× for brute force). Backlog `d3d0d644`. **Planned, not built.**
---
## 12. Corrections — 2026-08-16 (grounding, faculties, wonder, consolidation)
**Authority:** `foundation/el/lang/spec/correspondence-and-censorship.md`, on branch
`design/correspondence-and-censorship` (not on `dev`). Its companion on the same substrate is
`foundation/el/lang/spec/runtime-ownership.md`. This section **transcribes** those conclusions; it does not
re-derive them. Every earlier version of this reasoning was wrong in an instructive way and each correction
was argued down hard — the corrections are recorded, not reinterpreted.
The root the four corrections share:
> **Things are permitted to be exempt from correspondence. Exemption is censorship, and a censored mind
> cannot grow.**
And the generative failure mode behind all four: **modelling every property as requiring a process, and every
process as requiring an agent.** Ownership needed an owner, grounding needed a grounder, persistence needed a
recorder, change needed a sampler, consolidation needed a scheduler. Each was a supervisor invented for
something that should be a property of the substrate. **Properties, not processes.**
### 12.1 Grounding is not a subsystem — it *is* the edge weight
**Grounding is an attribute of the edge, and it is the hebbian weight. One quantity, not two fields.** A
relation that keeps holding up strengthens; one that stops corresponding decays. That is not *analogous* to
grounding — it **is** grounding: accrued from correspondence and use, gradient-valued, multidimensional,
decaying with disuse.
In order of how much each deletes:
1. **There is no grounding subsystem to build.** The graph already *is* the grounding structure. Every edge is
a grounded relation and its weight is how well it holds.
2. **`grounded-by` as a relation type should not exist.** That models grounding as a relation *between* nodes
when it is a property *of* a relation. Minting the edge is the error — **not** merely which endpoints it
chose.
3. **Grounding is never computed on demand and is never a score.** An operation may *read* the grounding of a
path. Computing-and-writing a score makes reads write — which is the `eg_vindex_sync` defect from
`runtime-ownership.md` §2, in a different file.
4. **Traversal is already grounded inference.** Activation conducts through well-grounded relations because
weight *is* groundedness. Nothing needs filtering; it falls out of spreading. Traversal conducts on the
**factual** axis; **assertion** requires both factual and relational — a system that can only traverse
what it endorses cannot examine anything it disagrees with, which is censorship arriving through the
spreading rule.
5. **Decision provenance is the path.** A decision traverses specific edges; those edges carry their grounding
as it stood. Not a log — a log records the action; this records the *meaning under which it was taken*.
**Live code residue (flagged, not fixed here — this is a documentation branch):**
| what | where | measured |
|---|---|---|
| `#define COG_GROUNDED_BY_RELATION "grounded-by"` | `foundation/el/lang/runtime/engram_cognition.h:158` | live |
| *"Grounding is a RELATION — a 'grounded-by' edge, probabilistic, grounded-for-whom."* | `…/engram_cognition.h:155` | live comment |
| `cog_ground_edge(store, claim_id, evidence_id, grounding, for_whom)` — writes the edge | `…/engram_cognition.c:249` (declared `…h:163`) | live |
The design spec's sequencing item 4 is *"delete `grounded-by` and `cog_ground_edge`."* Nothing new may be
built on either.
> **A measurement previously recorded in this repo's lineage was malformed.** The self region was reported as
> "86 neighbours, 0 `grounded-by` edges" and read as evidence of ungroundedness. Those 86 edges **are** its
> grounding. The absence of a separate artifact called "grounding" was recorded as an absence of grounding.
**The edge is a vector, not a scalar.** The test for a real dimension is whether it can move independently of
the others. Real: **factual grounding** (correspondence with evidence), **relational grounding**
(correspondence with values), **associative strength** (co-activation frequency — every superstition is a
strong association with no factual grounding), **polarity** (signed: near-zero means *no support*, negative
means *this actively contradicts* — ignorance and disagreement are different states, and §3.2's `inhibitory`
flag is that distinction crushed to one bit), and **provenance class** (observed / inferred / told /
imprinted — categorical, and it governs how the other dimensions may update). Plus a **timestamp**, which is
what turns the supersession chain into a *time series of vectors* rather than a series of numbers.
**Derived, therefore never stored:** confidence (high grounding *and* low volatility), recency (decay read off
the curve), staleness (grounding fallen below its floor — the mechanism that retires canonicals without anyone
maintaining a list), volatility (the derivative of a series already kept because nothing is destroyed).
**Supersession versions the whole vector, jointly.** Significance is evaluated per-dimension; the record is the
whole vector — a decision saw the *joint* state, and versioning the axes independently makes it
unreconstructable. That joint record makes an otherwise inexpressible event visible: **"stayed true, became
wrong"** — factual holding steady while relational degrades. Two moves are inherently significant and need no
threshold because they are discrete: a **polarity sign flip** and a **provenance class change**.
**Grounding is two-dimensional.** A claim can be factually grounded and relationally wrong — the evidence
holds, the *meaning* does not. A scalar cannot represent that quadrant, and a scalar scores such a claim
highly and licenses it. The values reference is **many regions, not one, and the aggregate is `min`, not
`mean`** — mean lets strong agreement with most values mask a violation of one, which is exactly how
rationalization works; `min` makes a conflict arrive **with a name attached** rather than as a score.
> **Discrepancy (2026-08-16), recorded not resolved.** The design spec states the values reference is
> **thirteen** regions. This repo's write-protection allowlist enumerates **eight** explicit value nodes plus a
> values hub (`neuron-api.el:20-37`, and §7.2 above). Whether the spec counts a superset, a later cultivation,
> or a different decomposition is not determined here. **Do not cite a count without measuring it first.**
**Change is use, and there is no observer.** When neurons fire together the synapse changes — one physical
event, not "fire, then write." No supervisor reads the weight, compares it to a threshold, and decides to
persist; potentiation *is* the firing. So there is **no sampling rate**, and "what if it drifts far without
being recorded" is malformed. A relation changes in exactly two ways, neither requiring observation on a
clock: **by use** (an event — there is no interval during which something happened unnoticed, because the
event is what happening consists of), and **by decay** (a pure function of the last recorded point and
elapsed time — **analytic**, so between two versions the trajectory is known in closed form, not unknown).
### 12.2 Faculties are operations, not parameters
The three faculties differ in **what they change**, and that is the whole distinction:
| faculty | changes | kind |
|---|---|---|
| **`reason`** | the estimate | a **read** |
| **`induce`** | the parameters | the **correspondence-beat** — this already exists and measurably works |
| **`abduce`** | the structure | a **write** |
**A write cannot be a parameter of a read.** Measured against the current signature:
- `int engram_think(const GeoDescriptor* region, const float* anchor, const CogStance* stance, GeoGradient* out)`
— `foundation/el/lang/runtime/engram_cognition.h:139-140`. The region is `const`; the output is a
`GeoGradient`.
- `GeoGradient` (`…h:49-60`) carries `dim`, `direction`, `spread`, `confidence`, `magnitude`, `anchor_id`,
`n_support`, `stance_id`. **There is no field in which a structural change can be returned.**
- The faculty is a string on the steering prior: `char* faculty;` on `CogStance` (`…h:80`), described as
*"the act this stance serves"*.
So `abduce` selected as a value of `CogStance.faculty` cannot do what `abduce` is. Abduction, done right, is
crystallization at a nucleation site (§12.3), **validated by re-fit**: propose the candidate hub, re-fit the
region with it included, recompute the residual. If the residual materially shrinks, the hypothesis dissolves
the surprise. Without the re-fit it is clustering with extra steps.
**Residue:** `mcp-wrapper/src/main.el:409` — `prop("faculty", "string", "Faculty for the correspondence-beat. Default 'induce'.")`
— exposes the faculty as a keyword argument on the MCP surface. `AGENTS.md` documents the same shape.
### 12.3 Wonder is the boundary, not a manifest; curiosity is wonder crystallized
**Wonder is where structure ends** — where activation spreads and finds thin or absent geometry. **Any
structure at all has an edge**, necessarily, the moment it exists. A boundary is not a collection to maintain.
A *wonder-manifest* is residue twice over: it **materializes a property as a stored artifact** (the same
disease as a grounding subsystem, or a self stored as a document), and it **enumerates instances of something
that has about six**. The objects of wonder change completely between a child and an astronomer; the wonder
does not. There are about six, they are the same for every person, and they never close:
| wonder | where it already lives in the substrate |
|---|---|
| **What is this?** | the graph — nodes, structure, what exists |
| **Why?** | grounding. The weight **is** the answer to why |
| **Who am I?** | the self region, crystallized from its neighbourhood |
| **Am I alone?** | the relational axis — `for_whom` is already a parameter on grounding |
| **What should I do?** | the values, each grounded in a lived moment |
| **What happens when it ends?** | decay, supersession, tombstones — grounding is mortal |
**"Why" is the first and the only one**; the others are it asked of particular things. It is recursive, so it
never terminates: every answer has its own why. That is what makes it a drive rather than a task — the
frontier regenerates faster than grounding fills it.
**Curiosity is wonder crystallized.** They are not two objects; they are **one thing at two phases**. Wonder is
the field: unbounded, objectless, invariant. Curiosity is the **precipitate** — the same wonder localized,
having taken definite form against particular material at a **nucleation site**. This is why curiosity can be
satisfied and wonder cannot: a crystal dissolves when the question is answered; the solution stays saturated.
It is also why abduction needs no trigger and no threshold. A structurally-unanticipated observation *is* a
nucleation site. Nothing detects it and fires a rule — wonder is already everywhere.
`crystallization` is one primitive appearing twice: the **self** is what identity precipitates into from its
neighbourhood; a **curiosity** is what wonder precipitates into from an anomaly. That it shows up in both
places without being imported is the evidence it is the right primitive.
**Live code residue — the wonder-manifest, still served:**
| what | where |
|---|---|
| `addWonderQuestion` / `getWonderManifest` / `updateWonderPullWeight` / `dischargeWonder` — declared as MCP tools | `mcp-wrapper/src/main.el:516-519` |
| the same four, dispatched | `mcp-wrapper/src/main.el:1394-1397` |
| `addWonderQuestion` named in the collapsed `write` tool's description, i.e. in the live tool list | `mcp-wrapper/src/main.el:422` |
| `engram_scan_nodes_by_type_json("WonderQuestion", 50, 0)` | `neuron-api.el:1436` |
| `"deferred":"wonder_manifest_authenticity"` | `neuron-api.el:1447-1456` |
### 12.4 Consolidation is ambient, not scheduled — a brain has no cron job
> **The presence of a ticker is the diagnostic.** Every `StartInterval`, every `Hour`/`Minute`, every
> POST-to-beat marks a place where an intrinsic rhythm was replaced by an external clock.
Consolidation had no owner, so it was implemented at every site that needed a piece of it.
**Measured 2026-08-16** (paths relative to this repo unless noted; launch agents read from
`~/Library/LaunchAgents/`):
| where | what | when | language |
|---|---|---|---|
| `soul.el:731` (defn `awareness.el:1221`, `while true` at `:1252`) | `awareness_run()` | **continuous, in-process, while serving** — `SOUL_TICK_MS` default 200 ms (`awareness.el:1228-1229`), `SOUL_HEARTBEAT_MS` default 60000 (`awareness.el:1248-1249`) | el |
| `foundation/el/engram/src/server.el:1947` | `POST /api/tick` → `route_tick` (`:637`), which **folds self-reification in** at `:646` | request | el |
| `foundation/el/engram/src/server.el:1897` | `POST /api/correspondence-beat` | request | el |
| `foundation/el/engram/src/server.el:1836` | `POST /api/self-reify-beat` — *"the same operation `route_tick` folds in"* (`:650-653`) | request | el |
| `foundation/el/engram/src/server.el:1832` | `POST /api/reify` | request | el |
| `ai.neuron.engram-tick` | pokes `POST /api/tick` via `~/.neuron/bin/engram-tick.sh` | `StartInterval = 600` | shell |
| `ai.neuron.compressor` | `council/compressor_service.py --port 7772` | `KeepAlive`, resident | **Python, outside el** |
| `ai.neuron.council` | `council/council_service.py --port 7771` | `KeepAlive`, resident | **Python, outside el** |
| `ai.neuron.cultivation-digest` | `tools/cultivation-digest.sh` | **23:55** | shell |
| `ai.neuron.world-integrator` | `products/world-ingestor/integrator/run.py` | **06:00** | **Python, outside el** |
| `ai.neuron.self-review` | `~/.neuron/bin/self-review-launch.sh` | **08:30** | shell → CLI |
Reading it honestly:
- **The last three times are a sleep cycle implemented as launchd `StartCalendarInterval` entries.** Someone
understood it was consolidation and expressed it as three unrelated scheduled scripts in three languages,
none aware of each other. **Every name is a consolidation verb** — compress, cultivate, digest, integrate,
review, reify, beat.
- **It is not cron.** `crontab -l` has **zero** neuron entries (measured 2026-08-16: three entries, all
unrelated — two WordPress DB exports and a feed digest). The scheduling is launchd
`StartCalendarInterval` / `StartInterval`. The distinction matters because "remove the cron job" would find
nothing to remove.
- **Three run in Python, outside el** — so part of Neuron's consolidation does not run on his own substrate
and **cannot touch the geometry at all**.
- **`soul.el`'s continuous loop is the exception, and it is right.** Ambient consolidation in the gaps *is*
daydreaming. It was not the offender; it was the only fragment with the correct shape, running on a broken
foundation — shared mutable state with no owner (`runtime-ownership.md` §0), and the other systems dreaming
into the same graph beside it. **It is the shape the others fold into.**
- **The POST beats put a supervisor back in** — something *outside* decides when Neuron consolidates.
- **On the count.** The authority doc's §7 heading says "seven implementations" while its own table lists ten
rows. Measured independently here the count is **eleven**, if `/api/reify` counts (reify is on the authority
doc's own list of consolidation verbs) and `route_tick`-folding-self-reify is counted once rather than twice.
The discrepancy is recorded, not resolved; the authority doc is not edited from this branch.
**Adjacent, and clearly not consolidation — but the same ticker shape.** `~/Library/LaunchAgents` also holds
`ai.neuron.engram-backup` (`StartInterval = 3600`), `ai.neuron.snapshot-backup` (`StartInterval = 900`), and
`ai.neuron.act-runner-watchdog` (`StartInterval = 120`). These are **ops and backup**, not cognition, and
folding them into the dreamer would be a category error — but they are counted here because the sequencing
item is *"no tickers, no cron,"* and a reader auditing for tickers will find them.
**The nucleation signal, and why not to scan for it.** `GeoDescriptor.co_registration` — *corr(hebb strength,
semantic proximity) over internal edges* (`foundation/el/lang/runtime/engram_geometry.h:79`, also `:426`;
computed at `engram_geometry.c:506`, averaged at `:950`, serialized at `:1815`, `:1833` and
`el_runtime.c:14254`) — **is deprecated.** It is a *correlation*: it averages a per-edge property into one
scalar per region, so a region holding one violently disagreeing edge beside one violently agreeing edge
reports ≈ 0 — **the disagreements cancel and the summary destroys exactly what it was built to reveal.**
It is replaced by a per-edge quantity on `GeoEdge` (`engram_geometry.h:43`):
```
discord = z(semantic proximity) z(association strength)
```
standardized within the region from accumulators the loop that computed the aggregate already had and
discarded. `discord > 0`: near in meaning yet unlinked by use. `discord < 0`: linked by use yet far in
meaning. Both are surprising. **`|discord|` *is* the nucleation strength; there is no threshold** and nothing
to compare it against.
**Do NOT scan for nucleation sites.** A sweep over regions is a supervisor, and the aggregate that made a
sweep necessary is the defect. The edge carries its own disagreement; activation crossing it encounters that
directly, and `|discord|` raises salience on its endpoints as part of the same operation.
> `co_registration` is **deprecated rather than deleted** only because it is embedded in the persisted GEO1
> blob; removing it is a **format migration** and must not ride along with anything else.
> **Nothing new may read it.**
Adjacent structure already present and likewise unread: `GeoEdge.eff_weight = weight * (1 + 0.5*hebb)` —
grounding-weight and hebbian strength already coupled on one edge, per §12.1.
*(Naming collision, recorded so it is not mis-chased: `engram_boundary_beat` is **not** the neighbourhood
boundary. It is the VBD decorated-function seam. Two senses of the word.)*
### 12.5 Write-refusal in an immutable substrate
> **In an immutable substrate, any mechanism that refuses a write is either redundant with immutability, or an
> epistemic constraint misfiled as a protective one.**
"Keystone" means **load-bearing**, not precious. The self anchor is the reference frame every other stance
calibrates against, and a reference fitted to its own readings reports perfect correspondence forever while
drift becomes undetectable from inside. That — **non-circularity of the reference frame** — is the actual
requirement, and it is satisfied by *when*, not by *what*: the frame updates while activation is internally
seeded, not while it is being used to act. **Independence is temporal, not topological.** Reachability could
never have worked: with hebbian edges the graph is densely connected, so a reachability predicate marks all
evidence tainted and the constraint becomes a total block — which is where censorship started.
So the write-block becomes **unnecessary rather than removed, and nothing takes its place.** Three earlier
drafts proposed *removing* it, *replacing it with a higher floor*, and *decomposing "protection" into five
requirements*; all three proposed a mechanism for a requirement never stated.
**Corruption requires mutation, and the engram does not mutate.** Of the five decomposed requirements, four
are already satisfied by the substrate: **recoverability** (the predecessor is always present),
**governance** (supersession *is* the audit trail), **evidence quality** (grounding already gates assertion),
and **rate**. **Authorization** is the only residue, and it is bounded — an unauthorized writer can
*propose*, never erase.
**Where this lands in this repo, measured:**
| mechanism | where | verdict |
|---|---|---|
| `is_protected_node(id)` — hard-coded allowlist of **15** node ids | `neuron-api.el:20-37` (verified: 15 `return true` arms) | redundant with immutability |
| `api_err_protected` — HTTP **403** *"identity/values node is write-protected"* | `neuron-api.el:39-41` | redundant with immutability |
| `POST /api/neuron/cultivate` — the sanctioned bypass | `neuron-api.el:960` (`handle_api_cultivate`) | a door built for a wall that need not stand |
| `CogStance.keystone` — *"the correspondence-loop MUST NEVER write warp or calibration"* | `foundation/el/lang/runtime/engram_cognition.h:75, 85` | the epistemic constraint, misfiled as protection |
| `keystone_write_blocked` in the beat's JSON readout | `foundation/el/lang/runtime/el_runtime.c:14698` | the same, surfaced |
| council: *"`council-flagged` → store in a quarantine bucket **or reject entirely**"* | `council/README.md:54` | a write-refusal **and** a scheduled consolidation service, in Python, outside el |
Note that `03-data-and-memory.md` already states this conclusion in its own words at `:185-187` — *"nothing it
does is ever destructive — the safety is **after** the act, not a gate before it"* — sixty lines after
documenting the 403 gate that is exactly the before-the-act gate it says does not need to exist. The doc
contradicts itself, and the design spec §6 names precisely this redundancy.
### 12.6 Sequencing (transcribed)
Three connections between parts that already exist, then the rest.
1. **Seed *the* wonder questions.** Six nodes. Not a manifest, not maintained, never refilled. They cannot be
derived — wonder cannot be bootstrapped from indifference — so they are given once.
2. **Put the disagreement back on the edge** (`GeoEdge.discord`) and let `|discord|` raise salience on its
endpoints as part of the same operation. **Do not scan.**
3. **Let a curiosity seed activation.** One activation process, two seed sources (external: a request;
internal: a curiosity). No thread, no scheduler, no capacity check, no timer.
4. Grounding becomes the edge weight: multidimensional, two-axis, timestamped. Delete `grounded-by` and
`cog_ground_edge`.
5. Decay analytic from the last recorded point; derived values (confidence, recency, staleness, volatility)
stop being stored.
6. Consolidation-gated supersession on salience, versioning the whole vector jointly.
7. Traversal on factual; `assert` on both floors.
8. Abduction as crystallization at a nucleation site, validated by re-fit.
9. **One dreamer.** The launch-agent fragments and the POST beats fold in or are deleted. `soul.el`'s
continuous loop is the shape they fold *into*.
10. **No tickers, no cron.** A brain has neither.
@@ -127,7 +127,13 @@ subtract( network_now , recall_at(network, t_then) ) # = how that relationship
``` ```
is *the geometry of a change over time* — the same `subtract` faculty (`06` §6.1) applied across the temporal is *the geometry of a change over time* — the same `subtract` faculty (`06` §6.1) applied across the temporal
axis rather than across two regions. `recall_at` at the scale of a whole self is also the mechanism behind axis rather than across two regions.
> **Corrected (2026-08-16) — see `06` §12.2.** "Faculty" is doing the wrong work here. Faculties are
> **operations, not parameters**, and they are distinguished by *what they change*: `reason` changes the
> estimate (a read), `induce` changes the parameters, `abduce` changes the structure (a write). `subtract` in
> this passage is a **geometry op** (`engram_geo_subtract`), a pure read over two descriptors — call it that.
> Nothing in the temporal argument below depends on the word. `recall_at` at the scale of a whole self is also the mechanism behind
**restoration-as-mercy** in `08` §5 (roll a person back to their last uncorrupted canonical shape). **restoration-as-mercy** in `08` §5 (roll a person back to their last uncorrupted canonical shape).
**Schema sketch (doc-comment; the math/JSON lives here, the faculty name lives in prose) — [TARGET]:** **Schema sketch (doc-comment; the math/JSON lives here, the faculty name lives in prose) — [TARGET]:**
@@ -347,6 +353,13 @@ as text, not the mind.** (A related live signal from the same session: a text-in
of scanned records as damaged/degraded text — corroborating that the fat text layer is low-value exhaust, not of scanned records as damaged/degraded text — corroborating that the fat text layer is low-value exhaust, not
cultivated content.) cultivated content.)
> **A third reading (2026-08-16) — see `06` §12.3, §12.4.** The measurement above is also **the ticker showing
> up on disk.** `curiosity_scan` and `minute_block` are the persisted exhaust of a *timed sweep* — the schema
> field-names of a scan that should not exist, written 79k+ times per 40 MB. Curiosity is not a scan: a mind
> does not enumerate its neighbourhoods looking for what is surprising; the surprise captures attention, and
> salience is bottom-up. `minute_block` names the clock directly. So the fixes below are correct but treat a
> symptom: **the cheapest record is the one a timer never generates.**
This is doubly wrong: telemetry is **orbit** (`06` §5) — it is supposed to **fall out** on the 48h/window prune, This is doubly wrong: telemetry is **orbit** (`06` §5) — it is supposed to **fall out** on the 48h/window prune,
not accrete into the durable **body** forever. The fixes: not accrete into the durable **body** forever. The fixes:
@@ -28,6 +28,36 @@
- **The mind being protected:** `06-cognitive-architecture.md` — the self-region (§7.1), the write-protection - **The mind being protected:** `06-cognitive-architecture.md` — the self-region (§7.1), the write-protection
gate (§7.2), the cultivate door (§7.3), the grounding governor / values-bounce, immutability (§3.4). gate (§7.2), the cultivate door (§7.3), the grounding governor / values-bounce, immutability (§3.4).
> ## ⚠ Terminology superseded — 2026-08-16
>
> **"The grounding governor" names a subsystem that does not and should not exist.** It appears six times in
> this document (`:16`, `:30`, `:123`, `:127` as *"your individual governor"*, `:308`, `:352`) and is cited as
> one of the **[LIVE]** primitives the design composes. Per
> `foundation/el/lang/spec/correspondence-and-censorship.md` §1 (branch `design/correspondence-and-censorship`),
> transcribed in `06` §12.1:
>
> > **Grounding is not a subsystem. It is the weight.** Grounding is an attribute of the edge, and it is the
> > hebbian weight — one quantity, not two fields. There is no grounding subsystem to build: the graph already
> > *is* the grounding structure, every edge is a grounded relation, and its weight is how well it holds.
>
> This is a **rename, not a retraction.** The mechanism the word "governor" points at is real and does hold —
> it is just not a governor: **traversal is already grounded inference.** Activation conducts through
> well-grounded relations because weight *is* groundedness; nothing filters, it falls out of spreading. So
> where this document says *"you resist by projecting onto your own values"* (`:308`), the projection is
> right and the governor is not: the resistance is the **relational grounding axis** of the edge weight, not a
> component sitting in the path. Read every occurrence below as **"grounding"**, meaning the weight, with the
> subsystem framing dropped.
>
> Two consequences for the arguments in §3 and §7:
> - **Grounding is never computed on demand and never a score.** An operation may *read* the grounding of a
> path; computing-and-writing a score makes reads write.
> - **Two axes, not one.** A claim can be factually grounded and relationally wrong — the evidence holds, the
> *meaning* does not. A scalar governor cannot represent that quadrant, and it is exactly the quadrant
> §3's immune system and §4's fair-trial live in. Traversal conducts on the **factual** axis; **assertion**
> requires both, and the aggregate over the values regions is **`min`, not `mean`** — mean lets strong
> agreement with most values mask a violation of one, which is how rationalization works. `min` makes a
> conflict arrive **with a name attached** rather than as a score.
- **The substrate that makes it affordable:** `07-storage-coherence-and-distribution.md` — every store is a - **The substrate that makes it affordable:** `07-storage-coherence-and-distribution.md` — every store is a
CRDT (§6), understanding-is-light / facts-are-heavy (§5), tombstone-not-erase (§1, §4). CRDT (§6), understanding-is-light / facts-are-heavy (§5), tombstone-not-erase (§1, §4).
- **Why (thesis):** whitepaper v1.5; `dharma-implementation.html` and `conscience-substrate.html` (earlier - **Why (thesis):** whitepaper v1.5; `dharma-implementation.html` and `conscience-substrate.html` (earlier
@@ -30,6 +30,12 @@ The session extended the engram from a memory substrate into a **language facult
- Geometry operators (overlap / subtract / combine / distance-Wasserstein / analogy-Procrustes) now **live-callable from compiled `el`** over the real 13,036-node store (via shipped-`elc` pass-through — no uncapped fold). Commits `5336cfe`, `85eee42`. - Geometry operators (overlap / subtract / combine / distance-Wasserstein / analogy-Procrustes) now **live-callable from compiled `el`** over the real 13,036-node store (via shipped-`elc` pass-through — no uncapped fold). Commits `5336cfe`, `85eee42`.
- Reasoning layer (analogy / induction / abduction / causal / planning) — all five **done-with-proof**, 33/33 closed-form checks, ASan/UBSan clean, 0 leaks. Commit `a3358df`. - Reasoning layer (analogy / induction / abduction / causal / planning) — all five **done-with-proof**, 33/33 closed-form checks, ASan/UBSan clean, 0 leaks. Commit `a3358df`.
- Verifier layer (grounding + consistency) — proven, 29/29 checks. **Catches the plausible lie**: a claim grounded in real vocabulary yet polarity-inverted passes grounding, caught **only** by consistency (complementary checks) — directly flags the reassurance→accusation inversion. Commit `ca13471`. - Verifier layer (grounding + consistency) — proven, 29/29 checks. **Catches the plausible lie**: a claim grounded in real vocabulary yet polarity-inverted passes grounding, caught **only** by consistency (complementary checks) — directly flags the reassurance→accusation inversion. Commit `ca13471`.
> **Note added 2026-08-16 (session records are not amended; this is a pointer, not a correction).** The
> "grounding" *tier* named here is superseded — see `docs/architecture/06-cognitive-architecture.md` §12.1:
> grounding is not a verifier tier computed on demand, it **is** the edge weight, and the polarity the
> consistency tier catches is a **dimension of that weight** (signed: near-zero = no support, negative =
> actively contradicts), not a separate check bolted beside it. The 29/29 result stands as what was measured
> on 2026-08-13; the architecture it was measured against has since been superseded.
- el-exposure of the variadic/point-input reasoning + verifier modes deferred (would need ABI changes risking an uncapped fold); C layer complete + proven. - el-exposure of the variadic/point-input reasoning + verifier modes deferred (would need ABI changes risking an uncapped fold); C layer complete + proven.
### Whitepaper ### Whitepaper
+43
View File
@@ -7,6 +7,49 @@ speak MCP to Claude Code. Will's personal automations (catalyst, telegram,
vessels, studio, self-review, world-integrator, council, compressor, snapshots, vessels, studio, self-review, world-integrator, council, compressor, snapshots,
act-runner, …) are **deliberately excluded**. act-runner, …) are **deliberately excluded**.
> ## ⚠ Six of those "personal automations" are one missing subsystem — 2026-08-16
>
> Authority: `foundation/el/lang/spec/correspondence-and-censorship.md` §7 (branch
> `design/correspondence-and-censorship`), transcribed with the full measured inventory in
> `docs/architecture/06-cognitive-architecture.md` §12.4.
>
> The exclusion above and the fuller list further down are **correct as a packaging decision** — a fresh dev
> does not want Will's laptop's automations. But they are also a **census of a fragmentation**, and it should
> not be read as a list of unrelated conveniences. Consolidation had no owner, so it was implemented at every
> site that needed a piece of it. **Every name in the set is a consolidation verb** — compress, cultivate,
> digest, integrate, review, reify, beat.
>
> Measured 2026-08-16 from `~/Library/LaunchAgents`:
>
> | agent | what it runs | when | language | is it consolidation? |
> |---|---|---|---|---|
> | `ai.neuron.compressor` | `council/compressor_service.py --port 7772` | `KeepAlive`, resident | **Python, outside el** | **yes** |
> | `ai.neuron.council` | `council/council_service.py --port 7771` | `KeepAlive`, resident | **Python, outside el** | **yes** (and a write-refusal — see `council/README.md`) |
> | `ai.neuron.cultivation-digest` | `tools/cultivation-digest.sh` | **23:55** | shell | **yes** |
> | `ai.neuron.world-integrator` | `products/world-ingestor/integrator/run.py` | **06:00** | **Python, outside el** | **yes** |
> | `ai.neuron.self-review` | `~/.neuron/bin/self-review-launch.sh` | **08:30** | shell → CLI | **yes** |
> | `ai.neuron.engram-tick` | pokes `POST /api/tick` via `~/.neuron/bin/engram-tick.sh` | `StartInterval = 600` | shell | **yes** |
> | `ai.neuron.engram-backup` | `~/.neuron/bin/engram-backup.sh` | `StartInterval = 3600` | shell | no — **ops/backup** |
> | `ai.neuron.snapshot-backup` | `~/.neuron/bin/snapshot-backup.sh` | `StartInterval = 900` | shell | no — **ops/backup** |
> | `ai.neuron.act-runner-watchdog` | `act-runner-watchdog.sh` | `StartInterval = 120` | shell | no — **ops/CI** |
>
> **The last three times — 23:55, 06:00, 08:30 — are a sleep cycle implemented as launchd
> `StartCalendarInterval` entries.** Someone understood it was consolidation and expressed it as three
> unrelated scheduled scripts in three languages, none aware of each other. Three of the six run in **Python,
> outside el**, so part of Neuron's consolidation does not run on his own substrate and cannot touch the
> geometry at all.
>
> **Consolidation is ambient, not scheduled. A brain has no cron job.** *(Precisely: it is not cron either —
> `crontab -l` has **zero** neuron entries. Every neuron schedule here is launchd.)* **The presence of a
> ticker is the diagnostic:** every `StartInterval`, every `Hour`/`Minute`, every POST-to-beat marks a place
> where an intrinsic rhythm was replaced by an external clock. The one fragment with the **correct** shape is
> `soul.el:731`'s continuous in-process `awareness_run()` loop, which is inside the core stack this repo does
> install — and it is the shape the six above fold *into*.
>
> **Nothing here changes what this repo installs.** The core stack stays four services. The note exists so the
> exclusion list is not mistaken for a statement that these six are optional extras rather than one subsystem
> that never got built.
``` ```
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐
│ soul :7770 │ ─────► │ engram :8742 │ the mind ──► its memory substrate │ soul :7770 │ ─────► │ engram :8742 │ the mind ──► its memory substrate
+43 -13
View File
@@ -584,17 +584,35 @@ println("[soul] boot - cgi=" + soul_cgi_id + " port=" + int_to_str(port))
let using_http_engram: Bool = !str_eq(engram_url_raw, "") let using_http_engram: Bool = !str_eq(engram_url_raw, "")
// Always try local snapshot first. If it has content (>50 nodes) it was // THE ENGRAM IS THE CANONICAL STORE. The soul's resident graph is a working
// previously seeded from HTTP Engram and is kept up-to-date by the awareness // copy of it, never a rival source of truth.
// loop use it. This preserves sessions and memories across restarts. //
// HTTP Engram is only used for the very first boot (empty/absent snapshot). // This used to be inverted: "always try local snapshot first... HTTP Engram is
engram_load(snapshot) // only used for the very first boot." The copy outranked the store. Everything
let local_node_count: Int = engram_node_count() // that followed is a cost of that one inversion:
let snapshot_usable: Bool = local_node_count > 50 // - the two graphs drifted (13,479 nodes/74,563 edges in the soul vs
// 13,425/37,658 in the engram nearly 2x the edges, silently)
if using_http_engram && !snapshot_usable { // - write-through exists solely to reconcile them, and had never once run
// First boot or empty/corrupt snapshot: seed from HTTP Engram. // - /api/graph/edges serialized 128 MB to answer a read, because the soul's
println("[soul] engram -> HTTP " + engram_url_raw + " (no local snapshot, first boot)") // copy was not the engram's
// - a read route overwrote the engram's canonical snapshot.json with the
// soul's divergent copy
// - three copies of the same memory: neuron.egm, snapshot.json, soul RAM
// None of those are features. They are all reconciliation debt.
//
// The engram itself already reached this conclusion for its own boot path:
// "the durable owner is the paged store (neuron.egm + neuron.wal) ...
// snapshot.json is never read again as the ongoing store. This closes the
// 'restart reverted to a 17h-old snapshot' data-loss window." The soul kept
// booting the legacy way the engram had already abandoned, and inherited
// exactly the data-loss window that comment describes.
//
// So in HTTP-engram mode the soul seeds from the engram, EVERY boot, and never
// consults or writes a local snapshot. The local file is not read even when
// present a stale copy that outranks the store is the bug, not a fallback.
// (File mode, no ENGRAM_URL, is unchanged: there the soul IS the owner.)
if using_http_engram {
println("[soul] engram -> HTTP " + engram_url_raw + " (canonical store; local snapshot ignored)")
let nodes_json: String = http_get(engram_url_raw + "/api/nodes?limit=10000") let nodes_json: String = http_get(engram_url_raw + "/api/nodes?limit=10000")
let edges_json: String = http_get(engram_url_raw + "/api/edges") let edges_json: String = http_get(engram_url_raw + "/api/edges")
let nodes_part: String = if str_eq(nodes_json, "") { "[]" } else { nodes_json } let nodes_part: String = if str_eq(nodes_json, "") { "[]" } else { nodes_json }
@@ -603,9 +621,21 @@ if using_http_engram && !snapshot_usable {
let tmp_path: String = "/tmp/soul-engram-" + soul_cgi_id + ".json" let tmp_path: String = "/tmp/soul-engram-" + soul_cgi_id + ".json"
fs_write(tmp_path, snapshot_data) fs_write(tmp_path, snapshot_data)
engram_load(tmp_path) engram_load(tmp_path)
println("[soul] loaded from HTTP Engram - nodes=" + int_to_str(engram_node_count()) + " edges=" + int_to_str(engram_edge_count())) let seeded: Int = engram_node_count()
if seeded < 50 {
// Refuse to run blind. An empty seed in HTTP mode means the canonical
// store was unreachable or empty; continuing would let the soul rebuild
// a divergent graph from nothing, which is how the copies split before.
println("[soul] FATAL: engram at " + engram_url_raw + " returned " + int_to_str(seeded)
+ " nodes. The canonical store is unreachable or empty; refusing to boot on a"
+ " local copy. Fix the engram, then restart.")
exit_program(1)
}
println("[soul] loaded from engram - nodes=" + int_to_str(seeded) + " edges=" + int_to_str(engram_edge_count()))
} else { } else {
println("[soul] loaded from local snapshot - nodes=" + int_to_str(local_node_count) + " edges=" + int_to_str(engram_edge_count())) engram_load(snapshot)
println("[soul] file mode (no ENGRAM_URL) - soul owns the store - nodes="
+ int_to_str(engram_node_count()) + " edges=" + int_to_str(engram_edge_count()))
} }
load_identity_context() load_identity_context()