--- 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` → `/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` → `/repos/...` - `.opencode/agents/memory-syncer.md` — `memory_save` → `memory-save` (2 места), `app_data/opencode-memory` → `` (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` и запустить снова.