Metadata-Version: 2.4
Name: brains-ai
Version: 0.1.0a3
Summary: Local-first control plane and coordination layer for AI coding agents
Author: mekjr1 and brains contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/mekjr1/brains-v2
Project-URL: Repository, https://github.com/mekjr1/brains-v2
Project-URL: Issues, https://github.com/mekjr1/brains-v2/issues
Keywords: ai-agents,coding-agents,control-plane,openai-compatible,mcp,local-first
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.110
Requires-Dist: uvicorn>=0.27
Requires-Dist: pydantic>=2.5
Requires-Dist: pydantic-settings>=2.0
Requires-Dist: PyYAML>=6.0
Requires-Dist: httpx>=0.27
Requires-Dist: sqlalchemy>=2.0
Requires-Dist: typer>=0.12
Requires-Dist: mcp>=1.0
Requires-Dist: jinja2>=3.1
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: types-PyYAML; extra == "dev"
Provides-Extra: litellm
Requires-Dist: litellm>=1.40; extra == "litellm"
Provides-Extra: postgres
Requires-Dist: asyncpg>=0.29; extra == "postgres"
Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
Provides-Extra: telegram
Requires-Dist: python-telegram-bot>=21.0; extra == "telegram"
Provides-Extra: slack
Requires-Dist: slack_sdk>=3.27; extra == "slack"
Provides-Extra: whatsapp
Requires-Dist: httpx>=0.27; extra == "whatsapp"
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.25; extra == "otel"
Requires-Dist: opentelemetry-sdk>=1.25; extra == "otel"
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25; extra == "otel"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.46b0; extra == "otel"
Provides-Extra: all
Requires-Dist: litellm>=1.40; extra == "all"
Requires-Dist: asyncpg>=0.29; extra == "all"
Requires-Dist: psycopg[binary]>=3.1; extra == "all"
Requires-Dist: python-telegram-bot>=21.0; extra == "all"
Requires-Dist: slack_sdk>=3.27; extra == "all"
Requires-Dist: opentelemetry-api>=1.25; extra == "all"
Requires-Dist: opentelemetry-sdk>=1.25; extra == "all"
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25; extra == "all"
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.46b0; extra == "all"
Dynamic: license-file

# Brains

Brains is a local-first **control plane *and* coordination layer** for AI
coding agents: a smart model gateway, MCP server, and shared task / focus /
session / pattern / recurring-task fabric — all driven by a single SQLite
file (`brains.db`) and a single supervised process (`brains serve-all`).

It absorbs the capabilities of the now-retired
[agent-hivemind](https://github.com/mekjr1/agent-hivemind) (advisory locks,
shared task queue, focus handoffs, zombie reaping, recurring tasks with
optional auto-spawn, OS service installers) on top of the existing routing /
provider / RAG stack.

## Production readiness status
This repository now ships a hardened MVP with typed APIs, routing policies, persistence, real provider transports (Echo, Ollama, any OpenAI-compatible HTTP endpoint, optional LiteLLM), schema versioning, multi-key auth, per-key rate limiting, and a working recurring-task scheduler. It is ready for internal/self-hosted use and extension.

## Features
- OpenAI-compatible gateway: `/v1/chat/completions` (SSE), `/v1/responses`, `/v1/messages`, `/v1/models`, `/health`
- Weighted-scoring task classifier + policy router + context planner
- Providers: `echo`, `ollama`, `openai_compatible`/`openai`, optional `litellm`, `github_copilot` (proxy your existing Copilot subscription)
- Multi-key auth, per-key sliding-window rate limiting, structured SSE error envelopes
- Per-provider retry + circuit-breaker policies, signed audit log, backup + restore CLI
- SQLite (default) or Postgres (extra) persistence with versioned migrations
- Local control plane: workspaces, sessions, tasks, handoffs, decisions, claims, mailbox, snapshots, patterns, tools
- Coordination plane v2: advisory locks, zombie reaper, recurring tasks, peer-help RPC, brain-session resume
- Multi-operator brain with per-workspace visibility (`shared`/`private`) and cross-workspace presence
- Repo + docs indexer with content-hash dedup, stale-doc flags, and freshness checks
- FastMCP server (stdio + SSE) for Claude Desktop / Cursor / etc.
- Dashboard (`:9876`) + admin console (`/admin`) with runtime overlay editor
- Service supervisor (`brains serve-all`) + OS install scripts (Windows / systemd / launchd)
- Optional out-bound bridges: WhatsApp, Telegram, Slack
- Optional OpenTelemetry traces + structured logs
- Typer CLI covering every plane: classify, plan, index, search, sessions, tasks, handoffs, decisions, audit, backup, recurring, jobs

