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

76 lines
No EOL
4.6 KiB
Markdown
Raw 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: 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 упадёт).