Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,35 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).

## [Unreleased]

### Added — Locus Coeruleus Phase 1 (schema + read+CRUD tools)

Adds the LC norepinephrine-readiness layer that the brain-region
coverage audit had flagged as missing: a concrete place for surprise,
novelty, and explicit alert events to become phasic LC activations
before Phase 2 wires them into `bg_modulators.lc_ne`.

- **Migration 067** — `lc_triggers`, `lc_firings`, and `lc_state`.
The trigger catalog is seeded with cerebellum high prediction error,
BG large TD error, novel entity sighting, and explicit user alert
rows. `lc_state` is a single broadcast row seeded to `tonic_mid`
with `ne_reservoir=0.5`. Indexes cover recent firings, agent
history, trigger history, and source-table trigger lookup.

- **`agentmemory.mcp_tools_locus_coeruleus`** — five Phase 1 tools:
`lc_status`, `lc_fire`, `lc_register_trigger`, `lc_signal_history`,
and `lc_set_mode`. `lc_status` reads the existing
`bg_modulators.lc_ne` dial when present, but no LC tool writes that
BG modulator in Phase 1.

- **Docs/tests** — proposal at `docs/proposals/locus_coeruleus.md`,
MCP category entry, coverage-tracker update, and focused pytest
coverage for migration seeds, empty status, idempotent trigger
registration, manual firing, mode validation, and history filters.

Phase 2 remains explicitly out of scope: no cerebellum/BG/novelty
auto-fire hookpoints and no NE broadcast writes to `bg_modulators.lc_ne`
land in this change.

### Added — issue #116 Phase 1-A: retrieval pathway log

