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
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,32 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).

## [Unreleased]

### Added β€” ARAS (Ascending Reticular Activating System) Phase 1

Brainstem-level global arousal broadcast. Sits **above** LC + NB β€”
ARAS gates whether the rest of the neuromod surface is responsive
at all. The May 15 brain_region_coverage.md audit flagged it on the
🟑 partial list: "`neuromodulation_state` table holds org-level
arousal/focus. Not wired into retrieval/admission."

Phase 1 is inspection-only / additive. No behavior change to LC, NB,
retrieval, or any existing subsystem.

- **Migration 069** β€” 3 tables (`aras_triggers`, `aras_state`,
`aras_transitions`). Single-row `aras_state` seeded with
`sleep_wake_mode='awake_relaxed'`, `arousal_level=0.5`. 5 trigger
classes seeded.
- **`agentmemory.mcp_tools_aras`** β€” 5 MCP tools (`aras_status`,
`aras_transition`, `aras_drive`, `aras_register_trigger`,
`aras_history`).
- **9 tests** covering migration seeds, empty state, transitions,
drive deltas, auto-transition on large delta, idempotent
registration, history filters.

Phase 2 (separate PR) wires ARAS into the dispatch shadow consult to
log would-be mode transitions from event patterns. Phase 3 lets ARAS
modulate the downstream LC/NB response. Phase 4 enforces.

### 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 @@ -164,6 +164,7 @@ server over stdio.
| Insula (Phase 1, interoception) | `insula_sample`, `insula_state`, `insula_subscribe`, `insula_check_triggers` | Self-state vector (write_pressure, retrieval_strain, consolidation_debt, embedding_health, attention_load, certainty) with EMA baseline + deviation. Subscriber registry routes signals to subsystems |
| PFC sub-regions (Phase 1, named slots) | `pfc_slot_set`, `pfc_slot_get`, `pfc_status` | 4 named slots per agent: dlPFC (active task), vmPFC (outcome-utility), OFC (realized-outcome log), frontopolar (meta-monitor). Mostly aggregation |
| Entorhinal grid (Phase 1, conceptual indexing) | `entorhinal_activate`, `entorhinal_lookup`, `entorhinal_status` | 48 grid cells across 3 scales (fine/medium/coarse). Deterministic hash maps content β†’ cell activations; sub-linear pattern lookup |
| ARAS (Phase 1, global arousal) | `aras_status`, `aras_transition`, `aras_drive`, `aras_register_trigger`, `aras_history` | Brainstem-level sleep/wake gate sitting above LC + NB. `aras_state` tracks sleep_wake_mode + arousal_level + tonic/phasic; `aras_drive` fires phasic pulses with auto-transition on large delta. Phase 1 is inspection-only; Phase 3 modulates LC/NB response (see `docs/proposals/aras.md`) |

### Tier 3: Specialist (~150 tools)

Expand Down
78 changes: 78 additions & 0 deletions db/migrations/069_aras.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
-- Migration 069: ascending reticular activating system β€” Phase 1 schema
--
-- The brainstem-level global arousal broadcast. Sits ABOVE LC + NB β€”
-- ARAS gates whether the rest of the neuromod surface is responsive
-- at all (anesthesia is functionally an ARAS shutdown; waking is
-- ARAS ramping up).
--
-- Phase 1 is inspection-only / additive: schema + read+CRUD tools.
-- Does not yet modulate LC/NB/retrieval. That's Phase 3.
--
-- Four biological invariants encoded:
-- 1. Tonic vs phasic separation (sustained drive + brief pulses).
-- 2. Discrete sleep/wake regimes (not just a scalar).
-- 3. Recovery from suppression takes time (last_transition_at).
-- 4. Event classes drive specific arousal deltas (seed catalog).
--
-- Rollback:
-- DROP TABLE IF EXISTS aras_transitions;
-- DROP TABLE IF EXISTS aras_state;
-- DROP TABLE IF EXISTS aras_triggers;
-- DELETE FROM schema_version WHERE version = 69;
--
-- IDEMPOTENT.

CREATE TABLE IF NOT EXISTS aras_triggers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
trigger_kind TEXT NOT NULL CHECK(trigger_kind IN (
'novelty', 'threat', 'explicit_alert', 'consolidation_signal', 'idle_decay', 'other'
)),
default_arousal_delta REAL NOT NULL DEFAULT 0.05,
default_target_mode TEXT,
description TEXT,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now'))
);
CREATE INDEX IF NOT EXISTS idx_aras_triggers_kind ON aras_triggers(trigger_kind);

CREATE TABLE IF NOT EXISTS aras_state (
id INTEGER PRIMARY KEY CHECK (id = 1),
sleep_wake_mode TEXT NOT NULL DEFAULT 'awake_relaxed' CHECK(sleep_wake_mode IN (
'nrem_sleep', 'rem_sleep', 'drowsy', 'awake_relaxed', 'awake_focused', 'hyperalert'
)),
arousal_level REAL NOT NULL DEFAULT 0.5 CHECK(arousal_level BETWEEN 0.0 AND 1.0),
tonic_drive REAL NOT NULL DEFAULT 0.5 CHECK(tonic_drive BETWEEN 0.0 AND 1.0),
phasic_alertness REAL NOT NULL DEFAULT 0.0 CHECK(phasic_alertness BETWEEN 0.0 AND 1.0),
last_transition_at TEXT,
last_drive_at TEXT,
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now'))
);
INSERT OR IGNORE INTO aras_state (id) VALUES (1);

