fix(memory): setup step 5 check index.json + align docs to real state (#85)

* fix(memory): check index.json not .rag dir in setup step 5

* docs(readme): align to real state after memory PRs

* chore(env): remove dead vars from env example

* docs(handoff): add handoff + ADR-037 for memory setup step5 fix

* docs(handoff): set PR number

---------

Co-authored-by: opencode-agent <agent@opencode.local>
This commit is contained in:
Sergey 2026-07-26 20:12:15 +03:00 committed by GitHub
parent 25cf10baa6
commit 3aa5330003
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 69 additions and 11 deletions

View file

@ -11,7 +11,6 @@ OPENAI_BASE_URL=https://openrouter.ai/api/v1
OPENAI_API_KEY=your-openrouter-api-key
OPENAI_EMBEDDING_MODEL=qwen/qwen3-embedding-8b
OPENAI_EMBEDDING_BATCH_SIZE=50
OPENAI_EMBEDDING_BATCH_DELAY=1
MEMORY_CHUNK_SIZE=512
MEMORY_CHUNK_OVERLAP=64
@ -29,9 +28,6 @@ TELEGRAM_API_ID=your-telegram-api-id
TELEGRAM_API_HASH=your-telegram-api-hash
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
# Redis (optional)
REDIS_PASSWORD=your-redis-password
# Cloudflare Tunnel (optional — see separate tunnel repo)
CLOUDFLARE_TUNNEL_TOKEN=
TUNNEL_DOMAIN=

View file

@ -75,9 +75,9 @@ else
echo " [4/6] hook correct"
fi
# 5. .rag index exists? → memory index (no) | noop (yes)
# 5. .rag/index.json exists? → memory index (no) | noop (yes)
if "$MEMORY_PYTHON" -c "import src.memory" >/dev/null 2>&1; then
if [ ! -d "$MEMORY_DIR/.rag" ]; then
if [ ! -f "$MEMORY_DIR/.rag/index.json" ]; then
echo " [5/7] building RAG index (memory CLI)"
( "$MEMORY_PYTHON" -m src.memory index "$MEMORY_DIR" -o "$MEMORY_DIR/.rag" ) 2>&1 \
|| echo " memory index failed — continuing"

View file

@ -9,7 +9,6 @@ Docker-based AI coding assistant with persistent memory — opencode configurati
```bash
git clone https://github.com/slaid098/opencode-config.git
cd opencode-config
mkdir -p app_data/{workspaces,ssh}
cp .env.example .env # fill in your keys
docker compose up -d
```
@ -31,12 +30,11 @@ opencode # .opencode/ auto-discovered
- `agents/` — subagent definitions (docs-reviewer, memory-syncer, reviewer)
- `commands/` — slash commands (run-pipeline, spec, configure-opencode)
- `skills/` — skill definitions (14 skills)
- `tools/` — custom tools (pipeline-status, spec-status, merge-pr)
- `tools/` — custom tools (commit, create-issue, create-pr, memory-setup, merge-pr, pipeline-status, post-docs-review, post-review, spec-status, tunnel)
- `scripts/` — Python scripts (pipeline-status, spec-status, check-adr-refs, etc.)
- `opencode.json` — main config (providers, MCP servers, permissions)
- `app_data/workspaces/` — agent working directory
- `app_data/ssh/` — SSH keys (not in git)
- `app_data/opencode-memory/` — persistent memory (separate git repo)
- `src/` — Python RAG CLI (memory)
- `docs/` — handoffs, decisions (ADRs), project map
- `.github/workflows/` — CI workflows (ubuntu-latest)
@ -49,16 +47,23 @@ Copy `.env.example` to `.env` and fill in:
|----------|-------------|
| `AI_PROVIDER_BASE_URL` | AI provider API URL |
| `AI_PROVIDER_API_KEY` | AI provider API key |
| `OPENAI_BASE_URL` | Embeddings API URL (OpenRouter default) |
| `OPENAI_API_KEY` | Embeddings API key (OpenRouter) |
| `OPENAI_EMBEDDING_MODEL` | Embedding model (default: `qwen/qwen3-embedding-8b`) |
| `OPENAI_EMBEDDING_BATCH_SIZE` | Embedding batch size (default: 50) |
| `OPENCODE_SERVER_PASSWORD` | opencode server password |
| `GITHUB_TOKEN` | GitHub personal access token |
| `CONTEXT7_API_KEY` | Context7 MCP API key |
| `OPENCODE_MEMORY_REMOTE` | Git remote for your opencode-memory fork (required) |
| `MEMORY_CHUNK_SIZE` | Memory index chunk size (default: 512) |
| `MEMORY_CHUNK_OVERLAP` | Memory index chunk overlap (default: 64) |
| `ANTIDETECT_BROWSER_MCP_URL` | Antidetect browser MCP URL (optional) |
## Memory setup
Memory uses `@mathew-cf/opencode-memory` plugin (hybrid search: ripgrep + local RAG).
Memory uses `@mathew-cf/opencode-memory` plugin (hybrid search: ripgrep + cloud embeddings (OpenRouter Qwen3 8B)).
- `OPENCODE_MEMORY_DIR` env var points to memory directory (default: `app_data/opencode-memory/`)
- `OPENCODE_MEMORY_DIR` env var points to memory directory (default: `/root/.local/share/opencode/opencode-memory`)
- `OPENCODE_MEMORY_REMOTE` must point at your git remote — fork the upstream [`slaid098/opencode-memory`](https://github.com/slaid098/opencode-memory) repo and set the URL in `.env`
- Run `.opencode/scripts/setup-memory.sh` to initialize memory repo

View file

@ -0,0 +1,28 @@
# ADR-037: setup-memory.sh step 5 — check index.json, not .rag dir
## Статус
Accepted (2026-07-26)
## Контекст
setup-memory.sh step 5 проверял наличие директории `$MEMORY_DIR/.rag` через `[ ! -d ... ]`, чтобы решить, нужно ли пересобирать RAG индекс. После внедрения Python memory CLI (PR#75) и wrapper'а для opencode-memory plugin (PR#77), наш формат индекса — `index.json` в директории `.rag/`. Однако оригинальный Rust rag-cli (который plugin использовал до wrapper'а) создаёт `meta.json` + `index.bin` в той же директории `.rag/`.
Баг: если Rust rag-cli уже отработал, директория `.rag/` существует, но содержит stale Rust-формат без `index.json`. Проверка `[ ! -d "$MEMORY_DIR/.rag" ]` возвращает false → step 5 пропускает rebuild → plugin продолжает использовать Rust rag-cli (wrapper не перезаписан, индекс не в нашем формате). End-to-end проверка после PR#77/#83 подтвердила это: wrapper не перезаписывался, meta.json в Rust схеме.
## Решение
Заменить проверку директории на проверку файла индекса:
`[ ! -d "$MEMORY_DIR/.rag" ]``[ ! -f "$MEMORY_DIR/.rag/index.json" ]`.
Теперь step 5 форсирует rebuild, если:
- директория `.rag/` не существует (fresh install), ИЛИ
- директория существует, но `index.json` отсутствует (stale Rust-формат, частичный индекс, удалённый файл).
Это гарантирует, что после первого запуска setup-memory.sh с новым кодом индекс будет в нашем Python memory CLI формате, а wrapper (step 5b) перезапишется при следующем запуске plugin'а.
## Альтернативы
- **Проверять `meta.json` (Rust-формат) и удалять директорию целиком.** Отклонено: деструктивно, может удалить валидный наш индекс при ложном срабатывании. Безопаснее проверять наличие нашего файла, чем absence чужого.
- **Всегда пересобирать индекс (unconditional rebuild).** Отклонено: ломает idempotent-контракт setup-memory.sh (тест `test_idempotent` ожидает, что 3-й запуск = 1-й по snapshot). Rebuild при каждом запуске = ~минута лишней работы + нагрузка на embeddings API.
- **Проверять содержимое `index.json` (схему/версию).** Отклонено: over-engineering для bash-скрипта. Проверка существования файла достаточна — формат валидируется Python memory CLI при загрузке.

View file

@ -0,0 +1,29 @@
---
pr: 85
title: fix(memory): setup step 5 check index.json + align docs to real state
---
## Что сделано
- `.opencode/scripts/setup-memory.sh` step 5: проверка `[ ! -d "$MEMORY_DIR/.rag" ]` заменена на `[ ! -f "$MEMORY_DIR/.rag/index.json" ]`. Теперь скрипт проверяет наличие нашего индексного файла (формат Python memory CLI), а не саму директорию — это форсирует rebuild, если остался stale Rust rag-cli индекс (meta.json + index.bin без index.json).
- `README.md` Quick start: убран `mkdir -p app_data/{workspaces,ssh}` (директории уже в репо с .gitkeep).
- `README.md` Structure: убрана строка `app_data/opencode-memory/` (runtime dir, не в репо); tools list обновлён до актуальных 10 tools (commit, create-issue, create-pr, memory-setup, merge-pr, pipeline-status, post-docs-review, post-review, spec-status, tunnel).
- `README.md` Configuration: таблица расширена с 6 до 13 vars (+7: OPENAI_BASE_URL, OPENAI_API_KEY, OPENAI_EMBEDDING_MODEL, OPENAI_EMBEDDING_BATCH_SIZE, OPENCODE_MEMORY_REMOTE, MEMORY_CHUNK_SIZE, MEMORY_CHUNK_OVERLAP).
- `README.md` Memory setup: "local RAG" → "cloud embeddings (OpenRouter Qwen3 8B)"; default OPENCODE_MEMORY_DIR исправлен с `app_data/opencode-memory/` на `/root/.local/share/opencode/opencode-memory`.
- `.env.example`: удалён `OPENAI_EMBEDDING_BATCH_DELAY` (dead — не используется в embedder.py); удалён `REDIS_PASSWORD` + комментарий (dead — нигде не используется). Telegram и Cloudflare оставлены.
## Почему
После merge PR#77 (setup-memory.sh wrapper) и PR#83 (incremental index) end-to-end проверка показала, что plugin продолжал использовать оригинальный Rust rag-cli: wrapper не перезаписывался, meta.json оставался в Rust схеме, index.bin лежал рядом. Причина — баг в step 5: проверка `[ ! -d "$MEMORY_DIR/.rag" ]` всегда false, если Rust rag-cli уже создавал директорию. Проверка `index.json` (наш формат) форсирует rebuild при рассинхронизации форматов.
README и .env.example устарели после PR#75/#77/#83: инструкции создавали уже существующие директории, описывали "local RAG" вместо cloud embeddings, таблица конфига была неполной, dead env vars вводили в заблуждение.
## Pending
— (после merge: удалить stale Rust rag-cli index вручную при первом запуске setup-memory.sh — step 5 пересоберёт в нашем формате)
## Watch out
- ADR-037 зафиксировал решение проверять index.json, не директорию — при будущих правках setup-memory.sh не откатывать к dir-check.
- README tools list содержит 10 .ts tools (без _shared.ts, который вспомогательный).
- Если добавится новый tool — обновить README Structure tools list.