Skip to content
Merged
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
62 changes: 62 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,68 @@ jobs:
- name: Run tests
run: pytest tests/ -v

# --------------------------------------------------------------------------
# Tier 1b: Windows smoke. Best-effort — currently `continue-on-error: true`
# because brainctl ships several optional extras (sqlite-vec, mint, code)
# whose native dependencies are POSIX-leaning. The smoke surface here is
# the core stdio MCP path plus brain.db init/migrate/CRUD, which is the
# 80% of brainctl that a Windows agent operator actually touches.
#
# Goals:
# * catch read_text() / locale / path-separator / line-ending breakage
# * catch SQLite version backfill bugs on Windows Python builds
# * keep the "ubuntu green = release green" invariant by not blocking
#
# When this stabilizes (no expected failures for 2-3 PRs), drop the
# continue-on-error and promote it to a required check.
# --------------------------------------------------------------------------
test-windows:
runs-on: windows-latest
continue-on-error: true
strategy:
matrix:
python-version: ["3.12"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies (core + mcp only)
# `[all]` pulls native deps (sqlite-vec wheel, signing, etc.) whose
# Windows wheels are inconsistent. The MCP/init/migrate surface is
# what we actually need to smoke on Windows.
run: |
python -m pip install --upgrade pip
pip install -e ".[mcp]"
pip install pytest
- name: Report SQLite version
run: python -c "import sqlite3; print('sqlite_version:', sqlite3.sqlite_version)"
- name: Smoke — brainctl init on Windows
# Invoke via the console-script entry point (defined in
# pyproject.toml as `brainctl = agentmemory.cli:main`). `python
# -m agentmemory` does NOT work because the package has no
# `__main__.py`.
shell: pwsh
run: |
$db = "${{ runner.temp }}\brain.db"
brainctl init --path "$db"
if (-not (Test-Path "$db")) { Write-Error "brainctl init did not create $db"; exit 1 }
$py = @"
import sqlite3, sys
c = sqlite3.connect(r'$db')
integrity = c.execute('PRAGMA integrity_check').fetchall()
rows = c.execute('SELECT * FROM bg_modulators').fetchall()
print('integrity:', integrity)
print('bg_modulators:', rows)
assert integrity == [('ok',)], f'integrity_check FAIL: {integrity}'
assert rows and rows[0][4] == 0.5, f'acetylcholine column FAIL: {rows}'
"@
python -c $py
- name: Smoke — core test subset (no native-extra deps)
run: |
pytest tests/test_mcp_allowed_tools.py tests/test_mcp_tools_consolidated.py tests/test_schema_parity.py tests/test_fk_integrity_triggers.py tests/test_mcp_tools_health.py -v

# --------------------------------------------------------------------------
# Docs sync: scripts/check_docs.py asserts that the published doc counts
# (MCP tool count, command count, etc.) match the implementation.
Expand Down
135 changes: 135 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,141 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).

## [Unreleased]

## [2.8.0] — 2026-05-20 — *16 brain subsystems + v2 MCP tool surface (PR #138)*

This release lands the issue #116 brain-architecture work and consolidates
the MCP tool surface to fit harness caps. Supersedes overnight PRs
#120–#137 as a single coherent artifact.

### Added — 16 brain-region / nucleus subsystems (Phase 1)

Migrations **067–082** introduce schemas + dispatch for: locus coeruleus
(phasic NE), nucleus basalis (phasic ACh + `bg_modulators.acetylcholine`),
ARAS (arousal / sleep-wake), habenula (negative prediction), hippocampus
CA1 + subiculum, workspace bandwidth, connectome, sleep architecture,
VTA / SNc dopamine pathways, septum theta, raphe, memory aging
(synaptic tagging-and-capture, Frey & Morris), claustrum, colliculi,
mammillary (Papez circuit), and olfactory. Each ships with an
`mcp_tools_*.py` module, a design proposal in `docs/proposals/`, and a
matching pytest module.

### Added — Windows CI smoke

