# Octobrain 0.9.0: знание выходит в мультиплеер

> Octobrain 0.9.0 превращает слой знаний в то, чем может делиться вся команда: git-backed knowledge boxes доставляют выверенные правила и документацию прямо в репозитории, синхронизируются в фоне и остаются разнесёнными по scope для каждого проекта или организации. Scope-ы памяти получают человекочитаемые имена вместо непрозрачных хэшей. А recall стал острее — RRF-фьюжн нескольких запросов делает декомпозицию запроса по-настоящему окупающейся, рёбра Supersedes позволяют актуальному факту обходить устаревший, а новые временные фильтры отвечают на вопрос «что я решил на прошлой неделе». Вот что изменилось и как обновиться.

# Octobrain 0.9.0: знание выходит в мультиплеер

Ваша команда уже написала документацию. Runbook для деплоя, правила «не трогай это без миграции», выстраданные заметки о том, почему платёжный сервис ретраит именно так. Всё это живёт в вики, которую никто не читает, в закреплённом сообщении в Slack и в головах трёх человек. Каждая новая сессия агента — и каждый новый коллега — стартует с нуля и переучивает всё это заново через боль.

[0.7.0](/blog/octobrain-0-7-0-memory-that-sleeps) научила память каждого агента **поддерживать себя саму** — sleep consolidation, decay, goal-anchored сворачивание. Это было про одну память, которая умнеет сама по себе.

0.9.0 — про вторую половину проблемы: знание, которое не должно переучиваться на каждой машине. Она делает слой знаний Octobrain **общим** — версионируется в git, разносится по scope по имени, синхронизируется автоматически — и обостряет recall, чтобы нужный факт побеждал чаще. (Заодно мы свернули сюда и наработки 0.8.0.)

---

## Git-Backed Knowledge Boxes — выкатывайте знание как код

Это главное. **Knowledge box** — это git-репозиторий, набитый markdown: правила, документация, плейбуки, заметки по архитектуре, — который Octobrain клонирует, индексирует и держит в синхроне. Соберите его один раз, версионируйте как код — и каждый агент на каждой подписавшейся машине получает одно и то же знание, доступное для поиска.

Есть две разновидности, и они покрывают два реальных случая:

**Локально для проекта — просто закоммитьте директорию `.box/`.** Сложите живое знание вашего проекта в `.box/` в корне репозитория. Любой, кто клонирует репозиторий и запустит Octobrain, получит его проиндексированным автоматически — без лишней команды, без настройки remote. Оно путешествует вместе с кодом, потому что оно _и есть_ в коде.

**Remote — подпишитесь на общий box.** Укажите Octobrain на git-URL — и он делает shallow-clone box-а и индексирует его под scope:

```bash
# Subscribe to your org's shared knowledge box
octobrain box import https://github.com/acme/engineering-knowledge

# Index it at the global scope — visible in every project on this machine
octobrain box import https://github.com/acme/conventions --global

# Pull + smart-reindex every subscribed box and the local .box/
octobrain box sync

# See what you're subscribed to, or drop one
octobrain box list
octobrain box remove github.com/acme/engineering-knowledge
```

Каждый чанк из box получает стабильный source URI вида `box://<host>/<org>/<repo>/...`, так что он сгруппирован, атрибутируем и аккуратно удаляем — выдёргиваете box, и все его строки уходят вместе с ним. Ре-синки **умные и построены на хэшах**: переэмбеддятся только изменившиеся файлы, так что `sync` по неизменившемуся box стоит почти ничего.

А под MCP вам даже не нужно звать `sync` — сервер обнаруживает `.box/` каждого проекта, прощупывает org-box и обновляет подписанные remote **в фоне, один раз за сессию**, single-flight-ом, так что это никогда не блокирует запрос. Ваш агент просто начинает находить знание команды в своих поисках.

```toml
[knowledge]
chunk_size = 1200   # boxes index through the same chunker as everything else
```

