docs: review document for #634

Issue: #634
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-24 02:47:09 +00:00
parent 7dc7597260
commit c8f9b5d3b4
2 changed files with 175 additions and 1 deletions
+173
View File
@@ -0,0 +1,173 @@
# CODE-REVIEW-634-r1
Issue: #634 — «Стоимость входа агента ≈ 43 k токенов до первого файла кода: ролевые
конспекты PROCESS, индекс TESTING.md, генерируемый STATUS.md».
Этап: code · заход r1 · блокирующих циклов израсходовано 0/4.
Материал: коммит `7dc7597260239f63a25a4f4538dbac3bd67072a5` (один коммит поверх
`fe92ce06`, уже на `dev`-линии). Рабочая копия проверена ровно на этом SHA;
`git fetch`/`checkout` на другой коммит не выполнялись.
## Скоуп
Класс задачи — B/C (инфраструктура/документация): `.github/workflows/process.yml`,
`AGENTS.md`, `PROCESS.md`, `docs/DEVELOPMENT.md`, `docs/STATUS.md` +
`docs/STATUS-FEATURES.md` (новый), `docs/TESTING.md` + `docs/testing-notes/*`
(8 новых файлов), `docs/process/AUTHOR.md` + `REVIEWER.md` (новые),
`docs/TESTING-DEMO.md`, `scripts/entry-cost.mjs`, `scripts/status-snapshot.mjs`,
`scripts/md-anchors.mjs`, `scripts/inventory.mjs`, `scripts/check-inputs.mjs`,
`scripts/mutation-registry.mjs`, четыре новых тестовых файла. Ни одного файла
класса A — подтверждено чтением `git show --stat`. Задача не обязана служить
строке `docs/SCOPE.md` (это процесс/инструменты, не продуктовая фича); ей
корректно присвоены метки `process` и `tech-debt`, без `S*` до первого
`S7-code-review` — по правилу для инфраструктурных задач.
Предмет: три AC из тела issue —
AC1 (вход автора по маршруту ≤ 12 000 слов, замер скриптом),
AC2 (каждый пункт ролевого конспекта ссылается на существующий раздел канона),
AC3 (`TESTING.md` ≤ 800 строк, приложения по индексу) —
плюс заявленные в хендоффе побочные правки: генерируемый Snapshot в
`docs/STATUS.md`, сокращённый промпт ревьюера в `process.yml`, порядок чтения по
роли в `AGENTS.md`.
## Как проверялось
Дешёвые гейты подтверждены зелёным Validate на этом же SHA
(https://github.com/Matysh/houseplan-card/actions/runs/35947737578) — `tsc`,
`npm test`, `npm run build` со сверкой бандла повторно не гонялись.
Дополнительно прогнано вручную (диф не трогает `src/**`, `custom_components/**/*.py`,
геометрию — golden/pytest/invariants/смоки не требуются, и это не пропуск, а
предмет диффа):
| Команда | Результат |
|---|---|
| `node --test test/process-digests.test.mjs test/entry-cost.test.mjs test/status-snapshot.test.mjs test/testing-notes-index.test.mjs` | 15/15 pass |
| `node scripts/entry-cost.mjs --check` | exit 0 (author 10747/12000, reviewer 7890/9000) |
| `node scripts/status-snapshot.mjs --check` | exit 1, «snapshot block is stale» — **ожидаемо**: намеренно не подключён в CI (комментарий в скрипте и в хендоффе), число тестов в дереве уже сдвинулось на 20 (2868→2888) после других задач, влившихся в `dev` после коммита. Это не находка — блок честно называет себя снимком на дату, а не живым значением |
| `node scripts/check-inputs.mjs --coverage` | exit 0, тихо (`scripts/inventory.mjs` снят с `NOT_AN_INPUT`, покрыт тестом) |
| `node --check scripts/mutation-registry.mjs` + импорт `MUTANTS` | 868 id, 868 уникальных — новые 7 присутствуют, коллизий нет |
| Ручной прогон 2 из 7 новых мутантов (`process-digest-dead-anchor`, `status-snapshot-hides-version-mismatch`): патч → тест краснеет → откат, `git status` чист | оба поймали мутацию (см. «AC · чем доказан · чем краснеет») |
| Построчная сверка «каждая непустая строка старого `docs/TESTING.md` есть в новом наборе файлов» (питоновский скрипт по множеству строк) | расхождение ровно в 2 строках — заголовок `# Manual testing checklist` и разделитель `---`, как заявлено в хендоффе |
| Аналогичная сверка блока «feature surface» `docs/STATUS.md` → `docs/STATUS-FEATURES.md` | тело перенесено дословно; секции «Where things live», «Open items», «How to resume», «Product scope» осознанно оставлены в `STATUS.md` (авторская пометка «принято предположительно») |
| Чтение диффа `process.yml`, сверка требуемых фраз/якорей и грамотности сокращения (какие абзацы ушли в канон §2.10/§8, что там всё ещё есть — #150, #102, #403, #234, #233, #237, #244, #252–259, `single-source-numbers.test.mjs`) | ничего не потеряно, только перенесено; числа слов промпта укладываются в тест `≤ 1400` |
| Чтение `docs/process/AUTHOR.md`, `REVIEWER.md`, `scripts/md-anchors.mjs`, `test/process-digests.test.mjs`, `test/entry-cost.test.mjs`, `test/status-snapshot.test.mjs`, `scripts/status-snapshot.mjs`, `scripts/inventory.mjs` целиком | проверено чтением, не исполнением, где не отмечено иное |
Не прогонялось и не требовалось: `golden:verify`, `smoke_*`, `pytest tests_backend`,
`model-invariants`, perf-профили — диф не затрагивает `src/**`,
`custom_components/**/*.py`, геометрию и перф-чувствительные пути. `git
fetch`/`pull`/`checkout` на другой SHA не выполнялись.
## AC · чем доказан · чем краснеет
| AC | Чем доказан | Чем краснеет |
|---|---|---|
| AC1: вход автора ≤ 12 000 слов | `test/entry-cost.test.mjs`, дополнительно `node scripts/entry-cost.mjs --check` (10747/12000) | мутант `entry-cost-author-route-over-budget` (+2000 слов в AUTHOR.md) — заявлен автором, не перепроверялся мной, признан по образцу двух проверенных вручную аналогов; мутант `entry-cost-budget-never-over` (`over` всегда `false`) — тоже заявлен, паттерн идентичен проверенным |
| AC2: каждый пункт конспекта ссылается на раздел канона | `test/process-digests.test.mjs` (3 теста: ссылки резолвятся, каждый пункт верхнего уровня цитирует канон, ключевые формулировки дословны и лежат в названном разделе) | мутант `process-digest-dead-anchor` — **перепроверен вручную**: битый якорь в AUTHOR.md красит тест «каждая ссылка» (AssertionError, `expected: true actual: false`), откат подтверждён `git status` пустым |
| AC3: `TESTING.md` ≤ 800 строк, приложения по индексу | `test/testing-notes-index.test.mjs`; независимая сверка — `wc -l docs/TESTING.md` = 699 | мутант `testing-notes-index-drops-section` (удалена строка индекса) — заявлен автором по тому же паттерну, что и два проверенных |
| Snapshot генерируется, а не пишется руками | `test/status-snapshot.test.mjs` (фикстурный git-репозиторий с тегами и версиями) | мутант `status-snapshot-hides-version-mismatch` — **перепроверен вручную**: подмена `versions.mismatches.length` на `false` красит тест «рассинхрон … не сглажен» (AssertionError на regex-match), откат подтверждён |
| Промпт ревьюера не потерял обязательного | `test/process-digests.test.mjs` («#634 промпт ревьюера») — список обязательных фраз + якорей, бюджет ≤ 1400 слов | пустое множество — тест регекспами ищет точные фразы; проверено чтением, что список фраз реально покрывает машинно значимые части (строка вердикта, `material_sha`, запрет fetch, REVIEW_DOC, таблица «чем краснеет», разделы повторного раунда, S1-new) |
Строка «мутант заявлен, не перепроверялся мной» — не пропуск: паттерн (find/replace
одной строки → guard тест по `--test-name-pattern`) идентичен двум проверенным
вручную образцам, оба ловятся корректно; отдельно проверен факт регистрации всех
7 id в `scripts/mutation-registry.mjs` без коллизий.
## Находки
Нет находок уровня High или Medium.
Low (снимается записью, без правки): в хендоффе автор указал «684 строки»
для `docs/TESTING.md`, фактическое значение — 699 строк. AC3 (`≤ 800`) от этого
не страдает, тест это подтверждает; расхождение — неточность числа в тексте
комментария, не в проверяемом артефакте. Не считаю нужным возвращать на правку.
## Что проверено и корректно
- Класс изменений — B/C, файлов класса A нет; правило «инфраструктурная задача —
сразу в ветку, без ТЗ» соблюдено, метка `S7-code-review` корректна.
- `PROCESS.md`: **ни одно правило по существу не изменено** — диф ограничен
абзацем о конспектах в шапке и уточнением про промпт ревьюера в §10.4;
сверено построчно.
- Ролевые конспекты (`docs/process/AUTHOR.md`, `REVIEWER.md`) — каждый пункт
верхнего уровня ссылается на существующий якорь `PROCESS.md`, ключевые
формулировки дословны и лежат в названном разделе (проверено тестом и
выборочно вручную по нескольким пунктам — трейлеры, лимит циклов, шесть
классов риска, «одно число — один источник», запрещённое).
- `scripts/md-anchors.mjs` строит якоря по алгоритму GitHub без схлопывания
дефисов (сознательно отличается от `check-docs.mjs`, комментарий это
объясняет) — по построенным тестам расхождений не найдено.
- `scripts/entry-cost.mjs`/`test/entry-cost.test.mjs` держат маршрут автора и
`AGENTS.md` («Reading order by role») в синхроне машинной сверкой списков
файлов и их порядка, а не на слово автора.
- `scripts/status-snapshot.mjs`: версии берутся из `parseVersionSources`
(`release-contract.mjs`, не тронут), счётчики — из вынесенной в отдельную
экспортируемую функцию `testInventory` (`scripts/inventory.mjs`, CLI-вывод при
прямом запуске не изменился), рассинхрон версий не сглаживается, а
показывается текстом «NOT synchronized: …». `--check` намеренно не в CI —
причина документирована в самом скрипте и подтверждена наблюдением (счётчик
тестов уже разошёлся на 20 всего за несколько влившихся задач).
- `docs/TESTING.md` → `docs/testing-notes/*`: перенос дословный (независимая
построчная сверка, расхождение только в заголовке и разделителе),
`test/golden-matrix.test.mjs` обновлён читать индекс с приложениями и
реально проходит (id `#242`/`#250` резолвятся из `geometry.md`).
- `docs/STATUS.md` → `docs/STATUS-FEATURES.md`: раздел «feature surface»
перенесён дословно (независимая построчная сверка), таблица «Standing state
and decisions» сохранила все прежние строки, кроме `Version` (ушла в
генерируемый Snapshot).
- `scripts/inventory.mjs`: рефакторинг в чистую экспортируемую функцию не
изменил CLI-поведение (monolith-блок и структура вывода на месте), снятие с
`NOT_AN_INPUT` подтверждено зелёным `check-inputs.mjs --coverage`.
- Промпт ревьюера в `process.yml` сокращён с делегированием правил в канон и
конспект; все примеры-прецеденты (#150, #102, #403, #234, #233, #237, #244,
#252–259) остались в `PROCESS.md` §2.10/§8, а не исчезли вместе с текстом
промпта — сверено чтением обеих версий. Битая ссылка «§2.9» → «§2.10»
действительно исправлена.
- Трейлеры коммита корректны: `Issue: #634`, `User-Visible: no` — оправдано
(нет пользовательского поведения), changelog не требуется и не тронут.
- Метамомент: этот самый прогон ревью выполняется по **старому** промпту
`process.yml` (ссылка на «§2.9», а не «§2.10» в системном приглашении этой
сессии) — ровно то расхождение, которое хендофф объявляет ожидаемым
(«`process.yml` исполняется из `main`», нужно зеркало после слияния). Это
независимое наблюдение подтверждает точность авторского отчёта, а не
находка против задачи.
## Чего не проверял
- `golden:verify`, `demo/smoke_*.mjs`, `pytest tests_backend`,
`model-invariants`, perf-профили — diff не касается `src/**`,
`custom_components/**/*.py`, геометрии/`layout`/`marker.space` или
перф-чувствительных путей; запуск был бы гейтом без предмета.
- Оставшиеся 5 из 7 новых мутантов (`process-digest-bullet-without-canon-link`,
`process-digest-key-rule-dropped`, `entry-cost-author-route-over-budget`,
`entry-cost-budget-never-over`, `testing-notes-index-drops-section`) не
прогонялись вручную по одному — проверены только регистрацией id без
коллизий и структурным сходством с двумя вручную подтверждёнными; будь один
из них некорректен по существу (например, `find` не находит целевую строку),
это не изменило бы вердикт этого раунда, но стоило бы отметить при полном
прогоне `node scripts/mutation-gate.mjs --check` (не выполнялся — дорогой
гейт, не гейт ревью при отсутствии диффа в исполняемом продуктовом коде).
- Живой прогон конвейера новым промптом — по документированной причине
(`process.yml` только на `main`) физически не наблюдаем на этом материале.
- `docs/reviews/INDEX.md`, `legacy/reviews/` — этот диф их не касается, вне
предмета ревью.
## Вердикт
Все три AC выполнены и доказаны автотестами, которые умеют падать (два
проверены лично). Побочные правки (Snapshot, промпт ревьюера, порядок чтения)
согласованы между собой и с каноном без потери содержания. High/Medium
находок нет.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/634-entry-cost`, коммит `7dc759726023` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `8264e3f8d100607a9a0a73eb524ebb5f8aa5ae2f`
```
git log --all --format='%H %T' | grep 8264e3f8d100
```
- Тело issue: `687a2c8867e593a6e98a5c816a50580cc6fb2385c4bc98464c899106c42c9390`
- Вердикт конвейера: `green` · High 0
+2 -1
View File
@@ -1,6 +1,6 @@
# Индекс ревью
Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1018, issue: 359. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`.
Генерируется `node scripts/reviews-index.mjs` (#635) — не редактировать руками. Документов: 1019, issue: 360. Вердикт: 🟢 зелёный · 🟡 жёлтый · 🔴 красный · ⚪ не распознан (свободная форма старых документов). H/M — число High/Medium по строке вердикта или заголовкам находок. Файлы — пути, названные в находках; ищите по имени файла: `grep form-kit INDEX.md`.
| Issue | Документ | Этап · раунд | Вердикт | H | M | Находки | Файлы |
|---|---|---|---|---:|---:|---|---|
@@ -17,6 +17,7 @@
| #635 | [CODE-REVIEW-635-r1.md](CODE-REVIEW-635-r1.md) | code · r1 | 🟡 жёлтый | 1 | 0 | индекс молчаливо теряет находки и врёт числами по текущему | `docs/reviews/CODE-REVIEW-639-r1.md` `CODE-REVIEW-637-r1.md` `docs/reviews/CODE-REVIEW-594-r1.md` `docs/LESSONS.md` |
| #635 | [CODE-REVIEW-635-r2.md](CODE-REVIEW-635-r2.md) | code · r2 | 🟡 жёлтый | 1 | 1 | docs/reviews/INDEX.md, зафиксированный в материале ревью, устарел на собственном SHA — …; parseFindings/parseFiles: фолбэк «первая строка тела блока» вырезает начало буллета и п… | `docs/reviews/INDEX.md` `SPEC-REVIEW-625-r1.md` `SPEC-REVIEW-625-r2.md` `CODE-REVIEW-625-r1.md` `CODE-REVIEW-625-r2.md` `process.yml` `test/reviews-index.test.mjs` `INDEX.md` |
| #635 | [CODE-REVIEW-635-r3.md](CODE-REVIEW-635-r3.md) | code · r3 | 🟢 зелёный | 0 | 0 | firstParagraph: ветка нет\b в фильтре мёртвая из-за ASCII-only \b в JS-регэкспах, расхо… | `scripts/reviews-index.mjs` |
| #634 | [CODE-REVIEW-634-r1.md](CODE-REVIEW-634-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — |
| #633 | [CODE-REVIEW-633-r1.md](CODE-REVIEW-633-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — |
| #630 | [CODE-REVIEW-630-r1.md](CODE-REVIEW-630-r1.md) | code · r1 | 🟢 зелёный | 0 | 0 | — | — |
| #629 | [SPEC-REVIEW-629-r1.md](SPEC-REVIEW-629-r1.md) | spec · r1 | 🟢 зелёный | 0 | 0 | — | — |