fix: the screenshot witness floor comes from the set, not from survivors

Тот же дефект, что #408 у golden, и в моём же коде из #401. Порог свидетелей
считался от числа кадров, уцелевших на диске: rm docs/images/*.png плюс
объявить все десять через --expect-change — уцелевших ноль, порог ноль,
причины никто не спрашивает, а в манифесте остаётся {"witnesses":0,"floor":0}
без единого слова о произошедшем. Щель была описана в комментарии над самой
функцией и оставлена открытой.

Порог теперь от набора сценариев, свидетели — из тех, с кем есть что
сравнить. Разделение принципиальное: удаление кадров лишает доказательств, но
не должно снижать планку. Первичная съёмка идёт через --no-witnesses
--reason, как теперь и в golden.

Отдельного параметра размера, как в golden, здесь не нужно, и это не
небрежность: `ids` и есть набор — docs-accept.mjs передаёт DOC_SCREENSHOTS, а
verifyDocsCandidate до того отказывает, если набор сцен в кандидате не совпал
с ожидаемым. Пустой ids — отказ, а не ноль.

Попутно Low из #405: повторная приёмка неизменённого набора затирала
acceptance.declared пустым списком. След приёмки отвечает на вопрос «когда
эти пиксели приняли и что тогда объявляли», а обновление отпечатка пикселей
не меняет — значит и стирать ответ не должно. Прежний след сохраняется и
помечается lastWriteWasFingerprintOnly.

Заодно отказ по свидетелям теперь возвращает сами числа: вызывающий печатает
свой вердикт, и сочинять их заново ему не из чего.

Issue: #409
User-Visible: no
This commit is contained in:
Matysh
2026-09-01 17:54:48 +03:00
parent cd0ecf4db2
commit 8119c523fa
3 changed files with 108 additions and 14 deletions
+14 -6
View File
@@ -139,14 +139,22 @@ function main(argv) {
const file = byId.get(id);
copyFileSync(file.from, file.to);
}
// След приёмки отвечает на вопрос «когда эти пиксели приняли и что тогда
// объявляли». Обновление отпечатка пикселей не меняет — значит и стирать
// ответ не должно (#409, Low из #405): прежняя редакция затирала `declared`
// пустым списком, и история терялась при первом же refresh.
const previous = JSON.parse(readFileSync(resolve(ROOT, 'docs/images/screenshots.json'), 'utf8'))
.acceptance;
const accepted = {
...manifest,
acceptance: {
declared: [...decision.replace],
witnesses: decision.witnesses.length,
floor: decision.floor,
...(skipWitnesses ? { witnessesSkippedBecause: skipReason } : {}),
},
acceptance: decision.replace.length
? {
declared: [...decision.replace],
witnesses: decision.witnesses.length,
floor: decision.floor,
...(skipWitnesses ? { witnessesSkippedBecause: skipReason } : {}),
}
: { ...(previous || {}), lastWriteWasFingerprintOnly: true },
};
writeFileSync(
resolve(ROOT, 'docs/images/screenshots.json'),