mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
Вход агента до первого файла кода стоил ≈ 26 700 слов (аудит 22.09). - docs/process/AUTHOR.md и REVIEWER.md — выжимки PROCESS.md: каждый пункт ссылается на раздел канона, ключевые формулировки дословные; test/process-digests.test.mjs сверяет якоря, ссылки и правила. - scripts/entry-cost.mjs — маршрут чтения по роли и бюджет (автор ≤ 12 000 слов, AC1); AGENTS.md «Read this first» называет те же маршруты. - docs/STATUS.md: блок Snapshot генерирует scripts/status-snapshot.mjs (версии — release-contract, счётчики — inventory, теги — git); feature surface и ранние milestones перенесены дословно в docs/STATUS-FEATURES.md. - docs/TESTING.md — действующая инструкция (684 строки, AC3); ручные чек-листы и приложения по issue перенесены дословно в docs/testing-notes/ с индексом и тестом на полноту. - Промпт ревьюера в process.yml читает конспект вместо пересказа правил; машинные требования (строка вердикта, REVIEW_DOC, запрет fetch, таблица «чем краснеет», разделы повторного раунда) сохранены и закреплены тестом. - PROCESS.md: правила не менялись; добавлены ссылка на конспекты в шапке и уточнение в §10.4, что ревьюер конвейера читает конспект. - 7 мутантов в реестре. Issue: #634 User-Visible: no
56 lines
3.1 KiB
JavaScript
56 lines
3.1 KiB
JavaScript
// Current test inventory, printed on demand.
|
|
//
|
|
// docs/STATUS.md used to carry these numbers inline; they went stale within a
|
|
// couple of releases while the version line next to them was kept current,
|
|
// which is worse than no number at all — a maintainer reading the snapshot
|
|
// underestimates the coverage that exists (review R5-2). The counts live here
|
|
// now, one command away, and STATUS.md describes the layers instead.
|
|
import { readdirSync, readFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { METRIC_NAMES, collectMetrics, readBaseline } from './monolith-metrics.mjs';
|
|
import { isMainModule } from './spawn-portable.mjs';
|
|
|
|
const count = (root, dir, match, re) =>
|
|
readdirSync(join(root, dir))
|
|
.filter((f) => match.test(f))
|
|
.reduce((n, f) => n + (readFileSync(join(root, dir, f), 'utf8').match(re) || []).length, 0);
|
|
|
|
const files = (root, dir, match) => readdirSync(join(root, dir)).filter((f) => match.test(f)).length;
|
|
|
|
/**
|
|
* Счётчики тестов по слоям. Один источник для этого отчёта и для таблицы
|
|
* Snapshot в docs/STATUS.md (`scripts/status-snapshot.mjs`, #634).
|
|
*
|
|
* Count both node:test spellings and indented pytest methods. Pure backend
|
|
* includes validation plus trail helper/recorder tests; only `test_ha_*` needs
|
|
* the Home Assistant harness (AUD-159B7-03).
|
|
*/
|
|
export function testInventory(root = process.cwd()) {
|
|
return [
|
|
{ id: 'node', label: 'Node unit (frontend + tooling)', count: count(root, 'test', /\.test\.mjs$/, /^\s*(test|it)\(/gm) },
|
|
{ id: 'backend-pure', label: 'pure backend (pytest, no HA)', count: count(root, 'tests_backend', /^test_(?!ha_).*\.py$/, /^\s*(?:async\s+)?def test_/gm) },
|
|
{ id: 'backend-ha', label: 'HA-harness backend (CI, py3.13)', count: count(root, 'tests_backend', /^test_ha_.*\.py$/, /^\s*(?:async\s+)?def test_/gm) },
|
|
{ id: 'smokes', label: 'browser smokes (headless chromium)', count: files(root, 'demo', /^smoke_.*\.mjs$/) },
|
|
];
|
|
}
|
|
|
|
if (isMainModule(import.meta.url)) {
|
|
const rows = testInventory().map(({ label, count: n }) => [label, n]);
|
|
const w = Math.max(...rows.map(([n]) => n.length));
|
|
for (const [name, n] of rows) console.log(`${name.padEnd(w)} ${n}`);
|
|
|
|
// #624: связность монолита — те же шесть чисел и тот же модуль, что у гейта
|
|
// `npm run lint:unused` («одно число — один источник»); рядом — база, чтобы
|
|
// движение было видно без git blame. bundleBytes есть только после сборки.
|
|
const { metrics } = collectMetrics(process.cwd());
|
|
const baseline = readBaseline(process.cwd()) || {};
|
|
console.log('\nmonolith (scripts/monolith-metrics.mjs; база scripts/monolith-baseline.json)');
|
|
const mw = Math.max(...METRIC_NAMES.map((n) => n.length));
|
|
for (const name of METRIC_NAMES) {
|
|
const now = metrics[name];
|
|
const base = baseline[name];
|
|
const delta = now != null && base != null && now !== base ? ` (${now > base ? '+' : ''}${now - base} к базе ${base})` : '';
|
|
console.log(`${name.padEnd(mw)} ${now ?? 'n/a — npm run build'}${delta}`);
|
|
}
|
|
}
|