Суть: runbook перестаёт жить в чьей-то голове. Он живёт в репозитории, ищется по смыслу и всплывает в контексте вашего агента в тот момент, когда он релевантен, — для всех.

---

## Scope-ы заменяют хэши проектов — память с именем

До сих пор Octobrain изолировал память по проектам, хэшируя URL вашего Git remote в непрозрачную SHA-256-директорию. Это работало, но прочитать её было нельзя, нацелиться на неё нельзя и поделиться ею тоже нельзя.

0.9.0 заменяет это на **scope-ы**: человекочитаемые строки, выводимые автоматически из вашего Git remote (или из локального пути как запасной вариант), которые вы реально видите и можете на них указать.

```bash
# Auto-detected from the git remote — nothing to configure
octobrain memory remember "rate limiting approach"

# Or target a scope explicitly
octobrain memory remember "rate limiting approach" --scope acme/payments

# Store something that should be visible everywhere, not just this project
octobrain memory memorize --title "Team convention: trunk-based, no long-lived branches" \
  --content "..." --global
```

Именно scope-ы делают box-ы связными: remote-box по умолчанию привязывается к scope уровня организации, `.box/` привязывается к scope своего проекта, а `--global` ставит знание или память перед каждым проектом на машине. Одна система именования, используемая везде, — пути хранения, фильтры поиска, статистика и логи теперь читаются на человеческом языке, а не хэшами.