`test-windows (3.12)` job verifies `brainctl init` + core test subset on
`windows-latest`. Continue-on-error today; promotion to required after
2–3 green PRs.

### Fixed — UTF-8 read for SQL files (Windows hardening)

`Path.read_text(encoding="utf-8")` explicit on every SQL-ingest site
(`_impl.py`, `brain.py`, `migrate.py` ×3). Previously the system locale
encoding was used, which crashed on em-dashes / arrows / γ in
`init_schema.sql` on Windows cp1252 locales.

### Fixed — fresh `brainctl init` includes every migration

`init_schema.sql` now contains migrations 067–082 inlined, and `cmd_init`
calls `migrate.run()` after `executescript()` as defense in depth.
`acetylcholine` is declared inline in the `bg_modulators` CREATE TABLE
to avoid a SQLite-version-dependent backfill quirk that left the column
NULL on CI Linux SQLite 3.31.

### Changed — MCP tool surface v2 (hard cutover, 370 → 100 visible)

**Breaking change.** Consolidated the public MCP tool surface from 370
named tools to **100 visible** by routing through 35 action-discriminated
dispatchers. v1 tool functions are untouched and still callable internally
(reverting the filter restores the v1 surface).

Why:
- Many MCP harnesses cap at ~100 visible tools.
- 370 tool descriptions burned ~50k tokens of system-prompt overhead
before any agent work began. v2 cuts that to ~12k tokens.
- The 16 brain regions shipped tonight (LC, NB, ARAS, Habenula, VTA,
Raphe, septum, claustrum, colliculi, mammillary, olfactory, CA1+Sub,
sleep, memory_aging, workspace_bandwidth, connectome) duplicated the
shape of 11 already-shipped regions. Tools were redundant at the
shape level even when the payloads were distinct.

New visible surface:
- **Primary (60 tools)** — memory_*, event_*, entity_*, agent_orient/
wrap_up/register, handoff_add/latest, trigger_create/check, search,
vsearch, pagerank, decision_add, procedure_add/get/list/search,
affect_*, reason/infer/think, reconsolidate, promote, free_energy_check,
health/stats/validate/lint/backup, dream_cycle, abstract_summarize,
zoom_in/out, push, wallet_create/show, weights, whosknows.
- **Subsystem dispatchers (7 tools)** — subsystem_list, subsystem_status,
subsystem_list_actions, subsystem_emit, subsystem_register,
subsystem_history, subsystem_configure. Cover 27 brain subsystems.
- **Topic dispatchers (22 tools)** — belief, tom, trust, reflexion,
gaps, federated, world, workspace, temporal, consolidation, expertise,
neuro, meb, quarantine, epoch, usage, schedule, task, policy,
knowledge, context, lifecycle.
- **Admin dispatchers (6 tools)** — entity_admin, memory_admin,
agent_admin, handoff_admin, trigger_admin, procedure_admin.

Hidden (still callable internally): 270 v1 tool names — full list at
`mcp_tools_consolidated.py:DEPRECATED_TOOL_NAMES`.

Migration: `docs/TOOL_MIGRATION_V2.md` has the full old→new mapping.
Common pattern: `lc_fire(...)` → `subsystem_emit(name="lc", action="fire", payload={...})`.

Rollback: remove the `_VISIBLE_TOOL_NAMES = _ALL_TOOL_NAMES - _V2_DEPRECATED`
filter in `mcp_server.py:list_tools` and the v1 surface returns immediately.
Or `git revert` the consolidation commit. The underlying Python tool
functions are untouched in every case.

Measured impact:
- Visible tool count: 260 → 100
- Tool description tokens in system prompt: ~40k → ~12k
- `list_tools()` response time: <1ms (negligible change)
- Cold-start import: ~340ms (no change vs. v1)
- `tests/bench/run --check`: P@1=0.60 / P@5=0.18 / Recall@5=0.51 (zero delta)

### Added — 16 new brain-region / subsystem Phase 1s (overnight 2026-05-20)

