---
pr: 104
title: Reindex memory + update SKILL.md/AGENTS.md for kebab-case tools
---

## Что сделано

Финальная фаза починки памяти (issue #99, часть #94). После PR #100–#103
(Python safe, 5 TS tools, E2E tests, remove plugin + Rust) — переиндекс + docs.

### 1. Переиндекс памяти через Python

Запущен `uv run python -m src.memory index` из `/root/workspace/opencode-config`.
Env vars (`OPENAI_BASE_URL`, `OPENAI_API_KEY`, `OPENAI_EMBEDDING_MODEL=qwen/qwen3-embedding-8b`)
наследованы из окружения — OpenRouter ответил.

Результат:
- `.rag/index.json` — 239 MB (было 220 MB), 2584 entries (было 2379), 4096-dim embeddings
- `.rag/meta.json` — создан, `version: "qwen/qwen3-embedding-8b:512:64"` (Python формат, `version` key — НЕ `model_id` который был Rust)
- `.rag/reindex.log` — финальная строка `done: total=86 took=286s changed=86 unchanged=0 deleted=0` (incremental: 86 изменившихся файлов переиндексировано, остальные merged из старого index.json)
- `.rag/index.bin` — НЕ существует (Rust, удалён в PR #103)
- Время: 2026-07-26 22:55 (свежее)

### 2. `OPENAI_EMBEDDING_BATCH_DELAY` — добавлена поддержка в код + `.env.example`

Issue #99 просил добавить `OPENAI_EMBEDDING_BATCH_DELAY=0.5` в `.env.example`, но
embedder.py НЕ поддерживал эту env var. Добавлена:
- `src/memory/embedder.py`: `BATCH_DELAY = float(os.environ.get("OPENAI_EMBEDDING_BATCH_DELAY", "0"))` + `time.sleep(BATCH_DELAY)` между батчами (только если `BATCH_DELAY > 0` и не последний батч)
- `.env.example`: `OPENAI_EMBEDDING_BATCH_DELAY=0.5` с комментарием про OpenRouter rate limits
- Default `0` (без задержки) — backwards compatible, не ломает существующие вызовы

Проверка: env var уже set в окружении (`=1`), import OK, E2E 4 passed.

### 3. SKILL.md (memory) — обновлён

`.opencode/skills/memory/SKILL.md`:
- Добавлена секция "Аритектура (progressive enhancement)": keyword всегда, semantic если `OPENAI_BASE_URL` set, fallback (OpenRouter упал → keyword), auto-setup (первый `memory-save` всё создаёт), `memory-doctor` как read-only диагностика
- Убрано упоминание `@mathew-cf/opencode-memory` plugin (было "Плагин удалён" — стало "без wrapper-hop, без MCP-плагина")
- Убрано упоминание `memory-setup` (удалённый tool)
- Исправлен default путь: `~/opencode-memory` (устаревший) → `/root/.local/share/opencode/opencode-memory` (актуальный, соответствует `_memory-shared.ts:17`)
- Tools уже были kebab-case (`memory-search`, `memory-save`, `memory-list`, `memory-access`, `memory-doctor`) — проверено, не требовало правок

### 4. AGENTS.md — обновлён

`AGENTS.md` (root):
- Tool Usage Policy таблица — уже содержала 5 kebab-case tools (`memory-doctor`, `memory-save`, `memory-search`, `memory-list`, `memory-access`)
- Убрано упоминание `memory-setup` из описания `memory-doctor` (было "замена `memory-setup`" — стало чистое описание)

### 5. Stale references — найдены и обновлены

Поиск `grep -rnE "memory_(search|save|list|access|setup|doctor)"` по `.opencode/`, `docs/`, `AGENTS.md`:

**Активные файлы (обновлены):**
- `.opencode/skills/memory/SKILL.md` — `memory-setup` упоминание убрано
- `.opencode/skills/run-pipeline/SKILL.md` — `memory_save` → `memory-save` (2 места), `app_data/opencode-memory` → `<memory_dir>/repos/...`
- `.opencode/skills/repo-init/SKILL.md` — `memory_save` → `memory-save` (gotcha-блок)
- `.opencode/skills/release/SKILL.md` — `memory_save` → `memory-save` (gotcha-блок)
- `.opencode/skills/configure-opencode/SKILL.md` — `memory_save` → `memory-save` (gotcha-блок)
- `.opencode/skills/add-skill/SKILL.md` — `memory_save` → `memory-save` (gotcha-блок)
- `.opencode/skills/spec/SKILL.md` — `memory_search` → `memory-search` (6 мест, replaceAll)
- `.opencode/skills/issue/SKILL.md` — `app_data/opencode-memory` → `<memory_dir>/repos/...`
- `.opencode/agents/memory-syncer.md` — `memory_save` → `memory-save` (2 места), `app_data/opencode-memory` → `<memory_dir>` (3 места)
- `.opencode/commands/spec.md` — `memory_search` → `memory-search`
- `.opencode/tools/memory-access.ts` — `memory_save` → `memory-save` (user-facing message)
- `.opencode/tools/memory-doctor.ts` — `memory_save`/`memory_search` → `memory-save`/`memory-search` (4 user-facing messages)
- `.opencode/tools/memory-search.ts` — `memory_save` → `memory-save` (user-facing message)

**Исторические файлы (НЕ тронуты — snake_case отражает реальные имена на момент написания):**
- `docs/decisions/*.md` — 20+ ADR (ADR-014, 022, 023, 024, 026, 030, 032, 033, 035, 036, 037, 038, 039, 043, 045)
- `docs/handoff/*.md` — 15+ handoffs (pr-36, 53, 57, 63, 71, 75, 77, 78, 80, 83, 89, 101, 103)

### 6. Memory file `technical/rag-cli-embeddings-model.md` — переписан

`~/.local/share/opencode/opencode-memory/technical/rag-cli-embeddings-model.md`:
- Был: описание Rust rag-cli как активного (candle-transformers, all-MiniLM-L6-v2, 384-dim, GLIBC 2.39)
- Стал: описание Python + OpenRouter как единственного пути semantic (qwen/qwen3-embedding-8b, 4096-dim, progressive enhancement, auto-setup)
- Зафиксировано что удалено: `@mathew-cf/opencode-memory` plugin, `@mathew-cf/rag-cli` Rust binary, `setup-memory.sh`, `memory-setup.ts`, `.rag/index.bin`, `meta.json` с `model_id`
- Ссылки на ADR-030, 036, 043, 045

### 7. E2E тест

`RUN_LIVE=1 uv run pytest tests/test_memory_tools_e2e.py -x -q --no-cov` — 4 passed (до и после правок embedder.py).

## Почему

PR #100–#103 сделали инфраструктуру (Python safe, 5 TS tools, E2E, remove plugin + Rust),
но:
- Индекс был старый (17:19, без `meta.json` — Python incremental reindex не мог определить version mismatch)
- Документация (SKILL.md, AGENTS.md, skills, agents, TS tools) содержала stale snake_case tool names (`memory_save`, `memory_search`) — agents могли вызывать несуществующие tools
- `OPENAI_EMBEDDING_BATCH_DELAY` была в issue #99 как требование, но не поддерживалась в коде — добавление в `.env.example` без поддержки вводило бы в заблуждение
- Memory file `rag-cli-embeddings-model.md` описывал Rust rag-cli как активный — агенты могли пытаться использовать удалённый путь

Без этого PR: semantic search работал (index.json был), но docs лгали агентам про tool names → агенты могли вызывать `memory_save` (snake_case) и получать "tool not found".

## Pending

— (переиндекс выполнен, env vars были в окружении)

## Watch out

- **Reindex требует env vars** (`OPENAI_BASE_URL`, `OPENAI_API_KEY`). Без них `embed_texts` возвращает `None`, индекс не строится. Keyword search продолжает работать. Если env vars отсутствуют при деплое — reindex нужно запустить вручную после настройки env.
- **`OPENAI_EMBEDDING_BATCH_DELAY` default `0`** в коде — backwards compatible. `.env.example` рекомендует `0.5` для OpenRouter. В текущем окружении set `=1` (унаследовано).
- **`docs/decisions/` и `docs/handoff/` содержат snake_case** (`memory_save`, `memory_search`) — это исторические записи, отражают реальные имена tools на момент написания. НЕ трогать.
- **Reindex был incremental** (86 changed файлов, 286s) — не полный. Полный reindex при `meta.json` отсутствии или `version` mismatch. Если нужен полный — удалить `.rag/meta.json` + `.rag/index.json` и запустить снова.