mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
ci: proof различает продуктовое дерево и overlay эталонов (#573)
Приёмка эталонов на beta.3 (`ad4000f9`) стоила второго полного Validate —
22 минуты, из них 17–22 на шард мутантов. Причина одна: корпус отпечатка
(`source-fingerprint.mjs`) называет `demo/golden` строкой-каталогом, а
замыкание входов раскрывало каталог во все текстовые файлы под ним, включая
`baselines-index.json`. Индекс становился входом smoke, performance_smoke и
каждого гарда через `serve.mjs`: на реальной паре C→B ключи smoke/perf были
DIFFERENT, отпечатки 181 из 183 браузерных свидетелей менялись, журнал их не
пропускал.
- `check-inputs.mjs`: `BASELINE_OVERLAY` — раскрытие каталога не выдаёт
overlay; явный корень golden и явная ссылка на файл — как были. На паре
C→B: ключи smoke/perf/parity/backend same, golden DIFFERENT; отпечатки
743 из 744 равны; план мутантов B с журналом C — 0–1 на шард вместо 38–44
- `ci-proof.mjs`: составное evidence — product tree без overlay, overlay
(tree, sha256 индекса, run из `Baseline-Reviewed`), content-ключи всех
реюзных job (исполненных тоже); `evaluateCiProof({expected, reviewedRun})`
сверяет с локальным расчётом, fail-closed на ключ, tree, индекс, reviewed
run, маркер с чужим ключом; proof без evidence при ожиданиях — stale
- `release-gate.mjs` / `release-prerelease.mjs`: ожидания считаются на
checkout кандидата (`candidateExpectations`), чужой checkout — notice
- мутанты: `baseline-overlay-leaks-into-every-key`,
`proof-trusts-evidence-it-could-verify`,
`reused-marker-key-unchecked-against-candidate`,
`product-tree-identity-counts-baselines`; перенацелен
`ci-proof-ignores-run-attempt`
- docs: TESTING (правило overlay), DEVELOPMENT (evidence в release proof),
STATUS
Issue: #573
User-Visible: no
This commit is contained in:
@@ -35,6 +35,22 @@ export const BUILD_OUTPUT = [
|
||||
'dist/**', 'custom_components/houseplan/frontend/**', 'demo/srv/assets/**',
|
||||
];
|
||||
|
||||
/**
|
||||
* Принятые эталоны и их индекс — overlay поверх продуктового дерева (#573).
|
||||
*
|
||||
* С ними сравнивает ровно одна проверка — `golden`, и у неё они стоят явным
|
||||
* корнем. Никакая другая job их не читает: смок и перф-смок сверяют бандл с
|
||||
* отпечатком исходников, а отпечаток (`source-fingerprint.mjs`) берёт из
|
||||
* `demo/golden` только `*.mjs`. Но корпус там назван строкой-каталогом, и
|
||||
* раскрытие каталога отдавало всем этим проверкам ещё и
|
||||
* `baselines-index.json` — так приёмка 13 кадров на `v1.76.0-beta.3`
|
||||
* (`ad4000f9`) сменила ключи smoke и performance_smoke и отпечатки 181 из 183
|
||||
* свидетелей с браузерным гардом, и второй полный Validate повторил 22 минуты
|
||||
* работы, которую первый уже сделал. Раскрытие каталога overlay не выдаёт;
|
||||
* явный корень и явная ссылка на файл — как были.
|
||||
*/
|
||||
export const BASELINE_OVERLAY = ['demo/golden/baselines/**'];
|
||||
|
||||
/**
|
||||
* Не входы Validate — с причиной. Каждая запись отвечает на вопрос «кто это
|
||||
* исполняет и почему не Validate».
|
||||
@@ -83,6 +99,7 @@ export const globToRegExp = (glob) => {
|
||||
return new RegExp(`^${re}$`);
|
||||
};
|
||||
const matchesAny = (file, globs) => globs.some((glob) => globToRegExp(glob).test(file));
|
||||
export const isBaselineOverlay = (file) => matchesAny(file, BASELINE_OVERLAY);
|
||||
|
||||
/** Отслеживаемые файлы (git), либо обход дерева там, где git недоступен. */
|
||||
export function trackedFiles(root) {
|
||||
@@ -253,8 +270,13 @@ export function closure(root, entries, { tracked = trackedFiles(root), stopAt =
|
||||
for (const ref of data) {
|
||||
if (trackedSet.has(ref)) { note(ref, file); seen.add(ref); continue; }
|
||||
// каталог по строке — данные; бинарные файлы под ним код по строке не
|
||||
// читает (эталоны golden входят в свою проверку явным корнем)
|
||||
if (isDir(ref)) for (const f of tracked) if (f.startsWith(`${ref}/`) && !BINARY.test(f)) { note(f, file); seen.add(f); }
|
||||
// читает, а overlay эталонов принадлежит только своей проверке (#573):
|
||||
// и то и другое входит в golden явным корнем
|
||||
if (isDir(ref)) {
|
||||
for (const f of tracked) {
|
||||
if (f.startsWith(`${ref}/`) && !BINARY.test(f) && !isBaselineOverlay(f)) { note(f, file); seen.add(f); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [...seen].sort();
|
||||
|
||||
Reference in New Issue
Block a user