Migrations 067-082 + their MCP tools (now accessed via `subsystem_*`
dispatchers — see v2 consolidation entry above). Each is Phase 1
inspection-only / additive — no behavior change to retrieval or
existing subsystems.

- **Migration 067** — Locus Coeruleus (NE source / +surprise broadcaster).
Codex-authored under orchestration.
- **Migration 068** — Nucleus Basalis (ACh / attention broadcaster).
Adds `acetylcholine` column to `bg_modulators` (4th dial).
- **Migration 069** — ARAS (global arousal / 6-stage sleep-wake state).
- **Migration 070** — Habenula (anti-reward / negative-PE channel).
- **Migration 071** — Hippocampus CA1 + Subiculum (trisynaptic loop
completion; match/mismatch + cortical bridge).
- **Migration 072** — Workspace bandwidth limit (top-K-per-epoch on
workspace_broadcasts).
- **Migration 073** — Connectome graph (22-node inter-subsystem comm
graph; bg_modulators is the top-degree hub).
- **Migration 074** — Sleep architecture (5-stage state machine with
per-stage permitted_operations CSV).
- **Migration 075** — VTA/SNc (DA source nucleus + pathway catalog).
- **Migration 076** — Septum + theta rhythm (4-8 Hz pacemaker, 8 bins
per cycle, phase-lock tracking).
- **Migration 077** — Raphe nuclei (5-HT source; DRN + MRN subtypes).
- **Migration 078** — Memory aging (synaptic tagging-and-capture;
tag at write, capture-within-window or demote).
- **Migration 079** — Claustrum (cross-modal retrieval binding;
9 modalities catalogued).
- **Migration 080** — Colliculi (SC + IC orienting reflex;
novel-pattern triggers).
- **Migration 081** — Mammillary Bodies + Papez circuit (episodic
consolidation transit log).
- **Migration 082** — Olfactory cortex (direct sensory-emotional
imprints; bypasses thalamus, Proust effect).

Plus the issue #116 Phase 1-A pathway log (migration 066), sigmoid
read-gate (`agentmemory.sigmoid_gate`), motivational entry gate
(`agentmemory.motivational_gate`), and the research-avenues memo at
`research/autonomous-research-avenues-2026-05-20.md`.

Test totals: 141 new test cases across 16 modules, all green. Bench
harness (`tests/bench/run --check`) confirms zero retrieval regression.

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

