@vernikr/size-report 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +103 -0
- package/README.md +235 -94
- package/package.json +21 -2
- package/src/args.js +191 -0
- package/src/artifact.js +9 -2
- package/src/check.js +8 -10
- package/src/cli.js +47 -448
- package/src/config.js +103 -24
- package/src/data.js +16 -9
- package/src/derived.js +3 -2
- package/src/doctor.js +121 -65
- package/src/explain.js +43 -26
- package/src/history.js +94 -77
- package/src/hook.js +17 -11
- package/src/init.js +75 -0
- package/src/modes.js +190 -0
- package/src/page/app.js +9 -498
- package/src/page/build.js +16 -7
- package/src/page/dom.js +22 -0
- package/src/page/panel.js +124 -0
- package/src/page/state.js +226 -0
- package/src/page/table.js +145 -0
- package/src/project.js +262 -0
- package/src/refusal.js +6 -1
- package/src/render.js +19 -11
- package/src/size-table.js +10 -4
- package/src/strip/forms.js +26 -0
- package/src/strip/guard.js +59 -0
- package/src/strip/js.js +136 -0
- package/src/strip.js +17 -190
- package/templates/README.md +17 -9
package/README.md
CHANGED
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
## Статус
|
|
12
12
|
|
|
13
|
-
**Выпуск 1.
|
|
14
|
-
реестре — `@vernikr/size-report` (
|
|
13
|
+
**Выпуск 1.3.0 (2026-09-15).** Инструмент живёт отдельным пакетом: имя в
|
|
14
|
+
реестре — `@vernikr/size-report` (публикуется тегом из CI, без секрета). Настроек
|
|
15
|
+
проект может не заводить вовсе: без файла инструмент выводит их из самого проекта и
|
|
16
|
+
говорит об этом строкой, а `--init` закрепляет выведенное файлом (чем этот шаг
|
|
17
|
+
отличается от прежнего — `CHANGELOG.md` 1.3.0).
|
|
15
18
|
Версия — в манифесте, а у выпуска есть `CHANGELOG.md` с разделом «Что изменится
|
|
16
19
|
в числах»:
|
|
17
20
|
таблица чисел в нём не пересказ, а замер на фикстуре, который сверяется с живым
|
|
@@ -79,12 +82,17 @@
|
|
|
79
82
|
дальше он не упоминается без имени проекта.
|
|
80
83
|
**Пункт R-1.2 волны 1** (`REFACTOR.md`): в пакете есть линтер — правила те же, что у
|
|
81
84
|
проекта-потребителя, плюс запрет склейки операторов в одну строку; всё настоящее
|
|
82
|
-
дерево (
|
|
85
|
+
дерево (102 файла) даёт ноль замечаний, `fixtures/` не линтуются — там данные.
|
|
83
86
|
|
|
84
87
|
**Пункты R-1.1 и R-2.1 волн 1–2** (`REFACTOR.md`): вычислительная часть отчёта одна
|
|
85
88
|
(`src/derived.js`) — страница исполняет тот же код, что считает статическую таблицу,
|
|
86
|
-
и разметку для неё
|
|
89
|
+
и разметку для неё строят обычные исходники (`src/page/*.js`), а не строки внутри
|
|
87
90
|
движка; артефакт и разметка страницы при этом совпали со старым выводом побайтово.
|
|
91
|
+
Главы программы страницы разделены по предметам — состояние выбора, узлы, панель,
|
|
92
|
+
таблица, сборка (`WORKLOG.md` §62): вклейка склеивает их подряд, поэтому собранная
|
|
93
|
+
страница осталась той же побайтово, а у глав одна область видимости — это записано
|
|
94
|
+
в `eslint.config.js`, потому что `import` между зовущими друг друга главами завёл
|
|
95
|
+
бы кольцо связей.
|
|
88
96
|
|
|
89
97
|
**Отчёт собирается и в проекте с модулями в `.js`** (`REFACTOR.md` R-4.6): гард
|
|
90
98
|
стриппера понимает обе формы — скрипт и модуль, — поэтому подключение не требует
|
|
@@ -100,7 +108,7 @@
|
|
|
100
108
|
есть в дереве, таблица файлов сходится с ним в обе стороны),
|
|
101
109
|
`test/docs-commands.test.js` (команды и ключи есть в справке, причины отказа
|
|
102
110
|
совпадают с реестром движка, ссылки на разделы ведут в существующие),
|
|
103
|
-
`test/docs-numbers.test.js` (числа проверок
|
|
111
|
+
`test/docs-numbers.test.js` (числа проверок — факт) и
|
|
104
112
|
`test/docs-pin.test.js` (пример установки ведёт на ревизию, чья справка знает
|
|
105
113
|
названные команды), а с выпуском добавился пятый — `test/changelog.test.js`
|
|
106
114
|
(версия выпуска — версия манифеста, а таблица «что изменится в числах» — не
|
|
@@ -176,8 +184,7 @@
|
|
|
176
184
|
86 мс на каждую клетку, плюс разбор опирается на экспериментальный API (без него
|
|
177
185
|
гард отступает к прежнему `node --check` — медленнее, но не мягче).
|
|
178
186
|
Прогон подешевел втрое: `pnpm test` 15,7 → **5,6 с** (тогда в наборе было 39
|
|
179
|
-
проверок), `pnpm run parity:live` 23,8 → **8,3 с**.
|
|
180
|
-
запасом на следующую проверку, а не под сегодняшнее число: набор стоит
|
|
187
|
+
проверок), `pnpm run parity:live` 23,8 → **8,3 с**. Набор стоит
|
|
181
188
|
**23,4–29,9 с** при 124 проверках — в зависимости от загрузки машины: окна с
|
|
182
189
|
загрузкой 18–70 несравнимы (в спокойном — 23,4–24,2 с, в занятых — 26,6–29,9 с;
|
|
183
190
|
в среде без настроек git — 27,4 с, с `CI=1` — 29,9 с), и это свойство окна, а не
|
|
@@ -193,41 +200,38 @@
|
|
|
193
200
|
прибавило** — 23,2 с и до него, и после: обе новые проверки измерены отдельным
|
|
194
201
|
прогоном, а не выведены из разброса. Из общего времени **+8,5 с** — десять проверок хука
|
|
195
202
|
(`test/hook.test.js`: сам он идёт 17,9–18,5 с и становится самым долгим файлом
|
|
196
|
-
набора, а та же ревизия без него — 15,8–16,6 с при 107 проверках).
|
|
197
|
-
двигалась, и это решение, а не пропуск: цель тогда была одна — полный набор
|
|
198
|
-
**≤ 28 с** (запас 2,3 с) — измеренное в неё укладывается, а поднимают цель по делу и с измерением,
|
|
199
|
-
а не под занятую машину: интеграционные
|
|
203
|
+
набора, а та же ревизия без него — 15,8–16,6 с при 107 проверках). Интеграционные
|
|
200
204
|
прогоны (клон, коммиты, слияние, отказы) дешевле не сделать, не ослабив проверку.
|
|
201
|
-
`pnpm run parity:live`
|
|
205
|
+
`pnpm run parity:live` — 9,3 с в обеих средах. Замеры, машина и разброс —
|
|
202
206
|
`REFACTOR.md` §5.
|
|
203
207
|
|
|
204
|
-
**Прогонов два, и
|
|
205
|
-
наборе — не объём файла, а сколько раз
|
|
206
|
-
процесс Node, а клон фикстуры и сборка
|
|
207
|
-
быстрый прогон собирает то, что доказывает по
|
|
208
|
-
справка, эталонные числа на общей фикстуре), а
|
|
209
|
-
инструмент по многу раз на своих клонах, коммитит и
|
|
210
|
-
дорогого файла названа построчно в
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
| Прогон | Команда | Проверок |
|
|
214
|
-
|
|
215
|
-
| Быстрый — каждая правка | `pnpm test` | **
|
|
216
|
-
| Полный — выкладка и CI | `pnpm test:all` | **
|
|
217
|
-
|
|
218
|
-
Ни одна проверка не потеряна и не ослаблена: полный прогон запускает все
|
|
208
|
+
**Прогонов два, и выбор между ними — по цене файла, а не по алфавиту**
|
|
209
|
+
(`REFACTOR.md` R-5.5). Цена проверки в этом наборе — не объём файла, а сколько раз
|
|
210
|
+
файл запускает инструмент и git: запуск — это процесс Node, а клон фикстуры и сборка
|
|
211
|
+
артефакта — сотни миллисекунд. Поэтому быстрый прогон собирает то, что доказывает по
|
|
212
|
+
прочитанному (исходники, дерево, справка, эталонные числа на общей фикстуре), а
|
|
213
|
+
полный добавляет то, что гоняет инструмент по многу раз на своих клонах, коммитит и
|
|
214
|
+
ставит хуки; причина для каждого дорогого файла названа построчно в
|
|
215
|
+
`tools/suites.js`.
|
|
216
|
+
|
|
217
|
+
| Прогон | Команда | Проверок |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| Быстрый — каждая правка | `pnpm test` | **65 из 167** |
|
|
220
|
+
| Полный — выкладка и CI | `pnpm test:all` | **167** |
|
|
221
|
+
|
|
222
|
+
Ни одна проверка не потеряна и не ослаблена: полный прогон запускает все 167 теми же
|
|
219
223
|
файлами, а быстрый берёт их часть. Умолчание — полный: файл становится быстрым только
|
|
220
224
|
явно и с причиной, поэтому новое дорогое не может тихо уехать в быстрый. Стерегут это
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
(`
|
|
225
|
+
объявление `test/suites.test.js` (полнота классификации и причина у каждого файла) и
|
|
226
|
+
сторож документации `test/docs-numbers.test.js` (числа в таблице выше).
|
|
227
|
+
|
|
228
|
+
**Целей по времени у прогонов нет, и это решение, а не пропуск.** Секунды зависят от
|
|
229
|
+
окна — машина бывает под очень разной нагрузкой, — поэтому ни набор, ни CI за время
|
|
230
|
+
не валятся, и документ секунд не обещает: `pnpm run suites:measure` печатает
|
|
231
|
+
длительность каждого файла отдельным прогоном (и сам прогон печатает её рядом с
|
|
232
|
+
галочкой), но это измерение, а не порог. Разделение держится признаком файла — чем он
|
|
233
|
+
занят, а не сколько идёт. CI зовёт полный прогон дважды: обычной средой и без настроек
|
|
234
|
+
машины (`GIT_CONFIG_GLOBAL=/dev/null`).
|
|
231
235
|
|
|
232
236
|
**Обещанное пакетом сведено к факту.** Список поставки называл четыре пути,
|
|
233
237
|
которых в репозитории нет (`dist/`, `templates/`, `CHANGELOG.md`, `LICENSE`):
|
|
@@ -242,14 +246,45 @@ fixture`) и больше не зависит ни от того, держит
|
|
|
242
246
|
пакета `npx size-table --write`).
|
|
243
247
|
|
|
244
248
|
**Проверки идут сами (шаг 6 плана, `.github/workflows/ci.yml`).** На каждый пуш и
|
|
245
|
-
на каждый запрос правки один job
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
+
на каждый запрос правки один job `verify` зовёт **одну команду** — `pnpm run verify`;
|
|
250
|
+
список шагов живёт в одном месте (`tools/gates/run.js`) и совпадает с локальным,
|
|
251
|
+
поэтому проверки, которой нет в профиле, в CI быть не может (это стережёт
|
|
252
|
+
`test/gates-verify.test.js`). В профиле: строгий линтер, датчики раздувания,
|
|
253
|
+
набор проверок, тот же набор в среде, где настроек машины нет вовсе
|
|
254
|
+
(`GIT_CONFIG_GLOBAL=/dev/null`), работу из собранного тарболла, сверку с историей
|
|
255
|
+
проекта-потребителя и воспроизводимость обоих эталонов. Покрытие под c8 дороже
|
|
256
|
+
(полный набор под ним) и живёт в slow-профиле — `pnpm run verify:slow`,
|
|
257
|
+
`.github/workflows/verify-slow.yml` по расписанию.
|
|
249
258
|
Секретов job не требует: история потребителя лежит в репозитории бандлом на той
|
|
250
259
|
же ревизии, что записана в эталоне (`fixtures/live/`), а пересъём идёт во временный
|
|
251
260
|
каталог и сверяется с закоммиченным — рабочее дерево остаётся чистым. Матрицы по
|
|
252
|
-
версиям Node
|
|
261
|
+
версиям Node нет намеренно: этот проход про контроль.
|
|
262
|
+
|
|
263
|
+
**Выпуск — это тег (`.github/workflows/release.yml`).** `git push origin v1.2.3`
|
|
264
|
+
прогоняет тот же полный набор, сверяет версию манифеста с тегом, проверяет работу
|
|
265
|
+
из собранного пакета и отправляет его в реестр — без секрета и без кода из
|
|
266
|
+
аутентификатора: публикация идёт по удостоверению GitHub Actions (trusted
|
|
267
|
+
publishing), которое npm принимает вместо токена. Издатель заведён один раз и живёт
|
|
268
|
+
на стороне npmjs.com, а не в репозитории: `npm trust github @vernikr/size-report
|
|
269
|
+
--file release.yml --repo vernikr/size-report --allow-publish` (то же самое — кнопка
|
|
270
|
+
Trusted Publisher в настройках пакета), права **publish** и stage publish; проверить,
|
|
271
|
+
что связь есть, — `npm trust list @vernikr/size-report`. Выпуск `1.2.0` прошёл именно
|
|
272
|
+
так: `v1.2.0` → 44 с, `+ @vernikr/size-report@1.2.0`, удостоверение подписано и
|
|
273
|
+
записано в журнал прозрачности.
|
|
274
|
+
|
|
275
|
+
Одна ловушка раннера стоила отдельной правки, и она не про этот пакет, а про
|
|
276
|
+
`setup-node`: с `registry-url` действие пишет в `.npmrc` строку
|
|
277
|
+
`_authToken=${NODE_AUTH_TOKEN}`, npm считает учётные данные заданными и за
|
|
278
|
+
удостоверением OIDC **не идёт** — публикация падает 404 при верно заведённом
|
|
279
|
+
издателе. Поэтому `registry-url` здесь не указан (реестр и так по умолчанию тот же, а
|
|
280
|
+
явный адрес живёт в `publishConfig`), и это стережёт `test/release.test.js`. Черновой
|
|
281
|
+
прогон из Actions («Run workflow»: по умолчанию он ничего не публикует) проходит весь
|
|
282
|
+
список до самого пути публикации: гоняет полный набор, проверяет работу из тарболла и
|
|
283
|
+
собирает пакет на черновой версии (`1.2.0` → `1.2.1-draft.0`, чтобы реестр не отказал
|
|
284
|
+
в уже выпущенном номере). Настроен ли издатель, черновой прогон не показывает:
|
|
285
|
+
`--dry-run` не обменивается удостоверением и проходит вообще без учётных данных
|
|
286
|
+
(проверено в пустом каталоге: код 0 без токена) — правду об этом даёт только настоящий
|
|
287
|
+
тег, и он её дал.
|
|
253
288
|
|
|
254
289
|
Первым же прогоном CI окупился: шаг живого паритета упал не на расхождении чисел,
|
|
255
290
|
а на самой проверке — вывод процессов собирался как строка, и многобайтовый символ,
|
|
@@ -347,8 +382,8 @@ deльт задан один раз и по артефакту: рост зел
|
|
|
347
382
|
`src/metrics.js`), поэтому разойтись не могут. Минификатора нет (установка без необязательных
|
|
348
383
|
зависимостей, платформа без него) — метрика отступает к упрощению, способ говорит
|
|
349
384
|
об этом словами, а прогон отдаёт **код 4**, а не молчание: числа при этом те же, что
|
|
350
|
-
у прежнего способа, — побайтово со эталоном.
|
|
351
|
-
сразу на
|
|
385
|
+
у прежнего способа, — побайтово со эталоном. Выведенный профиль ведёт новые проекты
|
|
386
|
+
сразу на сжатие (и `--init` закрепляет то же самое); цена названа прямо в его подсказке. Файл, который минификатор не
|
|
352
387
|
разобрал (разметка в `.js`, чужой синтаксис), — отказ кодом 2 с причиной от него
|
|
353
388
|
самого и двумя готовыми выходами.
|
|
354
389
|
|
|
@@ -382,13 +417,13 @@ deльт задан один раз и по артефакту: рост зел
|
|
|
382
417
|
живой истории (95 строк × 27 колонок, 1,23 МБ текста) тот же отчёт идёт
|
|
383
418
|
**1,55 → 6,35 с** — умножается именно сбор истории, а не таблица: токенов в
|
|
384
419
|
«сейчас» — **303 705**, то есть 4,05 Б на токен. Отсюда и цена набора проверок:
|
|
385
|
-
**7,3–7,9 → 10,4 с** при 66 → 73 проверках (запас и новый бюджет — ниже).
|
|
386
|
-
|
|
420
|
+
**7,3–7,9 → 10,4 с** при 66 → 73 проверках (запас и новый бюджет — ниже). Выведенный
|
|
421
|
+
профиль ведёт новые проекты сразу на токены.
|
|
387
422
|
|
|
388
423
|
**Волна 0 чистки пройдена** (`REFACTOR.md`): у отказов командной строки появились
|
|
389
424
|
коды выхода и справка вместо стека, `--help` отвечает, `--page` и `--write`
|
|
390
425
|
создают недостающий каталог, подсказка в отказе ведёт к работающей команде, а
|
|
391
|
-
|
|
426
|
+
вывод настроек больше не предлагает колонкой саму таблицу — иначе первая же
|
|
392
427
|
проверка настроек его отвергала.
|
|
393
428
|
|
|
394
429
|
**Появились две команды: полнота и объяснение** (шаг 5 плана). `size check`
|
|
@@ -437,10 +472,25 @@ deльт задан один раз и по артефакту: рост зел
|
|
|
437
472
|
| `CHANGELOG.md` | История выпусков и, у каждого выпуска, раздел «Что изменится в числах»: у кого числа поедут и почему |
|
|
438
473
|
| `tools/parity-freeze.js` | Снимает эталон паритета (`pnpm run parity`): замороженной копией, на ревизии проекта из манифеста — `--json`, конфиг, хеш артефакта, хеш инструмента |
|
|
439
474
|
| `tools/make-fixture.js` | Собирает синтетическую фикстуру (`pnpm run fixture`): детерминированную историю с ловушками плюс эталонные числа |
|
|
475
|
+
| `tools/synthetic/` | Сюжеты той сборки по предметам: `repo.js` — как говорим с git (закреплённые время, автор, настройки), `content.js` — что лежит в файлах, `history.js` — какие коммиты из этого получаются, `note.js` — записка к фикстуре со списком ловушек |
|
|
440
476
|
| `tools/parity-live.js` | Сверяет движок с живым проектом на клоне: числа и артефакт (`pnpm run parity:live`) |
|
|
441
477
|
| `tools/pack-check.js` | Собирает тарболл и проверяет, что из него всё работает: все исходники доехали, числа, артефакт и страница — как из репозитория (`pnpm run pack:check`) |
|
|
442
478
|
| `tools/check-standards.js` | Проверяет, что оба эталона воспроизводятся: пересъём идёт в никуда и сверяется с закоммиченным (наши файлы — побайтово, бандл — по содержимому) и что бандл живой истории несёт `HEAD` (`pnpm run check:standards`) |
|
|
443
|
-
| `.github/workflows/ci.yml` | CI:
|
|
479
|
+
| `.github/workflows/ci.yml` | CI: работа `verify` на каждый пуш и запрос правки зовёт `pnpm run verify` — тот же профиль, что локально; действия закреплены по SHA коммита |
|
|
480
|
+
| `.github/workflows/verify-slow.yml` | Slow-профиль по расписанию: то же плюс покрытие под c8 — дорогое не в каждом прогоне |
|
|
481
|
+
| `tools/gates/run.js` | Профили проверок — единственный список шагов: `fast` (каждая правка), `full` (перед отправкой и в CI), `slow` (+ покрытие); `--list` печатает команды |
|
|
482
|
+
| `tools/gates/metrics.js` | Датчик раздувания: правила размера и сложности, вес проверок, пометки долга — с храповиком подавлений ESLint (`.eslint-suppressions.json`) |
|
|
483
|
+
| `tools/gates/dup.js` | Датчик дублей: отпечатки клонов по содержимому (`dup-baseline.json`), взгляд против файла базы и против дерева `origin/main` |
|
|
484
|
+
| `tools/gates/deps.js` | Датчик связей: циклы, сироты, направление слоёв и неразрешимые импорты (`dependency-cruiser`) |
|
|
485
|
+
| `tools/gates/coverage.js` | Датчик покрытия: храповик по файлам против `coverage-baseline.json`, а не процент по репозиторию |
|
|
486
|
+
| `tools/gates/gatefiles.js` | Защита гейт-файлов: правка порогов, баз и обвязки без трейлера `Gate-Change:` — красный (хук `commit-msg` и CI по диапазону) |
|
|
487
|
+
| `tools/gates/common.js`, `tools/gate-probe.js` | Общее у датчиков (корень, разбор ключей, отчёты) и обвязка их проб: датчик зовётся командой, а не импортом |
|
|
488
|
+
| `.githooks/commit-msg`, `.githooks/pre-commit`, `.githooks/pre-push` | Хуки: защита гейт-файлов, быстрый профиль на правку и перед отправкой; ставятся `pnpm run hooks:install` (свой менеджер хуков не заводится) |
|
|
489
|
+
| `eslint.metrics.config.js`, `.eslint-suppressions.json` | Правила датчика раздувания и его база: пороги из замеров, всё, что выше, — в базе и разбирается постепенно |
|
|
490
|
+
| `.jscpd.json`, `dup-baseline.json` | Настройки и база датчика дублей: отпечаток считается по содержимому клона, поэтому база переносима |
|
|
491
|
+
| `.dependency-cruiser.cjs`, `.c8rc.json`, `coverage-baseline.json` | Правила графа связей, настройки снятия покрытия и его база по файлам |
|
|
492
|
+
| `AGENTS.md` | Короткая инструкция агенту репозитория: что запускать, что делать при красном, что нельзя менять |
|
|
493
|
+
| `.github/workflows/release.yml` | Выпуск по тегу: тот же полный набор, сверка версии манифеста с тегом и публикация в реестр по удостоверению GitHub Actions — без секрета и без кода из аутентификатора |
|
|
444
494
|
| `templates/` | То, что проект берёт как есть: `size-report.config.json` (черновик настроек), `ci.yml` (описание проверки) и `README.md` (куда что кладётся и что в них менять); едут в поставке и стерегутся `pack:check` и `test/templates.test.js` |
|
|
445
495
|
| `fixtures/parity/` | Эталон с `safe-resets` на коммите `bd6ef9d`: 95 строк × 27 колонок. Копия реализации, которой он снят, в дереве не лежит — её байты живут в истории и берутся оттуда по требованию (`REFACTOR.md` R-1.5) |
|
|
446
496
|
| `fixtures/synthetic/` | Бандл фикстуры на 16 коммитов, её конфиг, эталонные числа и хеш артефакта |
|
|
@@ -454,10 +504,17 @@ deльт задан один раз и по артефакту: рост зел
|
|
|
454
504
|
| `src/table.css` | Общая часть таблицы: геометрия клеток, липкие шапка и колонка, цвет дельт — одна на артефакт и страницу |
|
|
455
505
|
| `src/artifact.css` | Оформление статического артефакта сверх общей части |
|
|
456
506
|
| `src/page/app.css` | Оформление страницы сверх общей части: панель с деревом файлов, состояния пустоты, узкое окно |
|
|
457
|
-
| `src/page/
|
|
507
|
+
| `src/page/state.js` | Состояние страницы: данные отчёта, вид галочек, паспорт записи, память браузера и обмен ссылкой — глава программы страницы |
|
|
508
|
+
| `src/page/dom.js` | Узлы страницы: мелкие помощники разметки (`appEl`, `appBox`) — одни на панель и таблицу |
|
|
509
|
+
| `src/page/panel.js` | Панель выбора: галочки метрик и файлов, категории, дерево путей, легенда; перерисовку просит у главы сборки |
|
|
510
|
+
| `src/page/table.js` | Таблица страницы: клетка, подпись коммита, шапка и состояния пустоты — разметка поверх общего расчёта |
|
|
511
|
+
| `src/page/app.js` | Сборка и запуск страницы: таблица целиком, перерисовка по выбору читателя, первая отрисовка и смена якоря; вклеивается в собранную страницу
|
|
458
512
|
| `src/page/build.js` | Сборка страницы: данные, оформление и программа в одном файле без внешних ссылок |
|
|
459
513
|
| `src/git.js` | Единственная граница вызова git: закрепления настроек, блобы пачкой, история, сверка с диском |
|
|
460
|
-
| `src/strip.js` | Снятие балласта:
|
|
514
|
+
| `src/strip.js` | Снятие балласта: какая форма к какому файлу (расширение, стратегия) и что считать точным числом — вход разбора форм |
|
|
515
|
+
| `src/strip/js.js` | Снятие комментариев и отступов в JS: проход по случаям (комментарий, регексп, строка, символ) — строки и шаблоны насквозь |
|
|
516
|
+
| `src/strip/forms.js` | Формы текста со своим снятием балласта: разметка, стили, строки файла и JSON |
|
|
517
|
+
| `src/strip/guard.js` | Гард стриппера: снятое обязано компилироваться — скриптом в процессе или модулем в рабочем потоке |
|
|
461
518
|
| `src/parse.js` | Разбор модуля: рабочий поток на прогон и отступление к `node --check`, способ разбора последнего модуля |
|
|
462
519
|
| `src/parse-worker.js` | Сам разбор внутри потока: разбирает текст без исполнения, сообщает, что модулей vm в Node нет |
|
|
463
520
|
| `src/metrics.js` | Реестр метрик: что измеряется, нужен ли текст и насколько честна цифра; описание метрики для читателя — в одном месте |
|
|
@@ -474,14 +531,20 @@ deльт задан один раз и по артефакту: рост зел
|
|
|
474
531
|
| `src/data.js` | Категории файлов и контракт со страницей (`--data`) |
|
|
475
532
|
| `src/render.js` | Статический артефакт: клетки, таблица, примечание (стили — в `src/css.js`) |
|
|
476
533
|
| `src/config.js` | Настройки проекта-потребителя: умолчания, чтение, проверка |
|
|
534
|
+
| `src/project.js` | Настройки, выведенные из самого проекта (дерево и история): колонки, журнал, исключения. Без файла настроек он и есть настройки; `--init` закрепляет его файлом |
|
|
477
535
|
| `src/locales.js`, `src/refusal.js`, `src/tool.js` | Тексты отчёта; коды выхода и справка; имя и версия пакета |
|
|
478
|
-
| `src/cli.js` |
|
|
536
|
+
| `src/cli.js` | Вход инструмента: разбор строки, чтение проекта и доставка запроса режиму; главный файл пакета |
|
|
537
|
+
| `src/args.js` | Грамматика командной строки: режимы, ключи и команды плюс проверки их сочетаний — отказ называет виновника и готовую команду |
|
|
538
|
+
| `src/modes.js` | Режимы: собрать таблицу, сверить её с историей, отдать данные или страницу, полноту покрытия и диагностику |
|
|
539
|
+
| `src/init.js` | Закрепление настроек файлом (`--init`): то, что проект вывел о себе сам, ложится файлом — и проходит ту же проверку, что первый запуск |
|
|
479
540
|
| `test/api.test.js` | Публичный API пакета: список имён заморожен, разбиение не имеет права его менять |
|
|
480
541
|
| `eslint.config.js` | Правила оформления: те же, что у проекта-потребителя, плюс запрет склейки операторов в строке (`pnpm run lint`, `pnpm run lint:strict`) |
|
|
481
542
|
| `tools/harness.js` | Обвязка проверок: пути, клоны фикстуры (в том числе общий на набор и с CRLF), запуск инструмента, разбор отказов, хеши |
|
|
482
|
-
| `tools/
|
|
483
|
-
| `tools/
|
|
543
|
+
| `tools/page-harness.js` | Обвязка проверок контракта и страницы: данные контракта, собранная страница, чтение её в настоящем DOM, переключатели панели — одна на четыре набора |
|
|
544
|
+
| `tools/suites.js` | Разделение набора: какие файлы идут в быстрый прогон (с причиной для каждого), почему каждый дорогой — в полном |
|
|
545
|
+
| `tools/run-tests.js` | Прогон набора (`pnpm test`, `pnpm test:all`, `pnpm run suites:measure`): длительность каждого файла своим замером и сверка числа проверок |
|
|
484
546
|
| `tools/docs-facts.js` | Чтение фактов из документации — один слой на четыре проверки сторожа: что документ называет (пути, зовы, адреса разделов) против того, что есть в репозитории |
|
|
547
|
+
| `tools/yaml.js` | Разбор подмножества YAML — один разборщик на два сторожа описаний (`templates/ci.yml` и `.github/workflows/release.yml`): вне подмножества — ошибка, а не молча пропущенная строка, включая двоеточие с пробелом в незакавыченном значении (именно оно делало описание выпуска неразбираемым, пока проверка искала подстроки) |
|
|
485
548
|
| `tools/refusals.js` | Каталог отказов: по строке на каждый — причина, код выхода, обязательные фразы вывода, **что отказ советует** (`advice`: `run` — команда, `template` — форма с подстановкой, `manual` — действие человека с причиной, `coveredBy` — отдан другой проверке), а для непроверяемого — почему; карты мест отказа (`SITES`, `PRINTED`) держат числа, чтобы новый отказ не появился молча, а маркеры совета — чтобы не появился молча новый совет |
|
|
486
549
|
| `test/parity.test.js` | Паритет движка с эталоном: числа, артефакт, локаль |
|
|
487
550
|
| `test/frozen.test.js` | Замороженная копия: та ли это ревизия, с которой снят эталон, и воспроизводит ли она его |
|
|
@@ -491,20 +554,26 @@ deльт задан один раз и по артефакту: рост зел
|
|
|
491
554
|
| `test/cli.test.js`, `test/cli-paths.test.js` | Отказы командной строки: справка, настройки, коды выхода — и куда инструмент пишет |
|
|
492
555
|
| `test/refusals.test.js` | Отказы исполняются: каждый вызван прогоном, сверены код выхода и обещанные фразы (свои клоны — для чужого хука, обрезанной истории и ветки мимо отчёта), и **совет выполняется** — команда даёт обещанный код, не падает стеком, а где объявлено «отказ ушёл», тот же зов после неё отвечает другим |
|
|
493
556
|
| `test/refusals-catalog.test.js` | Сторож каталога отказов: у каждого места отказа в исходниках есть пункт, у каждого пункта — объявленный совет, а отказы, отданные другой проверке, ею в самом деле утверждаются (названные файл и строка проверяются) |
|
|
494
|
-
| `test/contract.test.js` | Контракт
|
|
557
|
+
| `test/contract-data.test.js` | Контракт данных: числа против эталона, состав полей против производных, пометки приближения против подписи метрики |
|
|
558
|
+
| `test/contract-derived.test.js` | Производные против чисел артефакта: итоги строки, дельты клетки и дельта итога — на коде, который лежит в дереве |
|
|
559
|
+
| `test/page-view.test.js` | Собранная страница: вклейка без копий расчёта, самодостаточность, дерево файлов, состояния пустоты, оформление и переключатели |
|
|
560
|
+
| `test/page-choice.test.js` | Память выбора и обмен ссылкой: перезаход, чужой отчёт, чужая и битая запись, смена адреса на открытой странице |
|
|
495
561
|
| `test/module.test.js` | Модуль в расширении `.js`: измеряется без правок настроек; гард стриппера жив (доказано мутацией) и не обвиняет невиновного |
|
|
496
562
|
| `test/guard.test.js` | Разбор модуля: идёт потоком, оба пути дают один вердикт, отступление работает без файла потока, сотни разборов дешевле запуска |
|
|
497
563
|
| `test/runner.test.js` | Чтение вывода процесса: куски склеиваются буферами, а не приклеиваются к строке — многобайтовый символ на границе кусков не превращается в два символа-заменителя |
|
|
498
564
|
| `test/git-pins.test.js` | Сторож границы git: прямых вызовов git без общего списка закреплений нет, и незакреплённое чтение показывается свидетелем (путь кавычками) |
|
|
499
|
-
| `test/docs-paths.test.js`, `test/docs-commands.test.js`, `test/docs-numbers.test.js`, `test/docs-pin.test.js` | Сторож документации, по файлу на обещание: пути и таблица файлов; зовы, причины отказа и адреса разделов; числа
|
|
565
|
+
| `test/docs-paths.test.js`, `test/docs-commands.test.js`, `test/docs-numbers.test.js`, `test/docs-pin.test.js` | Сторож документации, по файлу на обещание: пути и таблица файлов; зовы, причины отказа и адреса разделов; числа проверок; пин в примере установки |
|
|
500
566
|
| `test/changelog.test.js` | Сторож выпуска: версия в `CHANGELOG.md` — версия манифеста, а таблица «что изменится в числах» — это замер на фикстуре, сверенный с живым прогоном |
|
|
501
|
-
| `test/
|
|
567
|
+
| `test/release.test.js` | Сторож выпуска из CI: он начинается тегом, версия берётся из манифеста, секрета и одноразового кода не требует, prerelease не уезжает в `latest`, перед публикацией идёт полный набор — и подсказка на npmjs.com называет этот же файл |
|
|
568
|
+
| `test/suites.test.js` | Сторож разделения набора: полнота классификации (быстрый — явно, полный — с причиной), причина у каждого файла, что быстрый прогон остаётся частью набора |
|
|
569
|
+
| `test/gates-metrics.test.js`, `test/gates-dup.test.js`, `test/gates-deps.test.js`, `test/gates-coverage.test.js`, `test/gates-files.test.js` | Пробы датчиков: искусственное нарушение → датчик красный, снятие → снова зелёный; прогон зовёт датчик командой, а не импортом, поэтому доказывает и код возврата |
|
|
570
|
+
| `test/gates-verify.test.js` | Сторож единственного списка: команды профиля против рабочих процессов, хуков и `templates/ci.yml` — проверки, которой нет в профиле, в CI быть не может |
|
|
502
571
|
| `test/check.test.js` | Полнота и объяснение на настоящих коммитах фикстуры: непокрытый путь, «только отчёт», «число не сдвинулось», «мимо колонок», слияние — и что починка настроек не двигает числа |
|
|
503
572
|
| `test/doctor.test.js` | Диагностика на пяти состояниях проекта: без настроек (2), полное покрытие (0), неполное (1), обрезанная история (3), нет датчика (4) — и блок покрытия равен ответу `size check`, а не считается вторым разом |
|
|
504
573
|
| `test/hook.test.js` | Хуки на свежем клоне: ставятся только командой, дают отдельный коммит отчёта (в том числе после слияния), повторный запуск молчит, чужая работа и индекс не тронуты, в CI и при отказе инструмента ничего не делают, снятие возвращает проект к прежнему |
|
|
505
574
|
| `test/templates.test.js` | Шаблоны: черновик настроек проходит проверку инструмента и собирает настоящий отчёт; описание проверки разбирается и зовёт только существующие команды и ключи |
|
|
506
575
|
| `test/minify.test.js`, `test/tokens.test.js` | Настоящее сжатие и токены: числа против упрощения, кодировка как часть числа, честность подписи, работа без необязательной зависимости (код 4) и шов `SIZE_REPORT_NO_OPTIONAL` |
|
|
507
|
-
| `package.json` | Манифест пакета: имя `@vernikr/size-report`, версия `1.
|
|
576
|
+
| `package.json` | Манифест пакета: имя `@vernikr/size-report`, версия `1.2.0`, список поставки — только существующее |
|
|
508
577
|
|
|
509
578
|
Оба каталога эталонов снимаются заново теми же инструментами: `pnpm run parity` и
|
|
510
579
|
`pnpm run fixture` дают те же файлы. Побайтово сверяется наше — конфиг, эталонные
|
|
@@ -536,7 +605,7 @@ JSX и TSX выход зависит от настройки jsx сам
|
|
|
536
605
|
уже собранных значениях (`data`, `render`, `page`), а настройки, тексты и отказ —
|
|
537
606
|
по краям, потому что их знает любой и они не знают никого. Оба отчёта считаются на
|
|
538
607
|
сборке: страница получает исходники общего расчёта и своей программы вклеенными
|
|
539
|
-
(`src/derived.js`, `src/page
|
|
608
|
+
(`src/derived.js`, `src/page/*.js`), потому что открывается она с диска, без
|
|
540
609
|
сервера и без сети. Остальное — по шагам 2–6 (`PLAN.md` §5).
|
|
541
610
|
|
|
542
611
|
## Как подключить к своему проекту
|
|
@@ -555,16 +624,23 @@ JSX и TSX выход зависит от настройки jsx сам
|
|
|
555
624
|
### 1. Установка
|
|
556
625
|
|
|
557
626
|
```bash
|
|
558
|
-
pnpm add -D
|
|
627
|
+
pnpm add -D @vernikr/size-report
|
|
559
628
|
```
|
|
560
629
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
630
|
+
Пакет **опубликован в реестре**, и публично: `npm view @vernikr/size-report
|
|
631
|
+
version` отвечает `1.3.0`, `npm access get status @vernikr/size-report` — `public`,
|
|
632
|
+
а анонимный запрос тарболла — код 200. `npm i -D` и `yarn add -D` принимают то же
|
|
633
|
+
имя; ни ключа, ни ссылки на репозиторий не нужно.
|
|
634
|
+
|
|
635
|
+
Тот же выпуск можно взять ссылкой на репозиторий — так установка не зависит от
|
|
636
|
+
реестра, но остаётся привязанной к ревизии:
|
|
637
|
+
|
|
638
|
+
```bash
|
|
639
|
+
pnpm add -D github:vernikr/size-report#v1.3.0
|
|
640
|
+
```
|
|
565
641
|
|
|
566
642
|
Без сети (или если тянуть из codeload нечем) — тарболл: `pnpm pack` в клоне
|
|
567
|
-
пакета, затем `pnpm add -D ./vernikr-size-report-1.
|
|
643
|
+
пакета, затем `pnpm add -D ./vernikr-size-report-1.3.0.tgz`.
|
|
568
644
|
|
|
569
645
|
**Почему тег, а не sha.** Короткий sha pnpm разрешает только через видимые рефы, а
|
|
570
646
|
`git ls-remote` отдаёт одни верхушки веток: пока ревизия — верхушка, короткий sha
|
|
@@ -572,7 +648,7 @@ pnpm add -D github:vernikr/size-report#v1.1.1
|
|
|
572
648
|
<sha> to a commit`. Это не рассуждение, а проба: короткий пин `6530237` ставился,
|
|
573
649
|
пока `main` стоял на нём, и перестал — на следующем же коммите, а тот же sha
|
|
574
650
|
целиком поставился. Имя ветки (`#main`) или тег принимаются оба, но ветка —
|
|
575
|
-
движущаяся цель, а тег постоянен: этот выпуск стоит на теге `v1.
|
|
651
|
+
движущаяся цель, а тег постоянен: этот выпуск стоит на теге `v1.3.0`, он же и в
|
|
576
652
|
примере (сорок знаков тоже годятся, но их придётся брать глазами из истории).
|
|
577
653
|
|
|
578
654
|
Ревизия в примере — не украшение, а часть утверждения: она закреплена за тем, что
|
|
@@ -591,27 +667,45 @@ pnpm add -D github:vernikr/size-report#v1.1.1
|
|
|
591
667
|
GIT_SSH_COMMAND=false`): установка 3,4 с, дальше `size --write` и `size` работают
|
|
592
668
|
(`WORKLOG.md` §44). Прежнее требование было ценой приватности: локально — ключ, а
|
|
593
669
|
в CI — read-only deploy key перед `pnpm install` (то самое первое подключение,
|
|
594
|
-
`WORKLOG.md` §18); шаг с ключом из шаблона ушёл вместе с приватностью.
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
670
|
+
`WORKLOG.md` §18); шаг с ключом из шаблона ушёл вместе с приватностью. Публикация
|
|
671
|
+
в npm сделана 2026-09-15, и у неё была цена: имя `size-report` в реестре занято чужим
|
|
672
|
+
пакетом (2017 год, три версии), поэтому выкладка — это ещё и смена имени на имя в
|
|
673
|
+
области владельца (`@vernikr/size-report`), а не только отправка архива; что
|
|
674
|
+
затронуло переименование — `PLAN.md` §10, чем доказана выкладка — `WORKLOG.md` §53.
|
|
599
675
|
|
|
600
|
-
### 2.
|
|
676
|
+
### 2. Настройки: их можно не заводить
|
|
601
677
|
|
|
602
678
|
```bash
|
|
603
|
-
pnpm exec size --
|
|
679
|
+
pnpm exec size --write # таблица; настроек нет — их выведет сам инструмент
|
|
680
|
+
pnpm exec size --init # закрепить выведенное в size-table.config.json
|
|
604
681
|
```
|
|
605
682
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
(
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
683
|
+
Начинать с настроек не нужно: без файла инструмент выводит их из проекта — колонками
|
|
684
|
+
берёт крупнейшие файлы, по одному от каждого расширения (иначе отчёт состоял бы из
|
|
685
|
+
одних крупных `.md`, и ни один `.js` не попал бы под настоящее сжатие), журналом —
|
|
686
|
+
первый знакомый (`WORKLOG.md`, `CHANGELOG.md`, …), файлом отчёта — `docs/`, если
|
|
687
|
+
каталог есть, командой починки — объявленный скрипт `sizes`, а без него — путь
|
|
688
|
+
к установленному пакету (его цитируют подпись отчёта и отказы, поэтому он обязан
|
|
689
|
+
работать уже сейчас), ссылкой на коммит — адрес `origin`, метриками — `raw`, `min`,
|
|
690
|
+
`tok`. Метрика `min` считается настоящим сжатием (`"minify": {"engine": "esbuild"}`),
|
|
691
|
+
а `tok` — словарём (`"tokens": {"family": "openai", "encoding": "o200k_base"}`): без
|
|
692
|
+
этих необязательных зависимостей метрика честно отступает к другому счёту и прогон
|
|
693
|
+
отдаёт код 4 — правки настроек и тут не требуются.
|
|
694
|
+
|
|
695
|
+
Всё, что колонкой быть не может или в неё не поместилось (сам отчёт, замки
|
|
696
|
+
зависимостей, карты, собранное), называется в `skip` — поэтому первый же `size check`
|
|
697
|
+
полон, а не красен: «пути мимо колонок» появляются от новых правок, а не от того, что
|
|
698
|
+
проект ещё не описан. О том, что настройки выведены, инструмент говорит строкой в
|
|
699
|
+
stderr и называет команду, которая их закрепляет, — `--init`; закреплённое проходит
|
|
700
|
+
ту же проверку, что любой файл настроек, и дальше его правят глазами (сам `--init`
|
|
701
|
+
печатает, что закрепил, и что делать дальше — скрипты и проверку в CI). Без
|
|
702
|
+
закрепления профиль выводится заново на каждом запуске: числа не «поедут», но
|
|
703
|
+
повторить прежний замер — в том числе хуком и проверкой — можно только по файлу.
|
|
704
|
+
|
|
705
|
+
Закрепляется **то же, чем проект работает без файла**: вывод из проекта поверх
|
|
706
|
+
умолчаний. Поэтому в закреплённом файле видны и значения, которых в проекте никто не
|
|
707
|
+
писал, — тогда смена умолчаний в новой версии пакета не поедет по уже настроенному
|
|
708
|
+
проекту молча.
|
|
615
709
|
|
|
616
710
|
> Subкоманды `size init` пока нет — CLI знает только флаги (`--init`, `--write`,
|
|
617
711
|
> `--page`, `--data`, `--json`, без флага — проверка); полный список даёт `size --help`.
|
|
@@ -619,20 +713,21 @@ pnpm exec size --init # создаёт size-table.config.json
|
|
|
619
713
|
|
|
620
714
|
### 3. Что правится в конфиге
|
|
621
715
|
|
|
622
|
-
|
|
623
|
-
человек. Чаще всего правят:
|
|
716
|
+
Вывод знает про проект только то, что видно в дереве и истории, — какие колонки важны,
|
|
717
|
+
знает человек. Чаще всего правят:
|
|
624
718
|
|
|
625
719
|
| Ключ | Что это |
|
|
626
720
|
|---|---|
|
|
627
|
-
| `columns` | колонки таблицы: `{label, paths: [...]}`;
|
|
721
|
+
| `columns` | колонки таблицы: `{label, paths: [...]}`; **колонка — это файл**: список путей — её переименования (в ревизии берётся тот путь, который в ней есть), а не несколько файлов разом; `label` — то, что увидит человек |
|
|
628
722
|
| `metrics` | из чего состоит число: `raw` (размер объекта git), `min` (минифицированная форма — какая именно, решает `minify.engine`), `tok` (токены), `gzip` |
|
|
629
723
|
| `tokens.family`, `tokens.encoding` | словарь для `tok`: семейство (`openai`) и кодировка (`o200k_base` или `cl100k_base`) — кодировка меняет число, поэтому она и в настройках, и в подписи метрики |
|
|
630
724
|
| `minify.engine` | чем считается `min`: `strip` (комментарии и отступы, точность не обещается) или `esbuild` (настоящее сжатие; форматы без минификатора — упрощение, и это видно в подписи метрики) |
|
|
631
|
-
| `output` | файл таблицы (
|
|
725
|
+
| `output` | файл таблицы (в выведенном профиле — `docs/size-table.html`, если каталог `docs/` есть, иначе в корне) |
|
|
632
726
|
| `journal` | где искать разделы журнала, на которые ссылаются строки |
|
|
633
|
-
| `links.commitUrl` | шаблон ссылки на коммит, например `https://github.com/org/repo/commit/{sha}` |
|
|
634
|
-
| `skip` | пути, которые
|
|
635
|
-
| `fixCommand` | команда, которую цитирует подпись отчёта и подсказывает отказ; в
|
|
727
|
+
| `links.commitUrl` | шаблон ссылки на коммит, например `https://github.com/org/repo/commit/{sha}`; выводится из адреса `origin` у GitHub и GitLab (у остальных хозяев — пусто, а не догадка) |
|
|
728
|
+
| `skip` | пути, которые колонкой не стали: и те, что ею быть не могут (сам отчёт, замки зависимостей), и те, что в колонки не поместились (выведенный профиль объявляет исключениями всё остальное — поэтому первый `check` полон) |
|
|
729
|
+
| `fixCommand` | команда, которую цитирует подпись отчёта и подсказывает отказ; в выведенном профиле — ваш скрипт `sizes`, если он объявлен, иначе путь к установленному пакету внутри проекта (зов по имени пакета уходит в реестр — `REFACTOR.md` R-4.21) |
|
|
730
|
+
| `locale`, `title`, `heading` | язык текстов отчёта и его заголовки; пустые `title`/`heading` значат «взять из локали» |
|
|
636
731
|
| `minify.guard` | расширения, где результат стриппера проверяется разбором; модуль в `.js` гард понимает сам, трогать его не нужно |
|
|
637
732
|
| `hooks.enabled` | выключатель хука автообновления (`false` — хук остаётся на месте, но молчит; убирается он только `size uninstall-hook`) |
|
|
638
733
|
|
|
@@ -710,9 +805,10 @@ pnpm exec size doctor # 0 — делать нечего; иначе перв
|
|
|
710
805
|
`.github/workflows/size-report.yml` без правок — сборка таблицы, сверка с файлом
|
|
711
806
|
на диске, два снимка чисел (обычный и в среде без настроек git) и их сравнение.
|
|
712
807
|
Секретов оно не требует. Для `npm`/`yarn` в самом файле сказано, какие две строки
|
|
713
|
-
заменить. Рядом — `templates/size-report.config.json`,
|
|
714
|
-
|
|
715
|
-
|
|
808
|
+
заменить. Рядом — `templates/size-report.config.json`, образец настроек: колонки в нём
|
|
809
|
+
примерные (`README.md`, `package.json`), они есть почти в любом проекте, поэтому
|
|
810
|
+
первый отчёт собирается сразу. Нужен он, только если хочется начать с правленого
|
|
811
|
+
файла: без файла настройки выводятся из проекта (`--init` закрепляет выведенное).
|
|
716
812
|
|
|
717
813
|
Свой CI у пакета — `.github/workflows/ci.yml`: он гоняет у себя тот же список
|
|
718
814
|
команд, что описан ниже, и его можно взять за образец для шага потребителя.
|
|
@@ -723,7 +819,7 @@ pnpm exec size doctor # 0 — делать нечего; иначе перв
|
|
|
723
819
|
| 1 | таблица разошлась с историей (или правка на диске не закоммичена); у `size check` — путь истории не отслеживается и не исключён | `pnpm run sizes` и закоммитить таблицу; для `check` — дописать путь колонкой или в `skip` |
|
|
724
820
|
| 2 | что-то в вызове или в проекте — **командная строка** (незнакомый ключ, ключ без значения, повтор ключа, два режима сразу, лишнее слово, команда и режим, неизвестная команда, несовместимый ключ, нет ответа в JSON, два ответа сразу, нет коммита); **настройки и проект** (нет файла настроек, настройки не разобраны, настройки неверны, нет git, не git-репозиторий, конфиг уже есть); **история** (нет такого коммита, коммит назван неточно, коммит вне истории); **хук** (чужой хук, чужой core.hooksPath, нечем звать инструмент); **измерение** (файл не JavaScript, минификатор не разобрал) | текст отказа называет причину и готовую команду — и она выполнима: это сторожит `test/refusals.test.js` |
|
|
725
821
|
| 3 | неполная история (clone с `--depth`) | полный клон: `git fetch --unshallow` |
|
|
726
|
-
| 4 | нет датчика | `minify.engine: "esbuild"`, а минификатора нет: числа получены упрощением. Отчёт собран, причина и починка — в
|
|
822
|
+
| 4 | нет датчика | `minify.engine: "esbuild"`, а минификатора нет: числа получены упрощением. Отчёт собран, причина и починка — в тексте; если при этом таблица расходится с историей, код остаётся **1** (нарушение старше приближения), а заметка о другом счёте печатается рядом |
|
|
727
823
|
| 5 | внутренняя ошибка | это дефект инструмента: текст нужен нам, см. «Ловушки» ниже |
|
|
728
824
|
|
|
729
825
|
### 6. Отчёт обновляется сам после коммита (по желанию)
|
|
@@ -768,7 +864,17 @@ pnpm exec size uninstall-hook # снять и вернуть проект к
|
|
|
768
864
|
при упрощении — `minify.guard`. Стеком такой случай не выглядит ни там, ни там;
|
|
769
865
|
- **Минификатора нет** (установка без необязательных зависимостей, платформа без
|
|
770
866
|
`esbuild`) — метрика честно отступает к упрощению: числа те же, что у `strip`,
|
|
771
|
-
способ говорит об этом словами, а
|
|
867
|
+
способ говорит об этом словами, а **сборка** (`--write`) отдаёт **код 4** с
|
|
868
|
+
готовой починкой. У **проверки** в этом случае ответ из двух частей, и он назван
|
|
869
|
+
здесь потому, что именно её советует CI: если отчёт на диске собран с настоящим
|
|
870
|
+
минификатором, а прогон идёт без него, точность изменилась — значит числа в
|
|
871
|
+
таблице больше не совпадают с историей, и проверка скажет про расхождение
|
|
872
|
+
(**код 1**), показав разошедшуюся строку подписи, **и тут же назовёт другой счёт**
|
|
873
|
+
заметкой с готовой починкой. Вердикт при этом остаётся за расхождением: код 4
|
|
874
|
+
утверждал бы, что разница объясняется датчиком, а это никто не проверял —
|
|
875
|
+
расхождение может быть и правкой мимо отчёта (тот же порядок, что у `size check` и
|
|
876
|
+
у `doctor`: нарушение старше приближения). Починка в обоих случаях — `pnpm run
|
|
877
|
+
sizes`; на этом окружении она вернёт **код 4**.
|
|
772
878
|
Проверить это без переустановки можно окружением `SIZE_REPORT_NO_OPTIONAL=1` —
|
|
773
879
|
тем же приёмом это делает `test/minify.test.js`;
|
|
774
880
|
- **Разбор модуля — рабочий поток, поднятый один раз на прогон** (`REFACTOR.md`
|
|
@@ -831,8 +937,43 @@ R-4.1): пути, таблица файлов, зовы и ключи инстр
|
|
|
831
937
|
починки взяты из конфига) не проверяет никто: если это важно, это одна проверка
|
|
832
938
|
поверх `--data` в проекте.
|
|
833
939
|
|
|
940
|
+
## Гейт против раздувания
|
|
941
|
+
|
|
942
|
+
**Список проверок — один, и он же в CI.** Профиль проверок задан в одном месте
|
|
943
|
+
(`tools/gates/run.js`): `pnpm run verify:fast` (десятки секунд — каждая правка),
|
|
944
|
+
`pnpm run verify` (полный — перед отправкой и в CI) и `pnpm run verify:slow`
|
|
945
|
+
(по расписанию — то же плюс покрытие). CI зовёт эту же команду, а не свой список:
|
|
946
|
+
работа `verify` (`.github/workflows/ci.yml`) на каждый пуш и запрос правки, работа
|
|
947
|
+
`verify-slow` — по расписанию. Совпадение стережёт `test/gates-verify.test.js`:
|
|
948
|
+
проверка, которой нет в профиле, в CI не пройдёт.
|
|
949
|
+
|
|
950
|
+
**Датчики ловят раздувание, а не стиль** (стиль — у линтера): размер и сложность
|
|
951
|
+
функций, размер модулей, дубли веток и функций (`sonarjs`), вес проверок (проверка
|
|
952
|
+
без утверждения, утверждение без сравнения, выключенная проверка), пометки долга,
|
|
953
|
+
клоны по токенам (`jscpd`), циклы и сироты связей (`dependency-cruiser`), просадка
|
|
954
|
+
покрытия против своей же базы (`c8`).
|
|
955
|
+
|
|
956
|
+
**Порог взят из замера, а не из головы, и он храповик.** По исходному замеру:
|
|
957
|
+
сложность функции p50 1 / p90 4 / p99 11 / max 27 — порог 12 (в базе осталось 5
|
|
958
|
+
функций); длина функции p50 7 / p90 27 / p99 73 / max 118 — порог 60 (9 в базе);
|
|
959
|
+
модуль p90 381 строка / max 907 — порог 450 (в базе не осталось ни одного: три
|
|
960
|
+
толстых файла — контракт, программа страницы и сборка фикстуры — разделены,
|
|
961
|
+
`WORKLOG.md` §59–§61). Всё, что выше порога
|
|
962
|
+
сегодня, лежит в базе (`.eslint-suppressions.json`) и работе не мешает; новое валит
|
|
963
|
+
прогон. Дубли — 13 клонов / 84 строки (0,67 %), связи — 112 модулей / 468 связей и ни
|
|
964
|
+
одной находки.
|
|
965
|
+
|
|
966
|
+
**Базы обновляет человек.** `pnpm run baseline:metrics`, `baseline:dup`,
|
|
967
|
+
`baseline:coverage` — и только с трейлером `Gate-Change:` в сообщении коммита: правка
|
|
968
|
+
гейт-файла без него красна и локально (хук `commit-msg`), и в CI (по каждому коммиту
|
|
969
|
+
диапазона). Иначе гейт ослаблялся бы тем же коммитом, который он останавливает.
|
|
970
|
+
Таблица замеров, отвергнутые инструменты (knip, ast-grep, size-limit, gitleaks) и
|
|
971
|
+
действия человека — в `WORKLOG.md` §58.
|
|
972
|
+
|
|
834
973
|
## Для ИИ-агента
|
|
835
974
|
|
|
975
|
+
- `pnpm run verify:fast` — перед каждой правкой, `pnpm run verify` — перед отправкой;
|
|
976
|
+
что не так и что нельзя трогать при красном — `AGENTS.md`.
|
|
836
977
|
- `size check --json` — готово ли всё: какая часть истории покрыта, какие пути
|
|
837
978
|
мимо колонок (с коммитом-первопричиной) и какие коммиты выпали без строки.
|
|
838
979
|
- `size explain <коммит> --json` — почему у конкретного коммита нет строки: причина,
|
|
@@ -876,7 +1017,7 @@ pnpm test # быстрый прогон (каждая пр
|
|
|
876
1017
|
# контракт данных и страница, сторож документации и выпуска
|
|
877
1018
|
pnpm test:all # полный прогон (выкладка и CI): то же плюс интеграционные —
|
|
878
1019
|
# сборка на дисках, сверка с деревом, хуки, метрики
|
|
879
|
-
pnpm run suites:measure #
|
|
1020
|
+
pnpm run suites:measure # замерить длительность каждого файла набора
|
|
880
1021
|
pnpm run parity:live # паритет с живым проектом на клоне, две среды
|
|
881
1022
|
node bin/size.js --data # контракт данных: страница и агент
|
|
882
1023
|
node bin/size.js --page # минимальная страница отчёта
|