* 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>
3.3 KiB
3.3 KiB
| pr | title |
|---|---|
| 102 | E2E coverage for 4 hybrid-memory scenarios |
Что сделано
Создан tests/test_memory_tools_e2e.py с 4 E2E сценариями, покрывающими гибридную
память (keyword + semantic):
- zero-config keyword-only — поиск работает без
OPENAI_BASE_URL(semantic возвращает[]), keyword через ripgrep находит файл. - full hybrid — semantic находит по точному термину и синониму (через embedding), keyword находит по точному слову.
- fallback при падении OpenRouter — при невалидном
OPENAI_API_KEYsemantic возвращает[](401 не retryable → embedder returns None), keyword работает. - удаление файла — после удаления .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 + pollreindex.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) — добавлено явно.