**Это единственное breaking-изменение, которое вас касается:** флаг `--project` и параметры инструментов `project` теперь стали `--scope`. То же поведение, читаемое имя. См. [Апгрейд](#апгрейд).

---

## Recall по нескольким запросам, который реально окупается — RRF-фьюжн

Octobrain давно поддерживает поиск по нескольким запросам — разложить размытый вопрос на несколько более чётких и искать их вместе:

```bash
octobrain memory remember "authentication" "session security" "jwt expiry"
```

Проблема была в слиянии. Старая логика брала лучший единичный score каждого воспоминания и добавляла плоские 10% за каждое дополнительное совпадение — смешивая по-запросные score, вычисленные в **несравнимых масштабах**. Воспоминание, которое стабильно ранжировалось по всем трём запросам, могло проиграть разовому топ-попаданию по одному запросу. Декомпозиция на деле не помогала; иногда вредила.

0.9.0 заменяет это на **Reciprocal Rank Fusion** — тот же ранговый фьюжн с `k=60`, который Octobrain уже использует для объединения BM25 и векторного поиска внутри хранилища. RRF работает по рангам и не зависит от масштаба: воспоминание, которое хорошо встаёт по многим запросам, обходит то, что выстреливает по одному. Теперь декомпозиция запроса окупается так, как и должна. Это чистая математика — без LLM, без лишнего конфига, — а `rrf_fuse` — это маленькая, покрытая юнит-тестами функция, которой можно доверять.

---

## Recall знает, что актуально — ранжирование с учётом Supersedes

Факты устаревают. Вы решили использовать Postgres, а через шесть недель переключились на SQLite. Обе заметки в памяти, обе матчат «какую базу мы используем» — и старому ответу нечего делать в победителях.

В Octobrain всегда был тип связи `Supersedes`, но он определялся, парсился и хранился — а потом **никогда не читался при извлечении.** Готовая возможность, лежащая мёртвым грузом.

0.9.0 подключает его. Когда активное ребро `X Supersedes M` помечает результат как устаревший, извлечение **мягко понижает** устаревший (×0.1 — никогда не удаляя), так что актуальный факт поднимается наверх, а история остаётся доступной для запросов. Два намеренных предохранителя:

- **Рёбра уважаются, но никогда не создаются автоматически.** Распознать настоящее противоречие требует семантического суждения, и Octobrain намеренно держит это вне горячего пути. Вы (или ваш агент) ставите supersede; извлечение его уважает. По MCP инструмент `knowledge` теперь активно направляет агентов создавать supersedes-связи, когда они обновляют факт.
- **Best-effort.** Сбой при поиске связи оставляет результат нетронутым, а не выбрасывает его. В худшем случае вы возвращаетесь к старому поведению, но не хуже.

Актуальное решение побеждает; след назад к старому сохраняется.

---

## Recall с привязкой ко времени — временные фильтры и фильтры релевантности

«Что я решил на прошлой неделе?» — вопрос, который люди задают постоянно, и один семантический поиск отвечает на него плохо: релевантность ничего не знает о времени.

`MemoryQuery` уже поддерживал `created_after` / `created_before` (пробрасываемые прямиком в индекс `created_at`) и `min_relevance` — но MCP-инструмент `remember` никогда их не заполнял. Ещё одна готовая, но мёртвая возможность. 0.9.0 выставляет обе:

- **`created_after` / `created_before`** — дата в ISO-8601 (`2026-06-01`) или полный таймстамп RFC3339. Голая дата означает полночь UTC; всё, что не парсится, просто пропускает фильтр, а не падает с ошибкой.
- **`min_relevance`** — пол качества результата на конкретный вызов, перекрывающий глобальный дефолт.

Инструмент говорит агенту **вычислить окно самому** — он уже знает сегодняшнюю дату, — так что внутри инструмента нет хрупкого парсинга дат на естественном языке. «Что я решил на прошлой неделе» превращается в чистый индексированный range-скан — ровно тот тип привязанных ко времени вопросов, которые измеряет [LongMemEval](https://github.com/xiaowu0162/LongMemEval).

---

## Мы подкрепили это цифрами — retrieval-бенчмарки BEIR

0.7.0 добавила LongMemEval для долгосрочной памяти. 0.9.0 добавляет retrieval-харнесс [BEIR](https://github.com/beir-cellar/beir), чтобы мы могли оценивать **слой ранжирования** — эмбеддинги + фьюжн BM25 + реранкинг — на стандартных датасетах с настоящими qrels, полностью локально, без LLM-судьи.

С дефолтным локальным эмбеддером (`bge-small-en-v1.5`, 384-dim, 33M параметров), измерено как **nDCG@10**:

| Датасет                                     | Octobrain vector | Octobrain hybrid | BM25  | bge-small-en-v1.5 |
| ------------------------------------------- | ---------------- | ---------------- | ----- | ----------------- |
| **SciFact** (5.2K документов, 300 запросов) | 0.722            | **0.742**        | 0.665 | 0.713             |
| **NFCorpus** (3.6K документов, 323 запроса) | 0.341            | **0.363**        | 0.325 | 0.343             |

Колонка только-dense воспроизводит опубликованные BEIR-числа эмбеддера — это харнесс, валидирующий сам себя. Колонка **hybrid** (BM25 + вектор, слитые через RRF, дефолт Octobrain) добавляет **+2 nDCG@10** к голому эмбеддингу и обходит классический BM25 на обоих датасетах. Воспроизведите сами: `cd benches && bash scripts/run_retrieval.sh`. Заявления о recall выше — это заявления, за которые мы можем поручиться.

---

## Под капотом

Более тихие изменения, которые держат всё быстрым и предсказуемым по мере роста корпуса:

- **Две новые ручки поиска, в конфиге.** `search.similarity_threshold` (дефолт `0.3`) — глобальный пол релевантности для семантических запросов; `search.max_results` (дефолт `50`) — жёсткий потолок, который не может превысить ни один вызывающий. Обе теперь проброшены сквозь весь путь, а не заявлены-и-проигнорированы.

  ```toml
  [search]
  similarity_threshold = 0.3   # min relevance for semantic queries (0.0–1.0)
  max_results          = 50    # hard ceiling on results from any search
  ```

- **Таймауты для эмбеддингов и реранкера.** Медленный или зависший вызов провайдера больше не стопорит поиск — `timeout_secs` (дефолт `30`) ограничивает оба, с примером в конфиге реранкера.
- **Фоновая инициализация.** Тяжёлые стартовые задачи запускаются вне горячего пути, так что первый запрос после старта не платит за прогрев индекса.
- **Автоматическое обнаружение scope и переопределение конфига (из 0.8.0).** Octobrain выводит ваш scope из рабочей директории автоматически, а `OCTOBRAIN_CONFIG_PATH` позволяет указать на свой файл конфига — удобно для CI, контейнеров и multi-tenant-сетапов. Блокировки проекта и роли были разведены, так что несвязанные сессии перестают конкурировать.
- **Multi-arch Docker.** Релиз теперь собирает и пушит multi-arch-образы, так что `arm64` (Apple Silicon, Graviton) и `amd64` оба полноценны.
- **Упрочнённая математика ранжирования.** Правки лимита кандидатов реранкера, нормализации RRF, исключения архивированных воспоминаний и PRF-предохранитель подтягивают краевые случаи в новом пути извлечения. Поиск по knowledge теперь также возвращает полную родительскую секцию, а не усечённый фрагмент.

К большинству из них вы не потянетесь напрямую. В этом и смысл.

---

## Как выглядит 0.9.0 на практике

Новый инженер приходит в команду платежей:

1. **Он клонирует репозиторий.** Его директория `.box/` — runbook деплоя, правила «не обходи слой идемпотентности», заметки о том, почему мы ретраим, — индексируется автоматически при первом запуске его агента. Ноль настройки.
2. **Его машина подписывается на org-box** (`octobrain box import …`), так что общекомпанейские конвенции появляются под global scope, в каждом проекте.
3. **Он задаёт агенту размытый вопрос** — «как мы тут обрабатываем сбои вебхуков?» Декомпозиция на несколько запросов разворачивает его, RRF сливает ранги, и запись из командного runbook оказывается наверху.
4. **Решение изменилось в прошлом месяце** — команда ушла от очереди, которую раньше рекомендовала. Старая заметка помечена как superseded, так что побеждает актуальный подход, а история по-прежнему в одном запросе.
5. **Он спрашивает «что мы поменяли на прошлой неделе?»** — временной фильтр, чистый индексированный диапазон, без шума полугодовой давности.

Никто заново не объяснял систему. Знание уже было записано — Octobrain просто сделал его находимым, актуальным и общим.

---

## Апгрейд

С 0.7.x или 0.8.x миграция небольшая.

**Конфиг — `--project` становится `--scope`.** Это единственное breaking-изменение. Везде, где вы передавали `--project <id>` в CLI или параметр `project` MCP-инструменту, используйте вместо этого `--scope <name>`. Главное улучшение: значение теперь — человекочитаемая строка (автоматически выводимая из вашего Git remote), а не хэш, — так что почти всегда вы можете вообще выкинуть флаг и отдать всё на откуп обнаружению.

```bash
octobrain memory remember "api design" --scope acme/web   # was: --project <hash>
```

**Хранилище — делать нечего.** Колонка `scope` и её индекс добавляются при первом запуске, а существующие воспоминания мигрируют на месте. Ни ручных шагов, ни простоя.

**Новый конфиг аддитивен.** `search.similarity_threshold`, `search.max_results` и `timeout_secs` для эмбеддинга/реранкера — все идут с рабочими дефолтами. Добавляйте их, только если хотите тюнить.

**Knowledge boxes — opt-in.** Ничего не меняется, пока вы не закоммитите директорию `.box/` или не запустите `octobrain box import`. Существующие проиндексированные источники не тронуты.

**MCP-клиенты — обновите список инструментов.** `remember` теперь принимает `created_after`, `created_before` и `min_relevance`; `memorize` берёт `--global`. Никаких переименований у пяти основных инструментов — просто новые опциональные поля, которыми может пользоваться ваш агент.

Исходники, бинарники и Docker-образы: [github.com/muvon/octobrain](https://github.com/muvon/octobrain). Что-то сломалось — открывайте issue, мы их читаем.