## Install

Brains is a Python 3.11+ package, distributed on [PyPI](https://pypi.org/project/brains-ai/)
as `brains-ai` and as a Docker image on [GHCR](https://github.com/mekjr1/brains-v2/pkgs/container/brains-v2).

> The PyPI distribution is named **`brains-ai`** (the bare `brains` name was
> taken by an unrelated 2014 project). The Python module, CLI binary, and
> repo URL are all still `brains` / `brains-v2` — only the `pip install` /
> `pipx install` name differs, similar to `pip install Pillow` → `import PIL`.

### Quickstart

The whole setup is three commands — install, boot the stack, wire your tools:

```bash
pipx install brains-ai                            # or: uv tool install brains-ai
brains up                                         # init + gateway (:8787) + dashboard (:9876) + MCP (:9877)
brains wire                                       # register brains into every detected agentic tool
```

`brains up` is the one-command boot (init the DB + workspace, then supervise
the gateway, dashboard, and MCP server). `brains wire` makes every detected
agentic CLI/IDE discover brains — see
[Auto-wiring agentic tools](#auto-wiring-agentic-tools-brains-wire).

### Docker

If you'd rather not install Python at all:

```bash
docker run --rm \
  -p 8787:8787 -p 9876:9876 -p 9877:9877 \
  -v brains-data:/data \
  ghcr.io/mekjr1/brains-v2:latest
```

The container runs `brains serve-all` and persists `brains.db` plus admin
state under the named volume `brains-data` (`/data` inside the container).

### Development install

For hacking on brains — and to enable `brains upgrade` later — use an
editable git checkout instead:

```bash
git clone https://github.com/mekjr1/brains-v2.git
cd brains-v2
python -m pip install -e .
brains up
```

Prefer the granular commands (`brains init .` then `brains serve` /
`brains serve-all`) when you want to run pieces separately.

`brains init` does three things:

1. Creates `brains.db` (SQLite) in the current directory and applies all
   pending schema migrations.
2. Registers the current directory as a workspace.
3. **On first run only**, generates a 32-byte URL-safe admin key, writes
   it to `~/.brains/admin-key` (mode `0600` on Unix), and prints a
   one-time banner to stderr with the key value and the login URL.

The same key is used for the gateway API (`Authorization: Bearer <key>`)
and the admin/dashboard UI (`/admin/login`). Re-running any command later
reuses the persisted key silently — the banner only appears once.

### Logging into the admin dashboard

```bash
brains serve --host 127.0.0.1 --port 8787       # gateway + /admin
brains dashboard --host 127.0.0.1 --port 9876   # dashboard + /admin (alt)
```

Open <http://127.0.0.1:9876/admin> (or <http://127.0.0.1:9876/dashboard>)
in a browser. Unauthenticated requests to any `/admin/*` or `/dashboard/*`
HTML page 303-redirect to `/admin/login?next=<original-path>` (the old
`?key=...` URL trick is no longer required, and the redirect carries the
operator back to the page they were trying to reach after login). Paste
your admin key and you're in.

Forgot your key? Run:

```bash
brains admin-key show --reveal     # prints the persisted key
brains admin-key path              # prints the file path
brains admin-key rotate            # generates a new key (invalidates sessions)
```

You can also override the persisted key by setting `BRAINS_API_KEY` in
your environment — that value wins and nothing is written to disk.

### Optional extras
The lean core is intentionally small. Heavier capabilities ship as opt-in
extras:

| Extra        | What it adds                                              | Install                            |
|--------------|-----------------------------------------------------------|------------------------------------|
| `litellm`    | LiteLLM provider transport                                | `pip install 'brains-ai[litellm]'`    |
| `postgres`   | Postgres storage backend (asyncpg + psycopg)              | `pip install 'brains-ai[postgres]'`   |
| `telegram`   | Telegram bot bridge (`python-telegram-bot`)               | `pip install 'brains-ai[telegram]'`   |
| `slack`      | Slack bot bridge (`slack_sdk`)                            | `pip install 'brains-ai[slack]'`      |
| `whatsapp`   | WhatsApp Cloud API bridge (httpx-only)                    | `pip install 'brains-ai[whatsapp]'`   |
| `otel`       | OpenTelemetry SDK + OTLP exporter                         | `pip install 'brains-ai[otel]'`       |
| `all`        | Everything above                                          | `pip install 'brains-ai[all]'`        |

Installing the extra is **not** enough — each subsystem also has a config
flag in `brains.runtime.yaml` (the same file edited by `/admin`):

```yaml
schema_version: 1
subsystems:
  storage:
    backend: postgres        # or "sqlite" (default)
  bridges:
    telegram: { enabled: true }
    slack:    { enabled: false }
    whatsapp: { enabled: false }
  otel:
    enabled: true
```

If a subsystem is enabled in config but the matching extra is missing,
`brains` **fails loud at startup** with the exact `pip install` command in
the error. It never auto-installs packages at runtime and never silently
skips an enabled subsystem. `GET /health` reports the install state of
every extra so you can verify your runtime matches your intent.

## Upgrading

If you installed from a git checkout (the recommended path), upgrade with:

```bash
brains upgrade                  # git pull --ff-only, pip install -e ., apply migrations
brains upgrade --no-init        # skip the migration step
brains upgrade --git-branch dev # upgrade from a non-default branch
```

`brains upgrade` refuses to run if the install isn't a git checkout — in
that case, reinstall from your source distribution manually:

```bash
pip install --upgrade brains-ai
brains init .                   # re-applies any pending DB migrations
```

Check the installed version and DB schema state with:

```bash
brains version          # prints version + schema versions + extras (JSON)
brains --version        # short form: prints just the version string
```

See [CHANGELOG.md](CHANGELOG.md) for what changed between releases.

## Run
```bash
brains serve --host 127.0.0.1 --port 8787
```

## Authentication
- `/health` is open for local liveness checks.
- `/v1/*` endpoints require `Authorization: Bearer <key>` or `x-api-key`.
- The effective key is resolved at startup by `brains.api.admin_key.ensure_admin_key`:
  `BRAINS_API_KEY` env var wins; otherwise `~/.brains/admin-key` is loaded
  (or generated on first run).
- Configure a rotation list via `BRAINS_API_KEYS` (tuple of strings) — every value is accepted, enabling zero-downtime key rotation. Comparisons are constant-time.
- Set `BRAINS_RATE_LIMIT_PER_MINUTE` (or YAML `rate_limit_per_minute`) to a positive integer to enable per-key sliding-window rate limiting. Default is `0` (disabled). On limit, the gateway returns `429` with a `Retry-After` header.

## CLI
```bash
brains classify "Fix retry bug in webhook handler"
brains plan "Use latest API docs for migration"
brains add-repo .
brains index-repo .
brains search-repo "retry" .
brains embed-repo --model nomic-embed-text          # semantic index (needs an embed model)
brains search-semantic "where is retry handled"      # cosine search over embedded chunks
brains check-source https://docs.stripe.com/webhooks
brains traces
brains state --workspace .
brains session-start --workspace . --tool codex
brains decision-file --workspace . --title "Approve docs lookup" --body "Need current API docs"
brains handoff-set --workspace . --title "Next step" --body "Continue provider wiring"
brains task-create --workspace . --title "Fix retry bug" --priority p1
brains workspace-claim --workspace . --session ses_123 --scope code
brains message-send --workspace . --subject "Blocked on tests"
brains snapshot-capture --workspace . --kind git --data "{\"branch\":\"main\"}"
brains pattern-propose --name retry-tests --category testing --description "Use deterministic retry tests"
brains pattern-approve --name retry-tests
brains tool-register --name claude --display-name "Claude Code" --cli-command claude --capabilities edit,chat,mcp
brains tool-list --verify-now
brains recurring-create --workspace . --name daily-audit --title-template "Daily audit {date}"
brains recurring-fire --name daily-audit
brains docs-index --workspace .
brains views-refresh --workspace .
brains jobs run stale-docs-digest --workspace .
brains dashboard --host 127.0.0.1 --port 9876
```

## Dashboard & Admin Console

The dashboard ships as a single FastAPI app at `:9876` (or wherever you run
`brains dashboard`) and surfaces every plane of the control system through a
**collapsible left sidebar** grouped into *Live* (overview, sessions,
decisions, handoffs), *Work* (tasks, routes, recurring), and *Knowledge*
(events, patterns, tools, workspaces, operators). The sidebar starts in a
64px icon-only state and expands to 232px on click; the open/closed choice
persists per browser via `localStorage`. Every list page also carries a
collapsible **"ⓘ What's this?"** explainer panel that's open on first
visit and dismissed-once per browser.

- `/dashboard` — *Today* attention zone (decisions / handoffs / sessions /
  tasks that need you), quick actions, last-24h activity (scrollable feed),
  and a Universe snapshot
- `/dashboard/sessions`, `/dashboard/tasks`, `/dashboard/decisions`,
  `/dashboard/handoffs`, `/dashboard/routes`, `/dashboard/events`,
  `/dashboard/patterns`, `/dashboard/tools`, `/dashboard/workspaces`,
  `/dashboard/recurring`, `/dashboard/operators` — rich, filterable views
  per plane with row-click drill-in where a detail page exists
  (workspaces, tasks, sessions, decisions, handoffs)
- `/dashboard/api/*` — read-only JSON for programmatic access

The admin console lives under `/admin/*` on the same app (also mounted on the
gateway at `:8787/admin`):

- `/admin/login` — sign in with any configured API key (cookie-based session)
- `/admin/overview` — model tiers, task routes, auth posture
- `/admin/config` — edit model tiers / routes / rate limits / provider URLs;
  saves to a **runtime overlay** (`brains.runtime.yaml`) and reloads settings
  immediately
- `/admin/test` — ping any provider/model and view latency + preview
- `/admin/secrets` — see which `${ENV:NAME}` references are referenced and
  whether they're set in this process

### Auth & secrets

- Browser surfaces are gated by the `brains_admin_key` cookie set by
  `/admin/login`. Unauthenticated requests to any HTML page under
  `/admin/*` **or** `/dashboard/*` 303-redirect to the login form (with
  `?next=<original-path>` so you land back where you started after
  signing in). JSON `/admin/api/*` and `/dashboard/api/*` routes return
  a plain `401` and accept the standard `Authorization: Bearer <key>`
  header for script clients.
- The legacy `?key=...` query parameter is still honored for backwards
  compatibility but should not be used by browsers — see
  [SECURITY.md](SECURITY.md).
- The admin UI **never persists raw secrets**. Provider API keys are
  stored as `${ENV:NAME}` references in `brains.runtime.yaml`; values
  come from the process environment at load time. To rotate, update the
  env var.
- The runtime overlay only accepts a curated allowlist of keys
  (`models`, `routes`, rate limit, provider URLs, etc.) — operator-managed
  values like `api_key` and `db_url` stay in `BRAINS_CONFIG`/env.

## FastMCP & IDE Integration

Brains v2 includes a built-in FastMCP server with a background recurring task scheduler. You can connect Claude Desktop or Cursor to it using `stdio` or `sse` modes.

**Start the MCP server in SSE mode (recommended, always-on):**
```bash
brains mcp --mode sse --port 9877
```

`brains serve-all` and `brains up` already supervise the MCP server
alongside the gateway and dashboard, so you only need the standalone
`brains mcp` command when running the MCP transport on its own.

### Auto-wiring agentic tools (`brains wire`)

Instead of hand-editing each tool's MCP config, let brains register itself
into every agentic CLI/IDE it detects:

```bash
brains up             # ensure the MCP server is running (:9877)
brains wire           # wire all detected tools (global, SSE transport)
brains wire --status  # show what's wired
brains unwire         # remove every brains entry + rule block
```

`brains wire` is **global by default** — brains is a multi-session
coordination layer, so it registers into the user-level config of every
detected tool. For each tool it injects two things:

1. an MCP server entry (so the tool can call every `brains.*` tool), and
2. a short "use brains first" rule into the tool's instruction file,
   wrapped in `brains:wire` sentinels so it updates/removes cleanly.

Tier-1 tools: **GitHub Copilot CLI**, **Claude Code**, **OpenAI Codex CLI**.

| Flag | Effect |
|---|---|
| `--transport sse` (default) | point tools at the running `:9877/sse` server |
| `--transport stdio` | each tool spawns its own `brains mcp --mode stdio`, sharing the global DB via `BRAINS_DB_URL` |
| `--tool copilot-cli` | limit to specific tool(s); repeatable |
| `--no-rules` | wire the MCP entry only; skip the instruction rule |
| `--dry-run` | print the plan; write nothing |
| `--status` | report current wiring state |

Every edit is backed up (`<file>.bak-<timestamp>`), and a pre-existing
non-managed `brains` entry is never overwritten. The SSE transport embeds
your admin key in each tool's config, so keep those files local.

### Strict enforcement (route a tool's model through brains)

`brains wire` makes a tool *aware* of brains, but a model can still ignore the
rule. For hard enforcement, route the tool's model calls through the gateway
and let brains inject a **non-removable** system preamble:

1. Configure a real model tier (e.g. local Ollama — free, no key) and the
   preamble, via `brains.runtime.yaml` or `/admin/config`:
   ```yaml
   models:
     default: { provider: ollama, model: qwen2.5-coder:7b }
   ollama_base_url: http://127.0.0.1:11434
   gateway_preamble: "You are routed through Brains. Call brains.start_session and brains.plan_request before non-trivial work."
   ```
2. Point the tool's model traffic at the gateway:
   - Copilot CLI: `COPILOT_PROVIDER_BASE_URL=http://127.0.0.1:8787/v1`
   - Claude Code: `ANTHROPIC_BASE_URL=http://127.0.0.1:8787`
   - any OpenAI-compatible tool: `base_url=http://127.0.0.1:8787/v1`

Every request the tool makes now carries the preamble, added server-side after
the agent composes its prompt — so the agent cannot strip it. `gateway_preamble`
is empty by default (off). Note the gateway routes to your configured tier, so
point it at a capable provider — a 7B local model won't match a frontier cloud
agent.

**Claude Desktop Configuration (`claude_desktop_config.json`):**
```json
{
  "mcpServers": {
    "brains": {
      "url": "http://127.0.0.1:9877/sse"
    }
  }
}
```

**Cursor Configuration (stdio fallback):**
In Cursor Settings -> Features -> MCP, add a new server:
- Name: `brains`
- Type: `command`
- Command: `brains mcp --mode stdio`

## Providers

Brains ships five provider transports out of the box. Choose one (or mix them across tiers) in your `BRAINS_CONFIG` YAML:

| Name | Use for | Notes |
|---|---|---|
| `echo` | tests, local sanity checks | deterministic fake response |
| `ollama` | local LLMs via Ollama | configure with `BRAINS_OLLAMA_BASE_URL` (default `http://127.0.0.1:11434`), `BRAINS_OLLAMA_TIMEOUT_SECONDS` (default `30.0`) |
| `openai_compatible` / `openai` | OpenAI itself, Together, Groq, OpenRouter, Anyscale, vLLM, llama.cpp HTTP | configure with `BRAINS_OPENAI_COMPATIBLE_BASE_URL`, `BRAINS_OPENAI_COMPATIBLE_API_KEY`, `BRAINS_OPENAI_COMPATIBLE_TIMEOUT_SECONDS` |
| `litellm` (optional) | unified API over OpenAI/Anthropic/Bedrock/Vertex AI/Mistral | install with `pip install 'brains-ai[litellm]'`, configure with `BRAINS_LITELLM_TIMEOUT_SECONDS` |
| `github_copilot` | GPT-5 / Claude / Gemini via your existing GitHub Copilot subscription | auth via `brains copilot-login` (device-code flow) or `BRAINS_GITHUB_COPILOT_OAUTH_TOKEN`. See [GitHub Copilot provider](#github-copilot-provider) below. |

Example mixing providers across tiers:

```yaml
models:
  cheap:
    provider: ollama
    model: qwen2.5-coder:7b
  default:
    provider: openai_compatible
    model: gpt-4o-mini
  strong:
    provider: github_copilot
    model: claude-sonnet-4.5
  deep:
    provider: litellm
    model: anthropic/claude-3-5-sonnet-20241022
openai_compatible_base_url: https://api.openai.com/v1
openai_compatible_api_key: sk-...
```

Upstream provider failures are wrapped in a structured envelope:

- Non-streaming: HTTP `502` with `{"error": {"type": "provider_error", "code": "provider_invocation_failed", "message": ...}}`.
- Streaming: an SSE `data:` chunk carrying the same envelope followed by `data: [DONE]`.

### GitHub Copilot provider

The `github_copilot` provider proxies `https://api.githubcopilot.com/chat/completions`
so any OpenAI-base-URL tool (Claude Code, Codex, aider, Continue, …) can call
GPT-5 / Claude / Gemini billed against your existing Copilot subscription, with
the brain gateway adding classification, routing, audit, and rate-limit layers
on top.

OAuth-token sources are tried in order:

1. `BRAINS_GITHUB_COPILOT_OAUTH_TOKEN` env var
2. cached device-code token at `~/.brains/cache/github_copilot_oauth.json`
3. `gh auth token` shell-out (requires `gh auth refresh -s copilot` once;
    disable with `BRAINS_GITHUB_COPILOT_USE_GH_CLI=false`)

CLI:

```bash
brains copilot-login    # device-code flow → caches OAuth token
brains copilot-status   # show which auth source would be used
brains copilot-logout   # delete cached OAuth + session tokens
```

The short-lived (~30 min) Copilot session token is cached per OAuth-token
fingerprint and refreshed on 401 or near-expiry. Rotating the OAuth token
invalidates the cache automatically.

> **ToS caveat.** GitHub's Copilot terms scope it to "code suggestions in
> editors." Using it as a general gateway provider follows the same path
> OpenCode / aider / Cline take, but it is a personal-use grey area, not a
> sanctioned public API. The endpoint and headers can change without notice.

## Integrations
See `examples/` for Continue/Aider/Claude Code/Copilot CLI environment samples.

## Security notes
See `docs/security.md` for threat model and controls.

Pattern names are global stable IDs. The tool registry only records and verifies
local commands; it does not spawn agents. Recurring definitions only fire
manually into normal tasks. Auto-spawn and automatic recurring scheduler
execution are intentionally deferred until explicit policy gates exist.

## Roadmap — features by phase

Brains is built one phase at a time. Each phase is a coherent jump in what
the system can do. Shipped items stay as terse one-liners; see
[CHANGELOG.md](CHANGELOG.md) for the details.

### Phase 1 — Local single-machine control + coordination *(today)*

- [x] Smart model gateway (`/v1/chat/completions`, `/v1/responses`, `/v1/messages`)
- [x] Weighted-scoring classifier + policy router + context planner
- [x] Providers: Echo, Ollama, OpenAI-compatible, optional LiteLLM
- [x] SSE streaming with structured error chunks
- [x] Multi-key auth + per-key sliding-window rate limiting
- [x] SQLite persistence with versioned migrations
- [x] FastMCP server (stdio + sse) for Claude Desktop / Cursor
- [x] Local control plane: sessions, tasks, handoffs, decisions, mailbox, snapshots
- [x] Coordination plane v2: advisory locks, zombie reaper, recurring auto-spawn
- [x] `start_session` welcome packet
- [x] Brain-session resume across tool restarts
- [x] Peer-help RPC
- [x] Adoption telemetry
- [x] Repo indexer + search with content-hash dedup
- [x] Dashboard (`:9876`) + admin console (`/admin`)
- [x] Service supervisor (`brains serve-all`) with restart-on-crash
- [x] OS install scripts (Windows / systemd / launchd)
- [x] SSRF default-deny on freshness HEAD checks

### Phase 2 — Remote brain & multi-machine fleet

- [x] Pluggable storage backend (SQLite + Postgres); Turso / libSQL planned
- [ ] Read-replica + write-leader topology for the control plane
- [ ] HTTPS / TLS deployment guidance + container image + Helm chart
- [ ] Machine registry
- [ ] Cross-machine session visibility
- [ ] Machine-aware advisory locks
- [ ] Workspace federation (shared replicated, personal local)
- [ ] Encrypted machine-to-brain transport with mutual auth

### Phase 3 — Inter-agent peer collaboration

- [x] Real-time peer-help RPC
- [x] Brain-session resume across tool restarts
- [x] Agent → agent task handoff
- [ ] Agent-authored PRs / MRs
- [ ] Agent pre-review of agent PRs (human ratification stays mandatory)
- [ ] CI/CD watch
- [ ] Deploy hand-off (CI-green + recorded human approval)
- [ ] Standing-orders queue
- [ ] Conflict resolution when two agents touch the same file

### Phase 4 — Operator remote control (you, on your phone)

- [ ] Remote interactive-prompt gates
- [x] WhatsApp bridge (out-bound; inbound TODO)
- [x] Telegram bridge (out-bound; inbound scaffolded)
- [x] Slack bridge (out-bound; socket-mode inbound scaffolded)
- [ ] Email digest
- [ ] Web push notifications
- [ ] Voice-note input

### Phase 5 — Multi-project, multi-engineer orchestration

- [x] Multi-operator brain — Layer 1 of [decision record 0002](docs/decisions/0002-multi-operator-model.md)
- [x] Workspace permission model — Layer 2
- [x] Cross-workspace operator presence — Layer 3
- [ ] Cross-operator handoff protocol
- [ ] Sealed handoffs for sensitive payloads — Layer 4, deferred
- [ ] Workload-aware routing across the fleet
- [ ] Real-time fleet view
- [ ] Timezone-aware notification routing
- [ ] Per-operator + per-workspace budget caps

### Phase 6 — Production hardening

- [x] Per-provider retry / timeout / failover + circuit-breakers
- [x] OpenTelemetry traces + structured stdout logs
- [x] Signed audit log
- [x] Backup + restore tooling for the brain DB
- [ ] Token accounting parity across all providers
- [ ] Secret manager integration (Vault, AWS Secrets Manager, 1Password)
- [ ] Pen-test pass + threat-model refresh
- [ ] Compliance posture docs (SOC2, GDPR data handling)

---

## What's stable today

Brains today is a **hardened single-machine MVP** suitable for
self-hosted use by one operator with one or many local agents. Everything
checked in Phase 1 above is shipping, tested, and documented. Phases 2–6
are the planned trajectory.

## License & contributing
- License: [MIT](LICENSE)
- Contributing: see [CONTRIBUTING.md](CONTRIBUTING.md)
- Code of conduct: see [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
- Security disclosures: see [SECURITY.md](SECURITY.md)
