Files
houseplan-card/scripts/mutation-registry-check.mjs
T
Claudeandclaude[bot] c68d92f674 process: ratchets get a band over the beta ceiling (#699)
Two-sided ratchets with zero slack made parallel tasks conflict on shared
numbers, recompute them after every rebase and hit a ceiling because a
neighbour merged first (#689 after #691).

- Core lines (test/core-file-budget.test.mjs): a branch may grow up to
  CORE_BAND = 50 lines over the beta ceiling; shrinking no longer fails it.
- Bundle graphs (bundle-budget.mjs): initial View and lazy graphs fail only
  above ceiling + 2 000 B; below the ceiling is not a branch finding. The
  absolute INITIAL_VIEW_GZIP_BUDGET stays the wall.
- Monolith numbers (monolith-metrics.mjs, unused-locals-gate.mjs):
  METRIC_BANDS — 5 for delegates, port members and privates, 25 for host.
  refs, 2 000 B for dist/; a lower number is reported, not failed.
- Browser mutation guards: 200 is a guideline — mutation-gate --check warns
  above it instead of failing; every guard still needs its reason line.
- scripts/ratchets.mjs: `report [--warn]` and `tighten` — on the beta
  candidate the release manager sets every ceiling to the fact in one
  commit; release:prerelease prints loose ceilings as a warning.

Canon: PROCESS.md §3 (browser guards, monolith numbers) and §8 «Храповики»;
docs/TESTING.md.

Issue: #699
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-09-28 22:39:36 +00:00

67 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Cheap structural validation for mutation declarations. Kept out of the CLI
// so adding registry policy does not grow the execution coordinator (#558).
import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import {
BROWSER_GUARD_LIMIT, browserGuardPolicy, readDocumentedBrowserGuards,
} from './mutation-browser-policy.mjs';
import { staticTestSelectionProblems } from './mutation-guard-outcome.mjs';
export function checkMutationRegistry(selected, { allMutants, root, log = console.log }) {
let stale = 0;
let warned = 0;
const readTest = (file) => {
const path = join(root, file);
return existsSync(path) ? readFileSync(path, 'utf8') : null;
};
for (const mutant of selected) {
try {
if (/bundle:sync|bundle-sync\.mjs|rollup -c/.test(mutant.guard)) {
throw new Error('гвард сам собирает бандл — сборку делает раннер (#499)');
}
for (const patch of mutant.patches) {
const source = readFileSync(join(root, patch.file), 'utf8');
const hits = source.split(patch.find).length - 1;
if (hits !== 1) throw new Error(`якорь найден ${hits} раз(а)`);
}
const selection = staticTestSelectionProblems(mutant.guard, readTest);
const error = selection.find((problem) => problem.level === 'error');
if (error) throw new Error(error.text);
for (const problem of selection) {
log(`WARN ${mutant.id}: ${problem.text}`);
warned++;
}
log(`ok ${mutant.id}`);
} catch (error) {
log(`FAIL ${mutant.id}: ${error.message}`);
stale++;
}
}
try {
const policy = browserGuardPolicy(allMutants, readDocumentedBrowserGuards(root));
log(`browser guards: ${policy.count}/${BROWSER_GUARD_LIMIT}`);
if (policy.overLimit) {
// #699: ориентир, а не лимит — цена браузерных свидетелей растёт, но
// удалять чужой мутант ради числа не нужно.
log(`WARN browser guards: ${policy.count} при ориентире ${BROWSER_GUARD_LIMIT} — `
+ 'каждый сверх ориентира держится своей строкой обоснования в реестре');
warned++;
}
for (const mutant of policy.missingReasons) {
log(`WARN ${mutant.id}: browser guard не размечен — добавьте причину в `
+ '`docs/testing-notes/mutation-browser-guards.md` и конкретику в `because`');
warned++;
}
for (const id of policy.staleReasons) {
log(`WARN ${id}: browser-разметка устарела — такого browser guard больше нет`);
warned++;
}
} catch (error) {
log(`FAIL browser guard policy: ${error.message}`);
stale++;
}
if (warned) log(`предупреждений mutation registry: ${warned}`);
return stale ? 2 : 0;
}