External architecture memo (issue #116, "Thalamus, Basal Ganglia, and
Expand Down
3 changes: 2 additions & 1 deletion MCP_SERVER.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ docker run -v ~/.agentmemory:/data -e BRAIN_DB=/data/brain.db brainctl
The `CMD` defaults to `brainctl-mcp`, so the container runs the MCP
server over stdio.

## Available Tools (260)
## Available Tools (265)

| Tool | Description |
|------|-------------|
Expand Down Expand Up @@ -155,6 +155,7 @@ server over stdio.
| Affect | `affect_classify`, `affect_log`, `affect_check`, `affect_monitor` | Emotional state tracking |
| Thalamus (Phase 1+2, shadow gate) | `thalamus_status`, `thalamus_salience`, `thalamus_relay_create`, `thalamus_gate_set`, `thalamus_burst`, `thalamus_mode_set`, `thalamus_shadow_stats` | Typed routing layer + integrated salience scoring + shadow-mode gate consult on every W(m) write (see `docs/proposals/thalamus.md`) |
| Basal Ganglia (Phase 1+2+3 + holds + cascade) | `bg_status`, `bg_action_register`, `bg_modulator_set`, `bg_td_emit`, `bg_shadow_stats`, `bg_sweep_traces`, `bg_weights_show`, `bg_hold_trigger`, `bg_hold_release`, `bg_holds_active` | Five parallel loops + opponent Go/NoGo learning from real outcomes (three-factor rule) + dispatch shadow + outcome→δ wired into `outcome_annotate` + hyperdirect holds + cascade to thalamus (see `docs/proposals/basal_ganglia.md`) |
| Locus Coeruleus (Phase 1, NE readiness) | `lc_status`, `lc_fire`, `lc_register_trigger`, `lc_signal_history`, `lc_set_mode` | Surprise / novelty trigger catalog + LC activation log + single-row tonic/phasic state. Reads `bg_modulators.lc_ne`; Phase 2 will write it from cerebellum/BG/novelty events (see `docs/proposals/locus_coeruleus.md`) |
| Cerebellum (Phase 1+2+3, predict/observe + auto-wire) | `cerebellum_status`, `cerebellum_module_register`, `cerebellum_predict`, `cerebellum_observe` | Forward-model layer per cortical partner (motor/oculomotor/dlpfc/lofc/acc) × 3 prediction kinds. Marr-Albus sparse expansion + supervised LTD update. Boundary markers fire on \|δ_forward\|≥0.5 → workspace broadcasts + BG TD-error bus. Auto-wired into MCP dispatch. Confidence → thalamus salience precision (see `docs/proposals/cerebellum.md`) |
| Amygdala (Phase 1, valence tagging) | `amygdala_status`, `amygdala_tag`, `amygdala_query_valence`, `amygdala_extinguish` | Rapid one-shot valence/threat tagging per entity/agent/context. Saturating tanh update caps single-event movement at ±0.5 (anti-PTSD). Reconsolidation: query opens 1h labile window where next tag uses 4× learning rate. Extinction = context-keyed inhibitory overlay (ITC-analog), not erasure (see `docs/proposals/amygdala.md`) |
| Hippocampal subfields (Phase 1, DG/CA3 audit) | `hippocampus_dg_separate`, `hippocampus_dg_check`, `hippocampus_ca3_complete`, `hippocampus_subfields_status` | DG pattern-separation at write time + CA3 pattern-completion at retrieval, audit-only in Phase 1. Decisions: deduplicate (sim≥0.97), separate (sim≥0.85), passthrough (sim<0.85) |
Expand Down
87 changes: 87 additions & 0 deletions db/migrations/067_locus_coeruleus.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
-- Migration 067: locus coeruleus subsystem — Phase 1 schema
--
-- Implements Phase 1 of the LC proposal at
-- docs/proposals/locus_coeruleus.md. LC is the global surprise /
-- norepinephrine-readiness broadcaster that sits between prediction-error
-- sources (cerebellum, BG, novelty events) and the downstream
-- bg_modulators.lc_ne dial.
--
-- Phase 1 is inspection-only / additive: schema + read/CRUD tools.
-- No dispatch behavior changes. No writes to bg_modulators.lc_ne happen
-- in this phase; Phase 2 owns shadow wiring and NE broadcast.
--
-- Five biological invariants encoded here:
-- 1. Phasic and tonic-shift firing modes are explicit event classes.
-- 2. LC state is a single broadcast row, not per-agent private state.
-- 3. Trigger taxonomy separates prediction error, TD error, novelty,
-- and explicit alert sources.
-- 4. Norepinephrine delta is recorded as a gain budget, not content.
-- 5. Thresholds stay data-driven and seedable for later calibration.
--
-- Rollback, if needed before live adoption:
-- BEGIN;
-- DROP TABLE IF EXISTS lc_firings;
-- DROP TABLE IF EXISTS lc_state;
-- DROP TABLE IF EXISTS lc_triggers;
-- DELETE FROM schema_version WHERE version = 67;
-- COMMIT;
--
-- IDEMPOTENT: IF NOT EXISTS guards object creation; seed rows use
-- INSERT OR IGNORE so repeated application does not duplicate state.

CREATE TABLE IF NOT EXISTS lc_triggers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
source_table TEXT NOT NULL CHECK(source_table IN ('cerebellum_predictions','bg_td_events','memory_events','other')),
threshold_field TEXT,
threshold_value REAL,
default_ne_delta REAL NOT NULL DEFAULT 0.0,
description TEXT,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now'))
);
CREATE INDEX IF NOT EXISTS idx_lc_triggers_source_table ON lc_triggers(source_table);

CREATE TABLE IF NOT EXISTS lc_firings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
fired_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now')),
agent_id TEXT,
trigger_id INTEGER,
trigger_source_event_id INTEGER,
surprise_magnitude REAL NOT NULL DEFAULT 0.0,
ne_delta_applied REAL NOT NULL DEFAULT 0.0,
mode TEXT NOT NULL CHECK(mode IN ('phasic','tonic_shift')),
context_hash TEXT,
notes TEXT,
FOREIGN KEY (trigger_id) REFERENCES lc_triggers(id) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS idx_lc_firings_fired_at ON lc_firings(fired_at DESC);
CREATE INDEX IF NOT EXISTS idx_lc_firings_agent_fired ON lc_firings(agent_id, fired_at);
CREATE INDEX IF NOT EXISTS idx_lc_firings_trigger_fired ON lc_firings(trigger_id, fired_at);