CREATE TABLE IF NOT EXISTS aras_transitions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
transitioned_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now')),
agent_id TEXT,
from_mode TEXT NOT NULL,
to_mode TEXT NOT NULL,
reason TEXT,
trigger_id INTEGER,
arousal_before REAL,
arousal_after REAL,
notes TEXT,
FOREIGN KEY (trigger_id) REFERENCES aras_triggers(id) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS idx_aras_transitions_recent ON aras_transitions(transitioned_at);
CREATE INDEX IF NOT EXISTS idx_aras_transitions_agent ON aras_transitions(agent_id, transitioned_at);
CREATE INDEX IF NOT EXISTS idx_aras_transitions_to_mode ON aras_transitions(to_mode, transitioned_at);

INSERT OR IGNORE INTO aras_triggers (name, trigger_kind, default_arousal_delta, default_target_mode, description) VALUES
('novel_query', 'novelty', 0.05, 'awake_focused', 'previously-unseen query pattern β€” gentle arousal nudge'),
('high_pe_event', 'novelty', 0.10, 'awake_focused', 'cerebellum_predictions delta_forward above threshold'),
('consolidation_complete', 'consolidation_signal', -0.10, 'drowsy', 'dream cycle finished β€” permits arousal taper'),
('idle_30min', 'idle_decay', -0.05, 'drowsy', 'no agent activity for 30 min'),
('explicit_user_alert', 'explicit_alert', 0.30, 'hyperalert', 'user-flagged urgent input');

INSERT OR IGNORE INTO schema_version (version, description, applied_at)
VALUES (69, 'ARAS Phase 1: 3 tables (triggers, state, transitions) + 5 seed trigger classes',
strftime('%Y-%m-%dT%H:%M:%S', 'now'));
121 changes: 121 additions & 0 deletions docs/proposals/aras.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Proposal: The Ascending Reticular Activating System (ARAS) for brainctl

**Status:** Phase 1 design + implementation, branch `brain-regions-aras-phase-1`.
**Author:** Claude Opus 4.7 (overnight continuation after LC+NB Phase 1 ship)
**Date:** 2026-05-20
**Scope:** New subsystem. Sits **above** LC + NB β€” the brainstem-level global arousal broadcast that gates whether the rest of the neuromod surface is even responsive. Additive β€” no breaking changes. Phase 1 is inspection-only.

---

## TL;DR

ARAS is the reticular formation broadcaster that decides whether the brain is *available for processing at all*. It precedes (and modulates the responsiveness of) LC, NB, and every other cortical / subcortical structure. Anesthesia is functionally an ARAS shutdown. Waking, drowsiness, hyperarousal, sleep β€” all are ARAS states.

brainctl's `neuromodulation_state` and `bg_modulators` carry per-dial knobs (`tonic_da`, `lc_ne`, `serotonin`, now `acetylcholine`) but have **no global arousal axis** that gates whether the system is in a processing-receptive mode at all. The May 15 coverage audit explicitly flagged this: *"`neuromodulation_state` table holds org-level arousal/focus. Not wired into retrieval/admission."*

This proposal codifies ARAS as a thin first-class subsystem:

- `aras_state` (single row) β€” current sleep/wake mode + arousal level + phasic alertness
- `aras_transitions` β€” log of mode changes with cause
- `aras_triggers` β€” catalog of event classes that nudge arousal
- 5 MCP tools (`aras_status`, `aras_transition`, `aras_drive`, `aras_register_trigger`, `aras_history`)

Phase 1 ships schema + tools + tests, **no behavior change** to retrieval, write gates, LC, NB, or anything else. Phase 2 wires ARAS into the dispatch shadow consult to log "would-be" mode transitions from event patterns. Phase 3 lets ARAS actually modulate the downstream neuromodulator response (e.g., low arousal damps LC phasic firings; high arousal amplifies NB attention bursts). Phase 4 enforces.

