69a0ebe0fa
resumesPartialDownload: счётчики Range-запросов и байт; сервер отдаёт 400
без Range для .part — запасной путь «начать заново» закрыт.
failsOnSizeMismatch разделена на два:
- rejectsWrongTotalFromContentRange — сервер соврал в Content-Range,
бьёт в проверку actualTotal != expectedTotal (вторая, достижимая);
- truncatedResponseDoesNotProduceFile — оборванный ответ, по факту ловит
ветку IOException → «не удалось скачать» (а не first size check).
В mutations.tsv убрана строка про if (declaredBody >= 0 && written !=
declaredBody) — через java.net/http недостижимо (оборванный ответ даёт
IOException, не EOF). Добавлена строка про if (expectedTotal >= 0 &&
actualTotal != expectedTotal) — теперь убивает rejectsWrongTotalFromContentRange.
Все 18 мутаций (4 из ModelStore) убиты прогоном mutation_check.py.
3.5 KiB
3.5 KiB
| 1 | # file<TAB>old<TAB>new<TAB>must_fail_test | |||
|---|---|---|---|---|
| 2 | # Прогон: python3 e2e/mutation_check.py --gradle ./gradlew | |||
| 3 | # Правило: мутация обязана уронить ровно тот тест, который её ловит. Выжившая мутация = дыра в покрытии. | |||
| 4 | # no-op мутации (old == new) запрещены — харнесс их отклоняет. | |||
| 5 | # --- memo-core: ksqlite / FTS5 / vec0 --- | |||
| 6 | memo-core/src/test/kotlin/memo/core/CoreSmokeTest.kt | CREATE VIRTUAL TABLE v USING vec0(embedding float[4]) | CREATE VIRTUAL TABLE v USING vec0(embedding float[8]) | vec0KnnRoundTrip |
| 7 | memo-core/src/test/kotlin/memo/core/CoreSmokeTest.kt | floatArrayOf(0.1f, 0.9f, 0.0f, 0.0f) | floatArrayOf(0.0f, 0.0f, 0.0f, 1.0f) | vec0KnnRoundTrip |
| 8 | memo-core/src/test/kotlin/memo/core/CoreSmokeTest.kt | tokenize='unicode61' | tokenize='ascii' | fts5FindsCyrillic |
| 9 | memo-core/src/test/kotlin/memo/core/CoreSmokeTest.kt | SELECT a FROM t | SELECT a+1 FROM t | ksqliteSmoke |
| 10 | # --- Чанкер --- | |||
| 11 | memo-core/src/main/kotlin/memo/core/Chunker.kt | val trimmed = body.trim() | val trimmed = body.uppercase() | fourHashesIsNotAHeading |
| 12 | memo-core/src/main/kotlin/memo/core/Chunker.kt | private const val CHUNK_OVERLAP = 600 | private const val CHUNK_OVERLAP = 0 | longSectionIsSplitWithOverlap |
| 13 | # --- Коллекции (дефект тройного обхода, найден на приёмке) --- | |||
| 14 | # --- Индексатор: пропуск неизменённого файла --- | |||
| 15 | memo-core/src/main/kotlin/memo/core/Indexer.kt | if (existing.mtime == mtime && existing.size == size) {\n return false | if (existing.mtime == mtime && existing.size == size) {\n return true | indexerSkipsUnchangedFile |
| 16 | # --- Поиск: слияние режимов и ограничение k --- | |||
| 17 | memo-core/src/main/kotlin/memo/core/Searcher.kt | if (mode == SearchMode.LEX || mode == SearchMode.HYBRID) lexSearch(query) else emptyList() | if (mode == SearchMode.LEX) lexSearch(query) else emptyList() | hybridCombinesBoth |
| 18 | memo-core/src/main/kotlin/memo/core/Searcher.kt | .sortedByDescending { it.value }.take(k) | .sortedByDescending { it.value }.take(k + 1) | resultsRespectKAndTextLength |
| 19 | # --- MCP: ошибка инструмента обязана помечаться isError --- | |||
| 20 | # --- Watcher: debounce сводит правки к одному вызову --- | |||
| 21 | memo-watch/src/main/kotlin/memo/watch/Watcher.kt | _indexCalls.incrementAndGet() | _indexCalls.get() | modifyTriggersSingleIndexCall |
| 22 | # --- ModelStore: скачивание модели (ModelStoreTest) --- | |||
| 23 | memo-core/src/main/kotlin/memo/core/ModelStore.kt | if (!force && target.isFile && target.length() > 0L) { | if (false) { | skipsExistingWithoutNetwork |
| 24 | memo-core/src/main/kotlin/memo/core/ModelStore.kt | if (expectedTotal >= 0 && actualTotal != expectedTotal) { | if (false) { | rejectsWrongTotalFromContentRange |