mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-05 14:19:04 +00:00
test: гейт «новый код не добавляет any»
В src/** сейчас 1034 вхождения явного any в 49 файлах — больше, чем называл аудит (330), потому что монолит с тех пор разделился и его обвязка уехала в houseplan-editor-runtime.ts. Разовая замена такого объёма — месяц риска ради нуля пользовательской ценности, поэтому долг снимается при плановом извлечении подсистем (#34). Задача гейта одна: не давать долгу расти. Судятся только добавленные строки диапазона. Изменённая строка со старым any выглядит в диффе добавленной, и это намеренно: тронул — либо типизируй, либо обоснуй на той же строке `// any-ok: <причина>`. Голый маркер, пустая причина и шаблоны вроде todo, hack, потом не проходят. Ложных срабатываний нет по построению, а не по старанию: текст разбирается парсером TypeScript, и нарушением считается узел AnyKeyword. Регулярка по строке ловила бы слово any в прозе внутри шаблона html и в комментариях; здесь комментарии, строковые литералы, многострочные шаблоны и идентификаторы company, anyOf, manyRooms узлами такого вида не являются вовсе. Проверено исполнением на настоящем дереве, а не только юнитами: пробные коммиты в src/wall-thickness.ts показали, что добавленный any падает с файлом и строкой, типизированная строка в файле с 122 старыми any проходит, any-ok с конкретной причиной проходит, а голый и «todo» — нет, и что any в прозе, строке и идентификаторах не даёт ни одного срабатывания. В job frontend checkout получил полную историю без блобов: diff-aware проверке нужен диапазон, а содержимое старых ревизий — нет. Заодно закрыта ловушка в test/validate-workflow.test.mjs: имя job искалось через indexOf(' frontend:'), а эта строка встречается внутри ` frontend: ${{ ... }}` в outputs job changes, поэтому срез уходил не туда. Теперь имя ищется с начала строки. Четыре мутанта проверены руками, два добавлены в реестр: гейт, судящий все строки, и гейт, принимающий голый маркер. Issue: #342 User-Visible: no
This commit is contained in:
@@ -1004,6 +1004,31 @@ const MUTANT_DEFINITIONS = [
|
||||
replace: ' if (false) {',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'no-new-any-judges-every-line',
|
||||
guard: 'node --test --test-name-pattern="нетронутой строке гейт не блокирует" '
|
||||
+ 'test/no-new-any.test.mjs',
|
||||
because: 'гейт, судящий все строки вместо добавленных, краснеет на 1034 существующих '
|
||||
+ 'вхождениях и будет отключён в первый же день — а долг типизации снимается при '
|
||||
+ 'извлечении подсистем, не разовой заменой (#342)',
|
||||
patches: [{
|
||||
file: 'scripts/no-new-any.mjs',
|
||||
find: ' if (!file.addedLines.has(line)) continue;',
|
||||
replace: ' if (false) continue;',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'no-new-any-accepts-bare-marker',
|
||||
guard: 'node --test --test-name-pattern="только с конкретной причиной" '
|
||||
+ 'test/no-new-any.test.mjs',
|
||||
because: 'голый `// any-ok` — это не обоснование, а способ обойти гейт одной строкой; '
|
||||
+ 'без проверки причины исключение перестаёт что-либо значить (#342)',
|
||||
patches: [{
|
||||
file: 'scripts/no-new-any.mjs',
|
||||
find: ' if (exemption?.ok) continue;',
|
||||
replace: ' if (exemption) continue;',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'invariant-hidden-counts-corner-touch',
|
||||
guard: 'node --test --test-name-pattern="касание углом" test/model-invariants.test.mjs',
|
||||
|
||||
Reference in New Issue
Block a user