Skip to content

Latest commit

 

History

History
113 lines (89 loc) · 7.83 KB

File metadata and controls

113 lines (89 loc) · 7.83 KB

Code Memory Service — техническое видение

Описывает стек и устройство компонентов. Детали реализации конкретного кода намеренно опущены — это видение, не имплементация.

Стек

  • TypeScript на Node.js 24.
  • MCP — официальный SDK (@modelcontextprotocol/sdk), транспорт HTTP.
  • SQLite — встроенный node:sqlite: синхронный (удобно для CLI и HTTP-сервера), без нативных бинарников — собирается кросс-платформенно, FTS5 в комплекте.
  • tree-sitterweb-tree-sitter (WASM, без нативной сборки под каждую платформу) плюс WASM-грамматики нужных языков.
  • File watchingchokidar, два независимых watcher'а.
  • Frontmattergray-matter (разбор YAML-шапки заметок).
  • CLIcommander для one-shot команд; TUIInk.
  • Векторный слой (sqlite-vec) — отложен, схема остаётся совместимой.

Компоненты

Core-библиотека

Вся логика, не знает ни про MCP, ни про CLI:

  • Note store — чтение/запись .md с frontmatter; атомарная запись (.tmp → обновление индекса в транзакции → atomic rename).
  • Index layer — SQLite по схеме из 02, режим WAL, FTS5.
  • Structural indexer — tree-sitter; инкрементально по content hash.
  • Search / ranking — отсечка членства + weight × idf × text_relevance; термы текстового запроса стеммятся (вендорный русский Snowball) и матчатся префиксом — см. 03.
  • Anchor verifier — резолв якорей: symbol/file — SQL и stat, env — парсинг .env*, entity — реестр.
  • Watchers — два, с дебаунсом ~500 мс.

MCP-сервер

Тонкий фронтенд: 8 инструментов из 05, транслирует вызовы в core.

CLI

commander для команд + Ink для TUI-навигатора. Прямой фронтенд над core.

Индексация

  • Реконсиляция на старте контейнера. Сервис при запуске сравнивает content hash файлов с file_index и переиндексирует расхождения — ловит правки, сделанные пока контейнер был выключен. CLI делает то же при своём запуске.
  • Бутстрап. При пустом индексе — полная индексация всего проекта.
  • Watcher на код → изменённый файл переиндексируется tree-sitter'ом, его символы в symbol_index переписываются целиком (delete + insert).
  • Watcher на .memory/ → изменённый .md перечитывается, его строки в note-индексе и FTS обновляются.
  • Пересчёт anchor_status затронутых якорей — при изменении кода, дёшево.

Атомарность и конкурентность

  • Запись заметки атомарна: запись .tmp → транзакция SQLite → atomic rename.
  • Меж-процессный lock-файл в .memory/ на операции записи (CLI и MCP-сервер могут работать одновременно).
  • SQLite WAL — параллельные читатели при одном писателе.
  • ID заметки генерирует сервер (короткий хэш) — на вход create_note не принимается. Replay-идемпотентности по id нет: каждый create_note создаёт новую заметку, коллизия хэша гасится ретраем генерации. Дедуп пересекающихся заметок — задача скилла (searchupdate_note), не писателя.

Конфигурация

Отдельного конфиг-файла (.memory/config.yaml) нет — настраивать в проекте нечего:

  • Игнорируемые пути — индексатор уважает .gitignore проекта (vendor/, node_modules/, storage/ и т.п. уже там). Дизайн и так предполагает git.
  • Языки tree-sitter — определяются по расширению файла; набор поддерживаемых — это грамматики, вшитые в сервис. Файл с неизвестным расширением пропускается: его нет в symbol_index, но file:-якоря на него работают. Vue SFC (.vue) — особый случай: собственной грамматики нет, индексатор извлекает блок(и) <script>/<script setup> и парсит их содержимое JS/TS-грамматикой со сдвигом строк, чтобы symbol:-якоря на Vue-компоненты резолвились.
  • Коэффициенты ранжирования (множители весов, BM25-пол) — константы в core, подбираются эмпирически при разработке, не per-project.

Единственный параметр — корень индексируемого проекта — задаётся при развёртывании (env-переменная и монтирование в docker-compose.yml), не в .memory/. Нужен в основном разработчику системы, чтобы прогонять сервис на разных проектах.

Каталог .memory/ содержит: notes/, entities.md, временный onboarding.md, index.db.gitignore), lock-файл.

Развёртывание

  • memory-service — постоянный сервис в docker-compose.yml целевого проекта, соседний с его контейнерами. Монтирует репозиторий (rw на .memory/, ro на остальное); корень проекта — env-переменная.
  • Транспорт MCP — HTTP: Claude Code из своего контейнера обращается к сервису по compose-сети по имени (http://memory:PORT).
  • Один контейнер на проект — свой .memory/ и свой index.db.
  • Dockerfile лежит в репозитории сервиса. В целевой проект добавляется блок service в его docker-compose.yml; образ собирается локально из SSH-клона приватного репозитория либо берётся из приватного Docker-реестра. Блок коммитится в проект — память «приезжает» вместе с ним.
  • CLI вызывается через docker compose exec memory <команда>.
  • .memory/*.md и entities.md — в git; index.db (вместе с WAL-sidecar'ами index.db-wal / index.db-shm) и lock-файл — в .gitignore.

Отложено

  • Векторный (семантический) поиск — sqlite-vec.
  • Кейс B онбординга как отдельная машинерия (остаётся как guidance в скилле).