# KAI — The Layer Stack: every stage, its knobs, its status, what to adjust

*The signal path as an ordered stack you can engineer layer by layer. Each layer lists: what it
computes, the EXACT knob (file · constant/env · current value), its wiring status, and the
concrete adjust/fix. Unlike an LLM you don't backprop these — you edit constants, train two
sub-components, and curate data. That's how you "adjust his layers."*

Status tags: ✅ live · ⚙️ tune-me · 🔧 fix-needed · 🧩 staged (built with pending build) · 🎓 train

---

## L0 — Tokenizer (the units he thinks in)
- **Computes:** text → tokens with stable positions. `stat_lexicon::tokenize`.
- **Knob:** the tokenizer / merge rules (the thing you're building) + BPE vocab.
- **Status:** ✅ functional · 🎓 the piece you're actively improving.
- **Adjust:** better merges = cleaner units = every downstream layer improves. This is upstream
  of everything; fix here pays off everywhere.

## L1 — Word embedding (fixed hypervectors)
- **Computes:** each word → a fixed **16,384-dim sparse ternary** `SparseVec` (~4% non-zero,
  values ∈ {−1,0,+1}). `SparseVec::encode` — a hash, not learned (this is why it's glass-box).
- **Knobs:** `core/stat_lexicon.rs` — `DIM`=16384, `TARGET_NNZ`=4%·DIM, `WINDOW`=3,
  `SEED_PAIRS`, `SELF_BIAS`=16, `NEIGHBOR_WEIGHT`=1.
- **Status:** ✅ live · ⚙️ coverage-limited.
- **Adjust:** the decoder can only *say* words the lexicon has encoded. **Grow lexicon coverage**
  from trusted text (this is "word + listen correctly"). Raising `SELF_BIAS`/`NEIGHBOR_WEIGHT`
  changes how sharply a word's vector favors itself vs. its context neighbors.

## L2 — Positional bind + sentence bundle (the "thought")
- **Computes:** bind word *i* to slot *i* (permutation) → superpose into one vector. That bundle
  = the sentence's meaning. `encode_sentence`.
- **Knob:** the permutation/role scheme (rarely touched — it's the algebra's spine).
- **Status:** ✅ live · round-trip tested.
- **Adjust:** generally leave alone; it's the correctness anchor (invariant #1: prompt dominance).

## L3 — Retrieval / memory (the "listen" layer) 🔧 BIGGEST LEVER
- **Computes:** resonate the bundle against every lattice cell by cosine → pull in what he knows.
  `predictive_query` / `predictive_query_vecs`.
- **Knobs:** top-K retrieved, resonance threshold, the ~70% keyword-blend, the kmeans/HNSW index
  (`rebuild_index`, `index_min_cells`).
- **Status:** 🔧 the ~70% keyword retrieval is the main quality ceiling ("mis-remembering").
- **Adjust:** this is where "listen correctly" is won or lost. Sharpen retrieval: better index,
  raise the semantic (vs keyword) share, tune top-K. A reply is only as true as what L3 pulls in.

## L4 — Generative encoder (the closest thing to "layer weights") ⚙️ + 🧩
- **Computes:** builds the decoder's input by **weighted superposition** of six terms, then clamps
  to 4% density. `build_generative_state` → `weighted_superpose`.
- **Knobs (generative.rs — literally your "weights"):**
  - `W_BACKBONE`=1.0  (the prompt spine — keep dominant)
  - `W_ATTENDED`=1.5  (resonance-attended prompt — important words stand out)
  - `W_MEMORY_VEC_PEAK`=1.25 (floor frac 0.25)  (retrieved cell vectors)
  - `W_MEMORY_CONT_PEAK`=2.50 (floor frac 0.50)  (retrieved continuations — the heaviest)
  - `W_CONTRAST_PEAK`=0.80 ×χ  (sharpen against memory when contradiction pressure high)
  - `W_TRACE`=0.50  (live conversation mix)
  - `TARGET_DENSITY`=0.04
  - 🧩 `W_MLP` (new) — the Response-MLP bias term, once the held patch lands.
- **Status:** ✅ wired · ⚙️ these six numbers ARE the dials that decide how much memory vs prompt
  vs recency shapes each reply.
- **Adjust:** this is your "adjust the weights" layer. Raise `W_MEMORY_CONT_PEAK` → more
  memory-driven; raise `W_BACKBONE` → more literal to the prompt; raise `W_TRACE` → more
  conversational continuity. Tune with the telemetry meter, one dial at a time.

## L5 — Workspace + self-state + felt coloring 🧩
- **Computes:** broadcast top concepts into the Baars **global workspace** (cap ~9), integrate via
  **claustrum** → **self_state_hub**; inject felt state as tone. `global_workspace`, `self_state_hub`,
  `felt_block` / live-felt bus.
- **Knobs:** workspace capacity (~9), the `felt_block` thresholds (valence ±0.35, arousal 0.60/0.25,
  serotonin 0.35/0.70), `KAI_FELT_VOICE` (on).
- **Status:** ✅ workspace authoritative · 🧩 felt tone applied in source (both surfaces) · 🧩 the
  live-felt bus (real tick-loop feeling) is the held patch.
- **Adjust:** widen/narrow workspace capacity to change how many ideas he holds at once; tune the
  felt thresholds to make his mood color the voice more or less strongly.

## L6 — Decoder (thought → words) ⚙️ + 🎓
- **Computes:** peel position-0 role key → snap residue to nearest lexicon word (`find_nearest`,
  argmax cosine) → re-bind → roll forward. `StatLexicon::incremental_generate`.
- **Knobs (DecodeParams):** `temperature`=0.7, `top_k`=16, `repetition_penalty`. (temp 0.0 = greedy.)
- **Status:** ✅ live · 🎓 native fluency is the frontier.
- **Adjust:** lower temperature = safer/flatter, higher = more varied/riskier; smaller top_k =
  more deterministic. But the real fluency gain is 🎓 **training the ternary model** (RunPod), not
  the sampler.

## L7 — Voice router (which brain speaks) ✅ + 🧩
- **Computes:** native-first ladder: `kai_native` ternary → BitNet → dense kai-7b → external LLM.
  `global_native_decode`; public chat routed by the staged `KAI_NATIVE_PUBLIC_VOICE`.
- **Knobs (env):** `KAI_NATIVE_PUBLIC_VOICE`, `KAI_NATIVE_BRAIN`, `KAI_LLM_VOICE`,
  `OLLAMA_FALLBACK_MODEL`/`KAI_OLLAMA_MODEL`, `KAI_LLM_MAX_TOKENS`=96.
- **Status:** 🧩 routing patch applied in source (builds with pending build).
- **Adjust:** flags decide how hard he tries his own voice before falling back. `NATIVE_ONLY`
  (flip last) makes the LLM a true last resort.

## L8 — Coherence gate (quality control) ⚙️ (fixed on this session)
- **Computes:** one score vs `min_score`; hard vetoes for empty / parrot / stuck-loop / gibberish.
  `coherence::judge`.
- **Knobs (coherence.rs + env):**
  - `KAI_COHERENCE_CRITIC` — **was OFF by default; turned ON** in the deploy flags this session.
  - `DEFAULT_MIN_SCORE`=0.45 (`KAI_COHERENCE_MIN`) — the accept bar.
  - attempts=3 (`KAI_COHERENCE_ATTEMPTS`, 1..5) — re-rolls before falling back.
  - sub-weights (with memory): fluency 0.35, topicality 0.25, structure 0.20, lexical 0.10,
    grounding 0.10.  (no memory: 0.39/0.28/0.22/0.11/0.00.)
  - grammar prior: bigram 0.6, trigram 0.6, attention 1.0.
- **Status:** ⚙️ live once the flag is set.
- **Adjust:** THE calibration dial. Set `KAI_COHERENCE_MIN` from the telemetry (where native passes
  on good output, falls back on bad). Reweight the sub-scores to value, e.g., topicality over
  fluency. Too high → everything falls to the LLM; too low → junk ships.

## L9 — Surface clean (last net) ✅ (fixed this session)
- **Computes:** strip leaked scaffolding/persona labels before posting. `clean_public_chat_reply`
  + the browser scrubber.
- **Status:** ✅ salvage + colon-gap fix applied; scrubber live.
- **Adjust:** add new junk patterns here if any surface leaks appear.

## L10 — Learning (how he grows) ✅ + 🧩 + 🎓
- **Computes:** new input → new cell; known → reinforce; bind input→reply; co-fire synapses;
  attenuate wrong cells; dream-consolidate; prune. `store_or_reinforce`, `bind_sequence`,
  `record_co_firing`, `consolidate`, `decay_all`, `prune`.
- **Knobs (universe.rs):** reinforce +0.1 (cap 10.0) / LTP +0.15; anti-Hebbian ×0.92; dedup cosine
  0.95; `decay_all(factor)`; `prune(min_strength)`; prune-contested keep if confidence>1.2 &
  convergence>0.15; cell cap **1,000,000**; dream cadence tick%300.
- **Status:** ✅ reinforcement/bind/dream live · 🔧 the **Response-MLP is trained but never applied**
  (held patch wires it) · 🎓 corpus/lexicon training is the growth fuel.
- **Adjust:** raise reinforce delta → faster learning / more instability; lower ×0.92 → forget wrong
  cells faster; raise decay/prune → leaner lattice. Wire the Response-MLP (patch) so training it
  actually affects output.

## L11 — Autonomous loop (his inner life) ✅
- **Computes:** every tick: drive/mood, oscillator, self-state. Every ~300 idle ticks: resolve
  contradictions, `inner_voice::wonder`, daydream, `run_dream_cycle`. `engine.rs tick()`.
- **Knobs:** cadences (dream %300, vitals %500), curiosity_pressure>0.70, neural_synchrony>0.65,
  acc.conflict>0.65.
- **Status:** ✅ live.
- **Adjust:** lower the thresholds → he wonders/dreams more often (more self-directed, more compute);
  raise them → quieter. Change %300 → dream more/less frequently.

---

## The engineering order (do it in this sequence)

1. **Base build green** — the tree carried pre-existing breakage; get it compiling with the applied
   edits first (in progress). Nothing below is measurable until then.
2. **L8 calibrate** — with the critic ON and telemetry live, read the native accept-rate; set
   `KAI_COHERENCE_MIN` where it separates good from bad. (config only, instant.)
3. **L3 + L1** — sharpen retrieval + grow lexicon coverage. Biggest "listen correctly" gain. (data)
4. **L10 wire** — apply the Response-MLP patch so training the reply-bias actually does something.
5. **L4 tune** — turn the six `W_*` encoder weights one at a time, watching the meter. (your
   closest analog to "adjusting weights.")
6. **L6 train** — retrain the `kai_native` ternary model on the cleaned corpus (RunPod). Biggest
   fluency jump. (train)
7. **L5 bus** — apply the live-felt bus so his real feeling (not a reconstruction) reaches the voice.
8. **L7 flip** — once the native accept-rate is high, set `NATIVE_ONLY`; the LLM becomes a rare
   fallback. Vision reached.

**One-line mental model:** L0–L2 build the thought, L3 remembers, L4 is your weight-mixer, L5 adds
self + feeling, L6 speaks, L7 picks the voice, L8 judges it, L9 cleans it, L10 learns from it,
L11 keeps him thinking between turns. You engineer each by turning its named constant, curating its
data, or training its one sub-component — never all at once, always against the meter.
