diff --git a/.github/workflows/process.yml b/.github/workflows/process.yml index 9d9be65e..04226fae 100644 --- a/.github/workflows/process.yml +++ b/.github/workflows/process.yml @@ -978,64 +978,52 @@ jobs: ${{ needs.prepare.outputs.spec_body_changed == 'true' && format('ТЗ в теле issue менялось после зелёного ревью ТЗ ({0}, записанный хеш {1}). GitHub хранит правки тела без diff — дельту показать нельзя, поэтому AC сверяются с ТЕКУЩИМ текстом целиком, а не по дельте, и находка называется в вердикте (#517).', needs.prepare.outputs.spec_body_doc, needs.prepare.outputs.spec_body_recorded) || '' }} - **Если цикл не первый — объём разбора по дельте, а не заново** - (PROCESS.md §2.9, issue #214). Раньше промпт был одинаковым для - всех раундов, и повторный цикл заново выводил продуктовую рамку и - перепроверял AC, которых правка не касалась: r2 по #150 стоил - полного прогона ради одной строки в тестовой фикстуре. - - Порядок для r2 и дальше: - 1. найди вердикт предыдущего раунда в комментариях issue и SHA, - на котором он получен. SHA в вердикте не назван — это находка; - 2. объяви дельту: `git diff <тот SHA>..HEAD` для кода, дифф файла - ТЗ или тела issue для spec. Дельта — предмет этого раунда; - 3. по каждой находке предыдущего раунда покажи, чем именно она - закрыта: строка кода или текста, а не заявление автора; - 4. заново проверяй только те AC, чьё доказательство дельта - задевает. Остальные наследуй; - 5. в документе обязателен раздел «Унаследовано из r»: что - принято без повторной проверки, со ссылкой на документ того - раунда и SHA, на котором вывод получен. Без этого перечня - сокращение — молчаливое доверие, а такой тихий успех уже - дважды стоил дня (#171, #207). - - Разбор остаётся ПОЛНЫМ, если дельта не локальна: ребейз на ушедший - вперёд dev (после ребейза это другой код, §7.2), смена контракта - поведения, задета новая подсистема, либо объём дельты сопоставим с - исходной задачей. Сомневаешься — разбирай полностью и скажи почему. - - Сокращается объём РАЗБОРА, а не строгость: правка по замечанию - способна сломать AC, который предыдущий раунд признал выполненным — - так появилась регрессия #102. Поэтому граница не «только находки», а - «находки плюс всё, до чего дотягивается дельта». + Правила ревью в этом промпте не повторяются (#634): их канон — + PROCESS.md, выжимка для ревьюера — docs/process/REVIEWER.md, где + каждый пункт ссылается на свой раздел канона. Ниже — только то, что + относится к этому прогону, и требования, которые нельзя пропустить. Прочитай в этом порядке, прежде чем судить: 1. docs/SCOPE.md — зачем продукт существует и для кого. Он ограничитель: «features are built, improved and accepted only if they serve a job listed here». Первый вопрос к задаче — какую строку Core user jobs она закрывает. - 2. AGENTS.md и PROCESS.md — процесс, классы изменений, трейлеры, - лимит циклов, формат вердикта. - 3. Тело issue #${{ github.event.issue.number }} и все комментарии. - 4. Если меняется видимое поведение — docs/USER-GUIDE.ru.md: + 2. docs/process/REVIEWER.md — обязанности ревьюера: позиция, + ревью ТЗ, код-ревью, объём гейтов, повторный раунд, находки и + вердикт. Раздел PROCESS.md по ссылке открывай, когда пункт + касается твоего решения; при расхождении прав PROCESS.md. Если + файла в материале нет — читай PROCESS.md §2.4, §2.7, §2.10, + §4, §7.2, §8, §12. Задача правит сам конвейер, гейты или + процесс — PROCESS.md целиком, §10 в первую очередь. + 3. AGENTS.md — классы изменений, трейлеры, гейты, формат вердикта. + 4. Тело issue #${{ github.event.issue.number }} и все комментарии. + 5. Если меняется видимое поведение — docs/USER-GUIDE.ru.md: терминология интерфейса берётся оттуда, а не изобретается. - 5. Канонический документ затронутой подсистемы: docs/SUN.md, + 6. Канонический документ затронутой подсистемы: docs/SUN.md, LIGHT.md, CANVAS.md, WALL-THICKNESS.md, UX-MODES.md, CONFIG-COMPATIBILITY.md, TOUCH-SUPPORT.md. + **Если цикл не первый — объём разбора по дельте, а не заново** + (PROCESS.md §2.10, issue #214): найди вердикт и материал + предыдущего раунда (блок «Материал раунда» его документа), объяви + дельту `git diff <тот SHA>..HEAD` (для spec — дифф тела issue или + файла ТЗ), по каждой находке покажи, чем именно она закрыта — + строка кода или текста, а не заявление автора, — и заново проверяй + только AC, чьё доказательство дельта задевает. Разбор остаётся + ПОЛНЫМ, если дельта не локальна: ребейз на ушедший вперёд dev, + смена контракта, новая подсистема, объём сопоставим с задачей. + Сомневаешься — разбирай полностью и скажи почему. Сокращается + объём РАЗБОРА, а не строгость. + Для этапа spec: ТЗ живёт в теле issue (#517) — читай его, а не файл. Файлы docs/specs/-*.md — архив ТЗ до 2026-09-10: если такой файл есть у старой задачи, он и есть материал, новые не создаются. Проверь обязательные разделы §7.1, однозначность каждого AC и - указание способа доказательства. Отдельно проверь, что автор не - выдал догадку за решение: утверждение о поведении, которого нет ни - в одном документе и которое не помечено как предположение, — + указание способа доказательства. Утверждение о поведении, которого + нет ни в одном документе и которое не помечено как предположение, — замечание. Не бывает сложной задачи без единого открытого вопроса. - - Владельцу задаются только продуктовые вопросы: что человек видит или - делает и каков объём видимых изменений в этом issue. Технический - вопрос, вынесенный владельцу, — тоже замечание: ты его снимаешь и - решаешь по существу в своём вердикте. + Технический вопрос, вынесенный владельцу, — тоже замечание: ты его + снимаешь и решаешь по существу в своём вердикте. Для этапа code: материал — диапазон `git log --oneline origin/dev..HEAD` и `git diff origin/dev...HEAD`. **Материал ревью — ровно @@ -1044,95 +1032,60 @@ jobs: привязан к этому SHA (#312), и страж слияния сверяет вершину ветки с ним. Если автор в issue называет более новый коммит, которого в материале нет, — это находка «материал не был запушен до метки», а не - повод подтянуть его самому (#437 r3→r4 стоил лишнего раунда именно так, - #499). Ручного тестирования в цикле нет, + повод подтянуть его самому (#499). Ручного тестирования в цикле нет, поэтому именно ты отвечаешь на вопрос «оно вообще работает». По каждому AC: либо он доказан автотестом и ты убедился, что тест умеет падать, либо разобран по коду с явной записью «проверено - чтением, не исполнением». «Verified» без названной команды и её - результата доказательством не является. Зависимости уже установлены - workflow, Chromium тоже — `npm ci` выполнять не нужно. Проверь - трейлеры Issue и User-Visible, при User-Visible: yes — правки в оба - changelog в том же коммите. + чтением, не исполнением». Для защитного AC (валидация, гард, лимит, + отказ, инвариант) в документе обязательна строка таблицы + «AC · чем доказан · чем краснеет» с результатом прогона; пустой + третий столбец — находка Medium (§2.7, #435). «Verified» без + названной команды и её результата доказательством не является. + Проверь трейлеры Issue и User-Visible, при User-Visible: yes — правки + в оба changelog в том же коммите. Если дифф меняет величину, видимую + пользователю, назови прямо: какое число видно дважды и один ли у + него источник (§8). - **Объём гейтов соразмерен задаче.** Прогонять весь набор на каждой - правке — не тщательность, а потеря времени: полные наборы это - предрелизный гейт (PROCESS.md §8), а не гейт ревью. + **Объём гейтов соразмерен задаче** (PROCESS.md §8): полные наборы — + предрелизный гейт, а не гейт ревью. ${{ needs.prepare.outputs.validated_note }} Если зелёного прогона на этом SHA нет — прогоняешь сам, они дешёвые, - и в повторном раунде тоже: код изменился, а стоят они минуты: - `npx tsc --noEmit`, `npm test`, `npm run build` со сверкой трёх - копий бандла. Плюс `node scripts/check-docs.mjs`, если diff трогает - `src/**`: отпечаток скриншотов документации считается по всему - `src/**`, поэтому любая правка фронтенда делает его устаревшим — - выбирать тут нечего. Пропуск этого шага в #230 и #234 оставил `dev` - с красным job `docs` до следующей задачи (#237). - - Если diff трогает геометрию или ссылки на неё — рёбра комнат, - записи толщины, `layout`, `marker.space`, `open_spans` — обязательны - инварианты модели (#254): `npm test` уже гоняет их на всех моделях - проекта, а на конкретной конфигурации они проверяются командой - `npm run invariants -- --config <экспорт или ответ config/get>`. - Три вопроса, на которые они отвечают, и все три уже стоили - продукту дефектов: не исчезла ли запись толщины (#253), разрешима ли - каждая ссылка (#244, #252) и равен ли ключ записи толщины ключу - решёточного ребра (#258, #259). Последний сравнивает строки без - допусков: сдвиг ключа на один шаг решётки равен допуску первых двух, - поэтому они на нём промахиваются. Если задача меняет геометрию, а - инварианты в отчёте не названы — это непрогнанный гейт, а не мелочь. - - По необходимости, и «необходимость» определяется diff'ом и AC: - - браузерные смоки `demo/smoke_*.mjs` — названные в AC плюс те, - что печатает `node scripts/smoke-select.mjs --base --head `. - Сколько их всего — считает `ls demo/smoke_*.mjs | wc -l`; вшитое - в этот текст число трижды расходилось с деревом, поэтому его - здесь больше нет. Прогон всех уместен только когда задача - действительно задевает всё. Выбирать по теме недостаточно: регресс #234 поймал - `smoke_wall_junctions`, который по названию про стыки стен, а не - про толщину отрезка. Инструмент печатает три вида ответа, и они - разные: «прямое совпадение» — смок называет изменённый символ, - «зарегистрированная связь» — смок проверяет следствие контракта, - не называя его, «НЕОПРЕДЕЛЁННОСТЬ» — связь не доказана, и это не - разрешение ничего не прогонять. Вывод инструмента прикладывается - к комментарию ревью вместе с решением по каждой строке: прогнал - либо не прогнал и почему. Слабые связи (одно распространённое - имя) — повод посмотреть, а не обязанность прогонять; - - `npm run golden:verify` — если diff может изменить видимый - результат: рендер, геометрия, стили, слои; - - `python -m pytest tests_backend -q` — если тронут - `custom_components/**/*.py`; - - performance-профили — если названы в AC либо тронуты - чувствительные к перфу пути. - - **Одно число — один источник.** Если дифф добавляет или меняет - величину, видимую пользователю, назови в отчёте прямо: какое число - видно дважды (превью против записи, подпись против площади, - подсветка инструмента против сохранённого значения) и один ли у него - источник. Три дефекта подряд имели именно эту причину — #234, #233 и - способ, которым #234 обнаружили. Механическая часть закреплена - тестом `test/single-source-numbers.test.mjs`, смысловая — твоя. - - Дисциплина «тест должен уметь падать» не отменяется, но применяется к - тем тестам, которые ты прогонял. + и в повторном раунде тоже: `npx tsc --noEmit`, `npm test`, + `npm run build` со сверкой трёх копий бандла, плюс + `node scripts/check-docs.mjs`, если diff трогает `src/**`. + Зависимости уже установлены workflow, Chromium тоже — `npm ci` + выполнять не нужно. По диффу и AC: браузерные смоки — названные в AC + плюс вывод `node scripts/smoke-select.mjs --base --head `, + приложенный к комментарию с решением по каждой строке: прогнал либо + не прогнал и почему. Три вида ответа инструмента разные: «прямое + совпадение», «зарегистрированная связь», «НЕОПРЕДЕЛЁННОСТЬ» — связь + не доказана, и это не разрешение ничего не прогонять; слабые связи — + повод посмотреть, а не обязанность прогонять; + `npm run golden:verify` при видимом изменении; + `python -m pytest tests_backend -q` при правке + `custom_components/**/*.py`; инварианты модели + `npm run invariants -- --config <экспорт>` при правке геометрии или + ссылок на неё (#254) — задача меняет геометрию, а инварианты в + отчёте не названы, это непрогнанный гейт, а не мелочь; + performance-профили, если названы в AC. Дисциплина «тест должен + уметь падать» не отменяется, но применяется к тем тестам, которые + ты прогонял. **В комментарии обязателен перечень: какие гейты прогнал, какие нет и - почему.** Это условие честности такого сужения: непрогнанный гейт - становится видимым решением, а не молчаливым пропуском. Раздел «чего - не проверял» в документе ревью — не формальность, а главный его - раздел на коротких задачах. + почему.** Раздел «чего не проверял» в документе ревью — не + формальность, а главный его раздел на коротких задачах. Ты НЕ правишь ни ТЗ, ни продуктовый код. Только оцениваешь. Серьёзность: High блокирует; Medium В СКОУПЕ задачи чинится в ней же — без High это жёлтый вердикт и возврат автору, отдельный issue - НЕ заводится (решение владельца 2026-08-19, #202: заведение и - обслуживание issue дороже правки на месте); Low либо правится, - либо снимается с записью. Жёлтый вердикт допустим и при полностью - выполненных AC, если изменение не решает заявленный сценарий или - ухудшает смежный. Продуктовое рассуждение расширяет вопросы, но не - отменяет AC и не даёт права менять скоуп. + НЕ заводится (#202); Low либо правится, либо снимается с записью. + Жёлтый вердикт допустим и при полностью выполненных AC, если + изменение не решает заявленный сценарий или ухудшает смежный. + Продуктовое рассуждение расширяет вопросы, но не отменяет AC и не + даёт права менять скоуп. Только Medium-находку ВНЕ скоупа задачи (попутный дефект соседнего поведения, который в этой ветке чинить нельзя) заведи отдельным @@ -1142,13 +1095,11 @@ jobs: Напиши полный документ ревью в файл, путь которого лежит в переменной окружения REVIEW_DOC (абсолютный, ВНЕ репозитория). - - Почему не в docs/reviews: документ там был некоммитнутым файлом того - же дерева, которое ты мутируешь, проверяя «умеет ли тест падать». На - #220 три раунда подряд документ исчезал — восстановление дерева - (`git checkout -- .`, `git clean -fd`) сносит собственный артефакт - ревью, потому что он untracked. В репозиторий его положит шаг - публикации, взяв из REVIEW_DOC; тебе трогать docs/reviews не нужно. + Не в docs/reviews: восстановление дерева после проверки «умеет ли + тест падать» (`git checkout -- .`, `git clean -fd`) сносит + untracked-файл, и на #220 документ так исчезал три раунда подряд. + В репозиторий его положит шаг публикации, взяв из REVIEW_DOC; + тебе трогать docs/reviews не нужно. В самом репозитории не создавай файлов вообще: любые изменения в рабочей копии будут отброшены. Имя документа в docs/reviews шаг