opencode-config/docs/handoff/pr-124-keyword-search-out-of-box.md
Sergey 7249f1fcb5
fix(memory): keyword search out-of-box + doctor gaps + tests (#124)
* fix(docker): add system ripgrep via apt for keyword search fallback

* fix(ci): install ripgrep and npm deps for keyword search in CI

* fix(memory-search): warn when ripgrep not resolvable instead of silent skip

* fix(memory-doctor): check rg status, arch mismatch, and require errors

* test(memory): add keyword search and doctor unit tests

* test(memory): unskip e2e keyword tests without RUN_LIVE

* docs(handoff): add handoff and ADR for keyword search fix

* test(memory): remove unused var in keyword search test

* docs(handoff): set PR number to 124

* docs(project-map): update after structural changes (PR#124)

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-29 17:20:59 +03:00

4.6 KiB
Raw Permalink Blame History


pr: 124 title: fix(memory): keyword search out-of-box + doctor gaps + tests

Что сделано

  • Dockerfile: добавлен ripgrep в apt-get install (строки 3-16). System rg = fallback; @vscode/ripgrep в npm install -g (строка 38) остаётся primary path.
  • ci.yml (job test): после setup-node@v4 добавлены apt-get install -y ripgrep и npm ci (working-directory: .opencode) — CI теперь устанавливает ripgrep и npm-deps для keyword search.
  • memory-search.ts (~строка 312): при rgBin===null пишет warning в stderr (ripgrep not resolvable — keyword search disabled) вместо молчаливого skip. Аналогичный warning в category-fallback блоке.
  • memory-doctor.ts — закрыты 4 gap'а:
    • G9: checkRipgrep возвращает { lines, rgWorks } где rgWorks = rgBin !== null && r.status === 0; formatDoctorReport и allGreen используют rgWorks, а не rgBin !== null.
    • G5: resolveRgBinary({ allowSystemFallback: true }) в execute (консистентно с memory-search.ts:305).
    • G3: при rgBin===null (npm-пакет не найден) — строка с подсказкой npm package missing — run npm ci in .opencode/.
    • G2: detectArchMismatch() — если rgBin path содержит 'darwin' при process.platform === 'linux' (и обратные комбинации) + arch mismatch (arm64 vs x64) → строка arch mismatch: binary platform != runtime platform в отчёт.
  • tests/test_memory_keyword_search.ts (новый): 5 TS unit-тестов для resolveRgBinary() (npm-package, system-fallback, null-nothing, null-no-fallback) + memory-search stderr warning при rgBin===null.
  • tests/test_memory_doctor.ts (новый): 4 TS unit-теста — allGreen false при битом бинарнике (G9), allGreen true при рабочем (regression guard), arch-mismatch detection (G2), npm-missing hint в report (G3).
  • tests/test_memory_tools_e2e.py: убран глобальный pytestmark skipif(RUN_LIVE). Keyword-тест test_zero_config_keyword_only теперь запускается БЕЗ RUN_LIVE. Semantic-тесты (hybrid, fallback, deletion) имеют individual skipif(not RUN_LIVE).

Проверки: pytest tests/ -x -q 427 passed, 6 skipped; ruff check OK; ruff format --check OK.

Почему

README заявлял keyword search как "always works", но:

  1. System rg не был установлен нигде (Dockerfile/CI/host) — только хрупкий volume-mount npm-пакета.
  2. CI не устанавливал ripgrep ни через apt, ни через npm ci для .opencode/package.json.
  3. memory-search молча пропускал keyword search при rgBin===null — без warning, что затрудняло диагностику.
  4. memory-doctor имел 4 расхождения: allGreen проверял rgBin!==null а не r.status===0, allowSystemFallback расходился с memory-search, нет arch-mismatch detection, require-ошибки не попадали в отчёт.
  5. E2E-тесты скипались без RUN_LIVE целиком — даже keyword-тесты, которые не требуют embeddings API.

Pending

Watch out

  • TS unit-тесты (test_memory_keyword_search.ts, test_memory_doctor.ts) runnable under bun test — bun runtime отсутствует на CI host; файлы валидны как TS, но не запускаются pytest'ом. Это тот же pattern что test_commit_tool.ts / test_merge_pr_tool.ts.
  • detectArchMismatch() использует эвристику по имени path (contains 'darwin'/'linux'/'win32' + 'arm64'/'x64') — не вызывает file command. Покрывает основной случай (@vscode/ripgrep platform dir names).
  • resolveRgBinary({ allowSystemFallback: true }) в memory-doctor теперь консистентен с memory-search — но меняет поведение: если npm-пакет отсутствует но system rg есть, doctor покажет вместо . Это намеренно (doctor = зеркало реального поведения search).
  • CI: npm ci в .opencode/ требует package-lock.json — проверь что он есть в репо (иначе CI упадёт).