opencode-config/docs/handoff/pr-102-e2e-memory-tests.md
Sergey 9d1373a51b
test(memory): E2E coverage for 4 scenarios (#102)
* test(memory): E2E coverage for 4 scenarios

* docs(handoff): set PR number

* style(memory): ruff format e2e test

* docs(project-map): add test_memory_tools_e2e.py after PR#102

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-27 01:32:53 +03:00

58 lines
No EOL
3.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
pr: 102
title: E2E coverage for 4 hybrid-memory scenarios
---
## Что сделано
Создан `tests/test_memory_tools_e2e.py` с 4 E2E сценариями, покрывающими гибридную
память (keyword + semantic):
1. **zero-config keyword-only** — поиск работает без `OPENAI_BASE_URL` (semantic
возвращает `[]`), keyword через ripgrep находит файл.
2. **full hybrid** — semantic находит по точному термину и синониму (через
embedding), keyword находит по точному слову.
3. **fallback при падении OpenRouter** — при невалидном `OPENAI_API_KEY` semantic
возвращает `[]` (401 не retryable → embedder returns None), keyword работает.
4. **удаление файла** — после удаления .md + reindex, ни semantic, ни keyword не
находят удалённый файл.
Все тесты маркированы `@pytest.mark.skipif(not RUN_LIVE)` — запускаются только с
`RUN_LIVE=1`. Без env — 4 skipped.
Вспомогательные функции:
- `_rg_search(pattern, dir)` — keyword через ripgrep (subprocess), fallback на
`/root/.cache/opencode/bin/rg` если нет в PATH.
- `_semantic_search(query, index_dir, env)` — semantic через `python3 -m
src.memory search --json` (subprocess), с передачей кастомного env.
- `_reindex(memory_dir, index_dir)` — reindex + poll `reindex.log` до `done:`.
- `_make_memory_file(dir, term, synonym)` — tmp .md с frontmatter + уникальным
термином `zzuniqtestterm42` + опциональным синонимом.
## Почему
Фаза 1 (PR #100) сделала Python backend safe (lazy-init, return None). Фаза 2
(PR #101) создала 5 TS tools. Нужна E2E гарантия что keyword fallback работает
когда semantic недоступен — без E2E регрессии: lazy-init поломался → все tools
падают; fallback сломался → semantic-up → memory-down.
Подробное обоснование в `technical/memory-keyword-vs-semantic-decision.md` —
гибрид выбран вместо semantic-only именно из-за стабильности keyword path.
## Pending
## Watch out
- Тесты требуют `OPENAI_BASE_URL`, `OPENAI_API_KEY`, `OPENAI_EMBEDDING_MODEL` в env
(реальный OpenRouter, не mock). Запуск: `RUN_LIVE=1 uv run pytest
tests/test_memory_tools_e2e.py -v --no-cov`.
- Сценарий 4 (deletion) требует dummy-файл в memory_dir — иначе `run_index`
возвращает по `if not md_files` без обновления `index.json`, и удалённая запись
остаётся в индексе. Добавлен `_make_dummy_file`.
- `rg` может быть не в PATH — `_rg_bin()` пробует `shutil.which` затем
`/root/.cache/opencode/bin/rg`, pytest.skip если нет.
- Timeout: сценарий 3 — 300с (хотя 401 не retryable и embedder returns None
быстро, на всякий случай), сценарии 2/4 — 180с.
- Ruff: `subprocess.run` требует `check=False` (PLW1510) — добавлено явно.