125 lines
6.9 KiB
Markdown
125 lines
6.9 KiB
Markdown
# memo
|
||
|
||
Локальная библиотека заметок с семантическим поиском.
|
||
|
||
> **Как этим пользоваться — [`MANUAL.md`](MANUAL.md).** Пошаговая инструкция для человека:
|
||
> установка, команды, подключение к агенту, что мониторит демон, что можно удалять.
|
||
> Остальной README — для разработки.
|
||
|
||
**Markdown на диске — истина, `.db` рядом — пересобираемый кэш.** Агент (или человек) пишет и
|
||
читает обычные `.md`-файлы своими штатными средствами: `memo` не требует ни специального API записи,
|
||
ни изменения привычек. Он следит за файловой системой, держит рядом с каждой папкой-темой
|
||
индекс (SQLite + sqlite-vec + FTS5) и отвечает на смысловые вопросы гибридным поиском
|
||
(BM25 + вектор + RRF).
|
||
|
||
## Статус
|
||
|
||
Реализовано и принято на эталонном корпусе. 38 тестов, мутационная проверка, сквозной recall@5 = 20/20.
|
||
|
||
| Что | Вердикт приёмки |
|
||
|---|---|
|
||
| юнит-тесты всех модулей | ✅ |
|
||
| мутационная проверка (13 мутаций) | ✅ все убиты |
|
||
| индексация: 3 коллекции, повторный прогон — 0 обновлений | ✅ |
|
||
| recall@5 на эталонном корпусе (sem 20/20, lex 3/3) | ✅ |
|
||
| MCP-протокол живым клиентом + холодный старт | ✅ |
|
||
|
||
## Идея
|
||
|
||
- Коллекций (папок-тем) — сколько угодно; они не мешают друг другу.
|
||
- **Коллекция — каталог, в котором есть `*.md` напрямую** (не в подкаталогах). Вложенные папки
|
||
без своих заметок коллекциями не считаются — иначе одни и те же файлы индексируются по нескольку раз.
|
||
- Индекс каждой коллекции живёт в её `.memo/index.db` и **удаляется без потерь** — пересобирается.
|
||
- Поиск — обычный read-only инструмент; записи в markdown он не делает никогда.
|
||
- Только локально: эмбеддинг на CPU, сеть не нужна ни при индексации, ни при поиске.
|
||
|
||
## Состав (JVM-first, один Gradle-проект)
|
||
|
||
```
|
||
memo-cli # memo index|search|status — ручные проверки и приёмка без агента
|
||
memo-core # чанкер по заголовкам, sqlite-схема, инкрементальная переиндексация, гибридный поиск
|
||
memo-watch # демон: WatchService + debounce + реконсиляция по mtime
|
||
memo-mcp # MCP-сервер (stdio): memo_search / memo_status / memo_reindex
|
||
```
|
||
|
||
`memo-core` не знает ни про watcher, ни про MCP — это драйверы поверх ядра.
|
||
|
||
## Быстрый старт
|
||
|
||
```bash
|
||
./gradlew installDist # собрать все дистрибутивы
|
||
|
||
CLI=memo-cli/build/install/memo/bin/memo
|
||
$CLI index ~/notes # проиндексировать дерево (коллекции найдутся сами)
|
||
$CLI search ~/notes "чем чинят карточку в jellyfin"
|
||
$CLI search ~/notes "76.132" --mode lex --json
|
||
$CLI status ~/notes
|
||
```
|
||
|
||
MCP-сервер (stdio), регистрируется как обычный MCP-сервер:
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"memo": {
|
||
"command": "/opt/memo/memo-mcp",
|
||
"env": { "MEMO_MODEL_DIR": "/opt/memo/models/siglip2" }
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Инструменты: `memo_search(path, query, k, mode)`, `memo_status(path)`, `memo_reindex(path)`.
|
||
`memo_search` **сам создаёт индекс**, если его ещё нет — можно просто писать `.md` и сразу искать.
|
||
|
||
Демон слежения (для правок мимо агента — людьми, git, сторонними редакторами):
|
||
|
||
```bash
|
||
memo-watch/build/install/memo-watch/bin/memo-watch ~/notes
|
||
```
|
||
|
||
## Приёмка
|
||
|
||
```bash
|
||
bash scripts/accept.sh # полный прогон: сборка, тесты, мутации, индекс, recall, MCP
|
||
bash scripts/accept.sh --fast # то же без мутационной проверки (самая долгая)
|
||
```
|
||
|
||
Правило проекта: **«зелёная сборка» ничего не доказывает.** Тесты проверяются мутациями
|
||
(`e2e/mutations.tsv`): боевой код ломается, и нужный тест обязан упасть. Выжившая мутация —
|
||
дыра в покрытии, а не удача. Приёмка идёт на реальном корпусе (`scripts/make_e2e_corpus.sh`),
|
||
а не на моках.
|
||
|
||
## Документы
|
||
|
||
| Документ | Что внутри |
|
||
|---|---|
|
||
| [`MANUAL.md`](MANUAL.md) | **инструкция для человека**: как пользоваться, команды, подключение к агенту |
|
||
| [`docs/SPEC.md`](docs/SPEC.md) | полная спека: модель данных, индекс, маршрутизация, watcher, интерфейс, приёмка |
|
||
| [`TASK.md`](TASK.md) | ТЗ для исполнителя: стек, схема БД, контракты, чего не делать |
|
||
| [`TESTING.md`](TESTING.md) | тест-план: приёмочные проверки, команды, признаки провала |
|
||
| [`docs/orders/`](docs/orders/) | журнал заказов исполнителю — с доказательствами дефектов, а не «сделай хорошо» |
|
||
|
||
## Зависимости (проверено 02.10.2026)
|
||
|
||
| Что | Координата | Откуда |
|
||
|---|---|---|
|
||
| SQLite + sqlite-vec + FTS5 | `pw.binom.db:ksqlite:0.1.4` | Maven Central |
|
||
| Текстовый эмбеддинг (SigLIP2 int8, 768 dims) | `pw.binom.ai.embeddingtext:api:5` + `:siglip:5` | `http://nexus.xx/repository/caffeine/` |
|
||
|
||
Модель (в артефакты не входит, скачивается отдельно):
|
||
|
||
```bash
|
||
mkdir -p models/siglip2
|
||
curl -fSL -o models/siglip2/text_model_int8.onnx http://static.binom.pw/models/siglip2/text_model_int8.onnx # 283M
|
||
curl -fSL -o models/siglip2/tokenizer.model http://static.binom.pw/models/siglip2/tokenizer.model # 4.2M
|
||
```
|
||
|
||
## Требования
|
||
|
||
JDK 21. Индекс и поиск работают офлайн после скачивания модели.
|
||
|
||
## Лицензия
|
||
|
||
Apache-2.0.
|