CREATE TABLE IF NOT EXISTS lc_state (
id INTEGER PRIMARY KEY CHECK (id = 1),
mode TEXT NOT NULL CHECK(mode IN ('phasic_ready','tonic_high','tonic_mid','tonic_low')),
ne_reservoir REAL NOT NULL DEFAULT 0.5,
last_phasic_at TEXT,
last_tonic_shift_at TEXT,
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now'))
);

INSERT OR IGNORE INTO lc_triggers
(name, source_table, threshold_field, threshold_value, default_ne_delta, description)
VALUES
('cerebellum_high_pe', 'cerebellum_predictions', 'delta_forward', 0.5, 0.15,
'Cerebellum prediction error above threshold; surprise source for phasic LC.'),
('bg_large_td_error', 'bg_td_events', 'delta', 0.6, 0.10,
'Basal-ganglia TD error above threshold; value surprise source for LC.'),
('novel_entity_sighting', 'memory_events', 'event_type', NULL, 0.05,
'Novel observation event, especially new entity sightings.'),
('explicit_user_alert', 'other', NULL, NULL, 0.20,
'Manual or user-declared alert that should raise global NE readiness.');

INSERT OR IGNORE INTO lc_state (id, mode, ne_reservoir)
VALUES (1, 'tonic_mid', 0.5);

INSERT OR IGNORE INTO schema_version (version, description, applied_at)
VALUES (67, 'locus coeruleus Phase 1: triggers, firings, single-row LC state',
strftime('%Y-%m-%dT%H:%M:%S', 'now'));
2 changes: 1 addition & 1 deletion docs/proposals/brain_region_coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ Verdict per region: ✅ well-modelled · 🟡 partial / under-wired · 🟥 miss
| **Theory-of-Mind / TPJ-mPFC** | model other minds | `mcp_tools_tom.py`, perspective tables, belief_conflicts |
| **Belief system / dlPFC inference** | hold and revise probabilistic beliefs | `belief_*` tools, AGM-style credibility-weighted merge |
| **Reflexion / posterior parietal lesson-learning** | failure-driven self-correction | `reflexion_*` tools, CONTEXT_LOSS / HALLUCINATION / TOOL_MISUSE categories |
| **Locus Coeruleus (NE) — Phase 1** | global surprise / reset signal, tonic/phasic norepinephrine readiness | `lc_triggers`, `lc_firings`, `lc_state`, and `lc_*` MCP tools. Phase 1 is manual/read+CRUD; automatic cerebellum/BG/novelty wiring is Phase 2. |

## 🟡 Partial — substrate exists but not wired or only one half present

| Region | What it does (bio) | brainctl state | Gap |
|---|---|---|---|
| **Brainstem / Ascending Reticular Activating System** | global arousal broadcast via diffuse fan-out | `neuromodulation_state` table holds org-level arousal/focus | Not wired into retrieval/admission. The proposed thalamus mode-broadcast layer is the missing fan-out. |
| **Locus Coeruleus (NE)** | global surprise / reset signal | `neurostate.norepinephrine` in proposed schema | No concrete LC-analog signal currently *fires* on prediction-error to reset attention. |
| **Nucleus Basalis (ACh)** | broaden receptive fields, raise responsiveness | Same — `neurostate.acetylcholine` proposed, not yet emitting | No actual cholinergic-mode admission-loosening tied to attended sectors. |
| **Hypothalamus / allostasis** | homeostatic set-points + drives | `mcp_tools_allostatic.py` — demand_forecast, allostatic_prime | Has *prediction*; has no set-points (need-states) that *generate drives*. The system can't "feel hungry for data" or "need consolidation." |
| **Amygdala** | rapid valence tagging, fear conditioning, one-shot threat learning | `affect_*` tools classify valence/arousal lexically | Affect is a classifier, not a memory modulator. No "this kind of input previously caused a problem → preemptively bias suppression on that channel" loop. No fast-track fear learning that bypasses W(m). |
Expand Down
131 changes: 131 additions & 0 deletions docs/proposals/locus_coeruleus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Proposal: The Locus Coeruleus Subsystem for brainctl