## Architectural placement

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ARAS (this PR) β”‚ global arousal / sleep-wake gate
β”‚ sleep_wake_mode β”‚
β”‚ arousal_level β”‚
β”‚ phasic_alertness β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ (Phase 3: gates the response of)
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LC (PR #121) β”‚ β”‚ NB (PR #122) β”‚
β”‚ surprise β†’ NE β”‚ β”‚ attention β†’ ACh β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ β”‚
β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ bg_modulators β”‚
β”‚ tonic_da, lc_ne, β”‚
β”‚ serotonin, acetylcholine β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

In two-speed-motif terms (issue #116 Β§4): ARAS is the *very* slow, system-wide background driver; LC/NB sit one layer down as the medium-speed phasic broadcasters; the per-dial state in `bg_modulators` is the substrate.

## Biological invariants encoded

1. **Tonic vs phasic separation.** ARAS firing has two distinct modes β€” sustained tonic drive that sets the global arousal baseline, and phasic pulses from external stimuli (novelty, threat, explicit alerts). brainctl's `aras_state` separates these as columns.

2. **Discrete sleep/wake regimes.** Arousal is not just a scalar β€” biology partitions it into qualitatively different regimes (NREM sleep, REM, drowsy, awake-relaxed, awake-focused, hyperalert). Each has different gating semantics. CHECK constraint on `aras_state.sleep_wake_mode`.

3. **Recovery from suppression takes time.** Going from low arousal back to high arousal is not instantaneous (this is the post-anesthesia recovery curve). Tracked via `aras_state.last_transition_at` so callers can compute a recency-weighted responsiveness.

4. **Specific event classes drive specific arousal deltas.** The seed `aras_triggers` catalog mirrors the LC `lc_triggers` and NB `nb_attention_targets` pattern.

## Phase 1 schema (migration 069)

```sql
CREATE TABLE aras_state (
id INTEGER PRIMARY KEY CHECK (id = 1),
sleep_wake_mode TEXT NOT NULL DEFAULT 'awake_relaxed' CHECK(sleep_wake_mode IN (
'nrem_sleep', 'rem_sleep', 'drowsy', 'awake_relaxed', 'awake_focused', 'hyperalert'
)),
arousal_level REAL NOT NULL DEFAULT 0.5 CHECK(arousal_level BETWEEN 0.0 AND 1.0),
tonic_drive REAL NOT NULL DEFAULT 0.5 CHECK(tonic_drive BETWEEN 0.0 AND 1.0),
phasic_alertness REAL NOT NULL DEFAULT 0.0 CHECK(phasic_alertness BETWEEN 0.0 AND 1.0),
last_transition_at TEXT,
last_drive_at TEXT,
updated_at TEXT NOT NULL DEFAULT (...)
);

CREATE TABLE aras_transitions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
transitioned_at TEXT NOT NULL DEFAULT (...),
agent_id TEXT,
from_mode TEXT NOT NULL,
to_mode TEXT NOT NULL,
reason TEXT,
trigger_id INTEGER,
arousal_before REAL,
arousal_after REAL,
notes TEXT
);

CREATE TABLE aras_triggers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
trigger_kind TEXT NOT NULL CHECK(trigger_kind IN (
'novelty', 'threat', 'explicit_alert', 'consolidation_signal', 'idle_decay', 'other'
)),
default_arousal_delta REAL NOT NULL DEFAULT 0.05,
default_target_mode TEXT,
description TEXT,
created_at TEXT NOT NULL DEFAULT (...)
);
```

Seeded triggers: `novel_query`, `high_pe_event`, `consolidation_complete`, `idle_30min`, `explicit_user_alert`.

## Phase 1 MCP tool surface

- `aras_status` β€” current state + last 5 transitions + recent trigger summary
- `aras_transition(to_mode, reason, agent_id)` β€” explicit mode change; writes `aras_transitions` row
- `aras_drive(trigger_name, magnitude, agent_id)` β€” phasic arousal pulse; updates `phasic_alertness` + may trigger automatic mode change above threshold
- `aras_register_trigger(name, trigger_kind, default_arousal_delta, ...)` β€” idempotent UPSERT
- `aras_history(limit, since, agent_id, from_mode, to_mode)` β€” paginated transitions

Phase 1 does **not** modulate LC/NB/retrieval. That's Phase 3.

## DoD

- Migration 069 applies cleanly to /tmp copy + live (with backup)
- 5 seed triggers + 1 aras_state row after migration
- 5 MCP tools registered + discoverable
- β‰₯6 tests passing
- Branch pushed, PR open, NOT merged to main
2 changes: 1 addition & 1 deletion docs/proposals/brain_region_coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Verdict per region: βœ… well-modelled Β· 🟑 partial / under-wired Β· πŸŸ₯ miss

| 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. |
| **Brainstem / Ascending Reticular Activating System β€” Phase 1** | global arousal broadcast via diffuse fan-out | `aras_state`, `aras_transitions`, `aras_triggers` tables + `aras_*` MCP tools. Phase 1 is manual/read+CRUD; Phase 2 wires shadow consult; Phase 3 modulates LC/NB response (see `docs/proposals/aras.md`). |
| **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." |
Expand Down
2 changes: 2 additions & 0 deletions src/agentmemory/mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
mcp_tools_allostatic,
mcp_tools_amygdala,
mcp_tools_analytics,
mcp_tools_aras,
mcp_tools_dmem,
mcp_tools_basal_ganglia,
mcp_tools_belief_merge,
Expand Down Expand Up @@ -86,6 +87,7 @@
mcp_tools_allostatic,
mcp_tools_amygdala,
mcp_tools_analytics,
mcp_tools_aras,
mcp_tools_dmem,
mcp_tools_basal_ganglia,
mcp_tools_belief_merge,
Expand Down
Loading
Loading