Аудит v1.71.0-beta.1 (§3.2 M1/M2/M3/M6/M9) прогнал по мутанту на каждый
контракт: пять снятий защиты не покраснили ни один тест. Восьмой подряд
случай проверок, не умеющих падать, и первый — в бете, закрывавшей #421,
задачу ровно об этом.
Каждый свидетель ниже проверен отрицательным прогоном: мутант краснит
ровно свой тест и не задевает остальные.
1. Полное декодирование растра. `test_supported_raster_headers_and_full_decode`
спрашивал w/h/mime — их даёт header-парсер; обрезка `PNG_1X1[:33]`
теряет IEND и отбивается там же. No-op блока Pillow оставлял 35 pass.
Новый свидетель: PNG с верными сигнатурой, IHDR, IEND, длинами и CRC,
но с текстом вместо zlib-потока в IDAT. Оба прежних теста
переименованы — их имена обещали то, чего они не проверяли.
Пропуск без Pillow остался (validate_asset глотает ImportError
осознанно), но в окружении с Home Assistant отсутствие Pillow теперь
красное само по себе — иначе свидетель молча скипался бы в каноне.
2. Канонизация SVG. `ValidatedAsset(canonical,…)` → `ValidatedAsset(data,…)`
не краснило ничего: все тесты смотрели w/h/mime, ни один — байты.
Свидетель сверяет байты целиком: пролог и комментарий не переживают
канонизацию, пустой элемент сжимается.
Вторая половина — `_check_size(canonical)`. Экранирование `>` в тексте
раздувает документ вчетверо: загрузка 1.84 МиБ канонизуется в 7.35 МиБ
и до сих пор проходила входной контроль. Свидетель — ровно такая.
3. Гард внешних URL. Все три «внешних» кейса корпуса ловились другими
правилами (тег не из словаря, атрибут не из словаря, ветвь href), и
`if False:` не краснило ничего. Свидетель: разрешённый тег, разрешённый
атрибут, пять токенов — сработать может только сам гард, сообщение это
подтверждает.
4. Проекция декора. Единственный кейс задавал flip_h и opacity: 2 → 1;
ожидание неотличимо от «opacity игнорируется», а flip_v не проверялся
вовсе. Свидетели: четыре комбинации отражений, opacity 0.4 и 0 против
заглушки, форма asset_id с согласованным url (прежняя строка ловилась
сравнением url, поэтому регулярку id можно было удалить незаметно).
5. Гард benchmark из #423. Доказательство было циклическим: тест вырезал
из текста подстроку и спрашивал регулярку, находит ли она её, — а
регулярка искала именно её. Динамический режим `--guard-probe`
существовал с #423 и не вызывался ни одним прогоном. Теперь он в
`demo/guard/verify-guard.mjs` (умеет аргументы и файл выше каталога),
а тест из обнаружения требует у нового page-benchmark режим пробы и
запись в верификаторе.
Мутантов в реестре стало восемь новых: четыре бэкендных, три юнитных,
один на пробах гарда. У #423 их было ноль — единственная задача с
циклическим тестом и она же единственная без мутантов.
Гейты: typecheck зелёный; npm test 1790 tests, 1789 pass, 0 fail;
pytest без HA 310 passed, 2 skipped; npm run build зелёный, dist не
изменился (продуктовый код не тронут); mutation-gate --check применяет
все восемь якорей. Полный прогон новых мутантов — следующим шагом.
Issue: #430
User-Visible: no
Проверка `assertSupportBundleOwnership` бросала при
`initialViewGzipBytes >= 291046` — «граф не стал больше, чем на момент
закрытия #423». Запас до порога: пятнадцать байт на бете 1.71.0, сто
четыре сейчас. Пятнадцать байт gzip меньше одной строки локали, поэтому
первый же посторонний коммит получил бы красный CI с сообщением про
копирайт формы поддержки — к которому не имеет отношения.
«Граф не вырос» — критерий приёмки на момент задачи, а не свойство
продукта. Свойство продукта охраняют `INITIAL_VIEW_GZIP_BUDGET` (300000)
и предупреждение о низком запасе: они судят размер целиком и не
привязаны к чужому номеру issue.
Долговечная половина того же контракта — владение графом (маркеры формы
отсутствуют в initial View, присутствуют в ленивом редакторе) — осталась
и по-прежнему падает в обе стороны. Новый тест закрепляет, что размер в
эту функцию вернуться не может: 0, 291046, 10 МБ и `undefined` проходят
одинаково, пока владение соблюдено.
Гейты: typecheck зелёный, npm test 1787/1786 pass 0 fail, npm run build
зелёный (dist побайтово не изменился — продуктовый код не тронут),
node scripts/bundle-budget.mjs зелёный: initial View 290942 Б, бюджет
300000 Б, запас 9058 Б плюс честное предупреждение о запасе.
Issue: #429
User-Visible: no