**Status:** Design proposal, Phase 1 implemented as schema + read/CRUD tools.
**Authors:** Codex GPT-5 (implementation synthesis) following the brain-region subsystem pattern.
**Date:** 2026-05-20
**Scope:** New subsystem; additive and inspection-only in Phase 1. No dispatch, retrieval, write-gate, or neuromodulator behavior changes.

---

## TL;DR

brainctl already has two high-quality surprise sources: cerebellum prediction errors (`cerebellum_predictions.delta_forward`) and basal-ganglia TD errors (`bg_td_events.delta`). What it lacked was the small brainstem broadcaster that turns surprise into a global norepinephrine readiness signal. The locus coeruleus (LC) supplies that layer: a trigger catalog, an activation log, and a single current-state row that records whether the system is phasic-ready, tonically high, tonically mid, or tonically low.

Architecturally, LC sits between fast error detectors and the existing `bg_modulators.lc_ne` dial. Phase 1 only observes and records; Phase 2 will wire cerebellum/BG/novelty events into LC firing and then broadcast norepinephrine into `bg_modulators.lc_ne`.

```
cerebellum_predictions.delta_forward
bg_td_events.delta
memory_events novelty / observation
explicit user alert
|
v
locus_coeruleus
- lc_triggers
- lc_firings
- lc_state
|
v
bg_modulators.lc_ne (Phase 2 write target; Phase 1 reads only)
```

---

## Convergent Principles

1. **Two firing modes, two control problems.** LC phasic bursts are brief, stimulus-locked gain increases; tonic level is the slower arousal background. brainctl models both separately: `lc_firings.mode` captures phasic versus tonic-shift events, while `lc_state.mode` captures the current operating regime.

2. **P3-like "something changed" signal.** LC tracks the orienting response to salient, novel, or unexpected stimuli. In brainctl, that maps to prediction errors, TD errors, novel entity observations, and explicit user alerts.

3. **Aston-Jones adaptive gain.** Mid tonic plus phasic bursts supports exploitation and focused task performance; high tonic favors exploration and labile attention; low tonic maps to drowsy disengagement. LC state therefore uses `tonic_low`, `tonic_mid`, `tonic_high`, and `phasic_ready`.

4. **Norepinephrine gates plasticity.** LC-NE does not encode content. It adjusts gain and learning readiness, including LTP/LTD sensitivity in downstream circuits. In brainctl, that downstream dial is already present as `bg_modulators.lc_ne`; LC owns the event semantics that will eventually set it.

5. **Trigger taxonomy matters.** "Surprise" is not one source. Phase 1 separates cerebellar prediction error, BG TD error, novelty/observation events, and explicit user alerts so Phase 2 can tune thresholds and default NE deltas independently.

---

## Architectural Placement

LC is an interrupt-style broadcaster, not a selector. Cerebellum and BG detect error in their own domains; LC decides whether the error is behaviorally salient enough to raise global gain.

```
fast prediction / value errors
|
+------------------+------------------+
| |
v v
cerebellum_predictions bg_td_events
delta_forward delta
| |
+------------------+------------------+
|
v
lc_triggers catalog
threshold + NE delta
|
v
lc_firings log
|
v
lc_state row
|
v
bg_modulators.lc_ne
Phase 2 writes; Phase 1 status reads only
```

The LC subsystem deliberately stays out of the current `mcp_server.py` shadow hookpoints. Phase 1 exposes manual firing and inspection tools so operators can verify schema shape and semantics before automatic wiring.

---

## Phase 1 Schema

Migration `067_locus_coeruleus.sql` adds three tables:

- **`lc_triggers`** - seedable trigger catalog. Each row defines an event class, its source table, threshold field/value, default NE delta, and description.
- **`lc_firings`** - timestamped activation log. Each row records agent, trigger, source event id, surprise magnitude, NE delta that would be applied, firing mode, context hash, and notes.
- **`lc_state`** - single-row current LC mode and NE reservoir, seeded as `id=1`, `mode='tonic_mid'`, `ne_reservoir=0.5`.

Seed triggers:

| Trigger | Source | Field | Threshold | Default NE delta |
|---|---|---|---:|---:|
| `cerebellum_high_pe` | `cerebellum_predictions` | `delta_forward` | 0.5 | 0.15 |
| `bg_large_td_error` | `bg_td_events` | `delta` | 0.6 | 0.10 |
| `novel_entity_sighting` | `memory_events` | `event_type` | null | 0.05 |
| `explicit_user_alert` | `other` | null | null | 0.20 |

Indexes support recent-status reads, agent-specific history, trigger-specific history, and source-table trigger lookup.

---

## Phase 1 MCP Tool Surface

Five tools ship under the `lc_*` namespace:

- **`lc_status(agent_id=None) -> dict`** - returns `lc_state`, current `bg_modulators.lc_ne` if present, and a last-24h firing summary.
- **`lc_fire(trigger_name, surprise_magnitude, agent_id=None, source_event_id=None, notes=None) -> dict`** - manually logs a phasic LC firing by trigger name. Phase 1 updates LC's own state and log only; it does not write `bg_modulators.lc_ne`.
- **`lc_register_trigger(name, source_table, threshold_field, threshold_value, default_ne_delta, description) -> dict`** - idempotent trigger UPSERT. Source table is validated against the Phase 1 taxonomy.
- **`lc_signal_history(limit=20, since=None, agent_id=None, trigger_id=None) -> list[dict]`** - recent firing history with optional filters and pagination limit.
- **`lc_set_mode(mode, reason=None) -> dict`** - validates and updates `lc_state.mode`. Used by future shadow consults and manual inspection.

---

## Phase 2/3/4 Sketch

**Phase 2 - Shadow wiring.** Listen to cerebellum `delta_forward`, BG `delta`, novel observation events, and explicit alert events. Insert `lc_firings` automatically when trigger thresholds pass. Mirror the computed NE delta into `bg_modulators.lc_ne` in shadow mode with audit records and no behavior change.

**Phase 3 - Gain coupling.** Use LC-NE as a read-path and write-path gain signal: broader retrieval under high tonic NE, lower admission thresholds for surprising sources, and higher salience precision for LC-tagged sectors.

**Phase 4 - Calibration and enforcement.** Learn trigger thresholds and NE deltas from downstream outcomes. Couple LC mode to BG action selection and thalamus salience after enough shadow data accumulates.

---

## DoD for Phase 1

- Migration `067_locus_coeruleus.sql` applies idempotently to a fresh DB, a `/tmp` copy of live `brain.db`, and live `brain.db` after backup.
- Seed triggers and the single `lc_state` row exist after migration.
- The five `lc_*` MCP tools are registered and discoverable from `agentmemory.mcp_server`.
- Focused pytest coverage verifies migration seeds, empty status, idempotent trigger registration, firing round-trip, mode validation, and history filtering.
- `MCP_SERVER.md`, `CHANGELOG.md`, and `brain_region_coverage.md` document LC Phase 1 without touching NB-owned files or Phase 2 hookpoints.
11 changes: 11 additions & 0 deletions research/codex-track-reports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Codex track reports — auto-appended

## 2026-05-20 — Locus Coeruleus Phase 1

- Branch: `brain-regions-lc-phase-1`
- PR: https://github.com/TSchonleber/brainctl/pull/121
- Commit: `eca4590` (`locus coeruleus Phase 1: schema + read/CRUD tools`)
- Scope shipped: `067_locus_coeruleus.sql`, LC proposal, `mcp_tools_locus_coeruleus.py`, MCP registration, focused tests, MCP docs, coverage tracker, changelog, and init-schema parity for 066/067.
- Live DB: backed up to `/Users/r4vager/agentmemory/backups/brain.db.pre-lc-20260520T033749Z.db`; migration 067 applied live; `lc_triggers` has 4 seed rows; `lc_state` is `tonic_mid`; `bg_modulators.lc_ne` remained `0.5`.
- Verification: `/tmp` migration copy applied cleanly; `python3 -m pytest tests/test_mcp_tools_locus_coeruleus.py -x` passed; exact `_build_dispatch()` LC discoverability command returned all 5 tools; clean LC-only worktree full suite passed with `2249 passed, 28 skipped, 2 xfailed`.
- Coordination note: the shared checkout contains untracked NB files from Claude's parallel branch; none were staged or committed here.
Loading