External architecture memo (issue #116, "Thalamus, Basal Ganglia, and
Expand Down
53 changes: 51 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Published as `brainctl` on PyPI (v2.2.1+, current 2.4.10).
## Key Paths
- **DB:** `db/brain.db` (WAL mode, foreign keys ON, 59 user-facing tables, 49 numbered migrations + one unnumbered V2-4 quantum-schema file). The numbered sequence has an intentional gap at 050 — the V2-4 quantum schema (`db/migrations/quantum_schema_migration_sqlite.sql`) occupies that slot without a number because it was applied ad-hoc during the V2-4 rollout and pre-dates the idempotent runner fix in 2.4.8. The runner only picks up files matching `^\d+_.+\.sql$` so the quantum file is a no-op for `brainctl migrate` on fresh installs — apply manually if you need the quantum columns on a new DB. (Audit I28 — 2026-04-19.)
- **CLI:** `bin/brainctl` — main CLI entry
- **MCP server:** canonical entry is `agentmemory.mcp_server:run` (201 tools across `mcp_server.py` + 29 `mcp_tools_*.py` modules). Installed as the `brainctl-mcp` console script via pip. The legacy standalone `bin/brainctl-mcp` only registers a subset and is being phased out.
- **MCP server:** canonical entry is `agentmemory.mcp_server:run`. As of v2 surface consolidation (2026-05-20): **100 visible tools** (370 registered internally; 270 hidden behind action-discriminated dispatchers). Installed as the `brainctl-mcp` console script via pip. See `MCP_SERVER.md` for the tool reference and `docs/TOOL_MIGRATION_V2.md` for v1→v2 migration. The legacy standalone `bin/brainctl-mcp` only registers a subset and is being phased out.
- **Bench:** `bin/brainctl-bench` — retrieval eval harness (P@k / MRR / nDCG@k regression gate, fixtures under `tests/bench/`)
- **Source:** `src/agentmemory/` — Python package
- **Config:** `config/` — quiet hours, consolidation schedules
Expand All @@ -19,11 +19,60 @@ Published as `brainctl` on PyPI (v2.2.1+, current 2.4.10).
pip install -e . # dev install
brainctl stats # verify DB
brainctl search "test" # test search
python3 -m agentmemory.mcp_server --list-tools # full 199-tool MCP surface
python3 -m agentmemory.mcp_server --list-tools # 100-tool v2 MCP surface
python3 -m tests.bench.run # retrieval quality benchmark
python3 -m tests.bench.run --check # fail on >2% regression vs baseline
```

## MCP tool surface (v2, post-2026-05-20 consolidation)

100 visible tools split into four tiers:

- **Primary (call by name):** `memory_add`, `memory_search`, `vsearch`,
`search`, `event_add`, `event_search`, `entity_create`, `entity_get`,
`entity_search`, `entity_observe`, `entity_relate`, `decision_add`,
`handoff_add`, `handoff_latest`, `trigger_create`, `trigger_check`,
`agent_orient`, `agent_wrap_up`, `agent_register`,
`procedure_add/get/list/search`, `affect_*`, `reason`, `infer`,
`infer_pretask`, `infer_gapfill`, `think`, `reconsolidate`,
`reconsolidation_check`, `promote`, `free_energy_check`,
`pagerank`, `health`, `stats`, `validate`, `lint`, `backup`,
`dream_cycle`, `abstract_summarize`, `zoom_in`, `zoom_out`, `push`,
`push_report`, `wallet_*`, `weights`, `whosknows`.
- **Subsystem dispatchers** (`subsystem_list`, `subsystem_status`,
`subsystem_emit`, `subsystem_register`, `subsystem_history`,
`subsystem_configure`, `subsystem_list_actions`): cover all 27 brain
regions (LC, NB, ARAS, Habenula, VTA, Raphe, septum, claustrum,
colliculi, mammillary, olfactory, CA1, sleep, memory_aging,
workspace_bandwidth, connectome, BG, cerebellum, thalamus, amygdala,
hippocampus, ACC, DMN, drives, insula, PFC, entorhinal).
- **Topic dispatchers:** `belief`, `tom`, `trust`, `reflexion`, `gaps`,
`federated`, `world`, `workspace`, `temporal`, `consolidation`,
`expertise`, `neuro`, `meb`, `quarantine`, `epoch`, `usage`,
`schedule`, `task`, `policy`, `knowledge`, `context`, `lifecycle`.
- **Admin dispatchers:** `entity_admin`, `memory_admin`, `agent_admin`,
`handoff_admin`, `trigger_admin`, `procedure_admin`.

**Call pattern for dispatchers:**
```jsonc
// Discover first
subsystem_list() // all 27 subsystems + layers
subsystem_list_actions(name="lc") // valid actions for LC

// Then act
subsystem_status(name="lc", agent_id="...")
subsystem_emit(name="lc", action="fire", payload={trigger_name: "x", surprise_magnitude: 0.7})
subsystem_configure(name="lc", field="set_mode", payload={mode: "tonic_high"})

belief(action="get", payload={...})
trust(action="calibrate", payload={...})
entity_admin(action="merge", payload={...})
```

If you call a v1 name (e.g. `lc_status`, `belief_collapse`, `trust_show`),
the MCP server returns "Unknown tool" with a suggestion. Migration table
in `docs/TOOL_MIGRATION_V2.md`.

## Architecture
- Tables: memories, events, entities, decisions, context, knowledge_edges, affect_log, access_log, agent_state, agent_beliefs
- FTS5 indexes on memories, events, entities
Expand Down
Loading