diff --git a/decisions/2026-05-06-kb-search-overhaul.md b/decisions/2026-05-06-kb-search-overhaul.md new file mode 100644 index 0000000..75d80ee --- /dev/null +++ b/decisions/2026-05-06-kb-search-overhaul.md @@ -0,0 +1,101 @@ +--- +date: 2026-05-06 +type: decision +tags: [kb, openclaw, search, fts, infra, summary] +status: applied +--- + +# Перестройка KB-поиска и синхронизации (8 фаз за один день) + +## Что было до + +Запрос «OpenWRT Липки» Максимке возвращал `netbird-inventory.md`, потому что: +- слова «Липки» во всём vault'е была одна строка в табличке инвентаря, +- слово «OpenWRT» статистически перевешивали НИИКН-документы (`govru-quickfix`, `niikn-openwrt-awg-fix`), +- кросс-ссылок и aliases не было, embeddings не было, +- лаг push→бот доходил до 16 минут (cron `*/5` Mac→Gitea + cron `*/15` Gitea→openclaw). + +Пользователь жаловался: «бот путает, я ему про Липки, он мне про НИИКН». + +## Что сделано + +| Фаза | Эффект | +|---|---| +| 1. Embeddings (ollama+bge-m3) | ⛔ откачено — openclaw 2026.5.2 при `provider: ollama` шлёт inputs целиком, ollama тратит >5 мин/запрос, undici fetch валится по headers timeout. ollama на LXC 132 готова (uptime, bge-m3 1024d), но сторона openclaw нуждается в фиксе chunking | +| 2. Webhook + auto-reindex | Gitea push→listener (HMAC SHA-256)→`kb-pull.sh`→`openclaw memory index`. **push→FTS: 15 мин → 50 c**. См. [[../snippets/openclaw-kb-webhook]] и [[2026-05-06-openclaw-kb-webhook-deployment]] | +| 3. objects-map.json + _index.md | Скрипт `scripts/kb-objects-map.py` парсит netbird-inventory + frontmatter и пишет JSON для бота + human-readable [[../projects/_index]]. Базовый структурный слой | +| 4. Stubs + frontmatter | Создано 6 README (`znamenskoye`, `mmfb`, `lipki` уже был, + 4 stub'а клиентских OpenWrt). Обогащён frontmatter в `niikn`, `dttb`, `glavtorg`, `krasnogorsk`, `zelenograd` с aliases для netbird-имён. **38 → 14 orphan-пиров** | +| 5.1. Слить дубли видео | Удалён `dttb/video-surveillance-report.md` (297 строк, неполная копия), canonical `videonablyudenie-znam.md` обогащён aliases | +| 5.2. Архив audit/ | 18 устаревших drift-отчётов 2026-04-* перенесены в `audit/archive/`, в active остались 7 свежих | +| 6. Recall + dreaming | `openclaw memory promote --apply`: 17/39 коротких воспоминаний переехали в долгую. `dreaming.enabled=true` (cron `0 3 * * *`). Weekly cron на promote | +| 7. Расширенный kb-audit | Скрипт `scripts/kb-objects-audit.py` пишет еженедельный отчёт с score: проверяет frontmatter, online-orphans, битые wiki-ссылки. Первый запуск — score=84 (12/12 frontmatter ✓, 3 online orphan, 26 битых wiki) | +| 8. UX бота | `memorySearch.query.minScore=0.4`, IDENTITY.md разводит двух Максимок (homelab vs НИИКН), INFRASTRUCTURE.md переписан как навигатор по vault'у | + +## Метрики до / после + +| Параметр | До | После | +|---|---|---| +| «OpenWRT Липки» top-1 | `netbird-inventory.md` ❌ | `projects/lipki/README.md` ✅ | +| «Антон клиент Звенигород» top-1 | ничего | `projects/lipki/README.md` ✅ | +| «AgentDVR ЧОП Знаменское» top-1 | три дубля | `videonablyudenie-znam.md` ✅ | +| «Константин Вишневый сад» top-1 | `netbird-inventory.md` | `projects/vishnevyy-sad/README.md` ✅ | +| Лаг push → видно боту | 5–16 мин | **~50 секунд** | +| Проектов с netbird-привязкой | 0 | **9** | +| Структурный объект-граф | нет | `objects-map.json` (34 entries) | +| Online orphan-пиров | ~30+ | **3** | +| Auto-reindex после pull | нет | есть | +| Recall promoted | 0 (mёртв 16 дней) | 17 + weekly cron | +| Dreaming | off | on (ночной cron) | +| FTS-шум audit/ | 24 файла | 7 active + 18 в archive | + +## Грабли (для будущей памяти) + +1. **Gitea SSRF-protection.** Без `webhook.ALLOWED_HOST_LIST` в `app.ini` Gitea silently отказывает доставлять webhook на private IP. В docker-логах: `webhook can only call allowed HTTP servers, deny '10.0.0.239'`. Listener при этом получает 0 запросов, journal пустой. + +2. **`flock -n` теряет двойные push.** Если webhook прилетел во время pull/reindex — non-blocking lock молча выходит. Заменить на `flock -w 180`. + +3. **openclaw 2026.5.2 ollama-провайдер игнорирует chunking.** При `provider: ollama` шлёт файлы целиком в `/api/embed`, ollama buffer растёт до 700 MB, обработка >5 мин, fetch валится. Не лечится `chunking.tokens=512`, `nonBatchConcurrency=1`, `batch.enabled=false`. Bug либо в openclaw, либо неочевидный конфиг-флаг. + +4. **substring matching → false positives.** Alias `cloud` подхватывал `Cloud-NIIKN New niikn.com`. Перешли на exact-match с нормализацией `ye→e`. Aliases теперь должны содержать **полные** имена пиров как в netbird-inventory. + +5. **Heredoc через ssh с backticks** — bash интерпретирует backticks как command-substitution внутри пути файла. Для записи структурных markdown'ов с inline-кодом — пушить через base64 или scp/pct push, не heredoc. + +6. **`git commit` без `-a` или явного `git add`** забирает только staged. Удаление через `git rm` помечается автоматом, а modify — нет. Один коммит может оставить часть правок несинхронизированными — дополнительный коммит лечит. + +## Что отложено + +| Задача | Причина | Когда возвращаться | +|---|---|---| +| Векторный поиск через ollama | bug в openclaw 2026.5.2 ollama-провайдере | при апгрейде openclaw, или попробовать `provider: local` (transformers.js встроен в openclaw) | +| 14 orphan-пиров (Денис Тихая, DESKTOP-2IOQS54 Saransk, KOMPUTER, MastaNotebook, …) | нужны факты от Олега чьи это машины | по мере выяснения — добавлять в aliases подходящих проектов | +| 26 битых wiki-ссылок | автоматический фикс не всегда возможен (некоторые цели реально удалены) | semi-auto проход: показать список, для очевидных — починить, остальное — оставить TODO | +| Singleton-проекты (`projects/*.md`) без frontmatter | не критично — они top-level note'ы | при касании | + +## Артефакты в vault + +- [[../projects/lipki/README]], [[../projects/znamenskoye/README]], [[../projects/mmfb/README]] +- [[../projects/sergey/README]], [[../projects/benilux/README]], [[../projects/vishnevyy-sad/README]], [[../projects/openwrt-4/README]] +- [[../projects/_index]] — авто-генерированный реестр +- `audit/objects-map.json` — машинно-читаемый граф +- [[../audit/2026-05-06-objects-audit]] — первый health-check +- `scripts/kb-objects-map.py`, `scripts/kb-objects-audit.py` +- [[../snippets/openclaw-kb-webhook]] +- [[2026-05-06-openclaw-kb-webhook-deployment]] +- frontmatter добавлен в `projects/{niikn,dttb,glavtorg,krasnogorsk,zelenograd}/README.md` + +## Артефакты вне vault + +**LXC 137 (openclaw):** +- `/usr/local/bin/kb-pull-webhook.py` (Python listener, HMAC) +- `/etc/systemd/system/kb-pull-webhook.service` +- Обновлённый `/usr/local/bin/kb-pull.sh` (`flock -w 180`, hash-diff, auto-reindex) +- Cron `0 4 * * 1` weekly memory promote +- Config: `memorySearch.query.minScore=0.4`, `dreaming.enabled=true`, ollama-провайдер откачен (бэкап `/root/.openclaw/openclaw.json.bak.embed-2026-05-06-112441`) +- Переписаны `/root/clawd/IDENTITY.md`, `INFRASTRUCTURE.md` + +**LXC 136 (Gitea):** +- `webhook.ALLOWED_HOST_LIST = 10.0.0.0/24,*.dttb.ru,private` в `/opt/gitea/data/gitea/conf/app.ini` +- Webhook id=1 на репо `oleg/knowledge-base` + +**LXC 132 (code-server):** +- ollama systemd override `OLLAMA_HOST=0.0.0.0:11434, KEEP_ALIVE=24h` (для будущего возврата к embeddings)