From 5aa8771dc3cd9bf23d170a511ff461927cbe05dc Mon Sep 17 00:00:00 2001 From: Matysh Date: Thu, 13 Aug 2026 14:24:50 +0300 Subject: [PATCH] docs: bring the process canon back in line with what actually runs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The canon moved into the repository in #112 and then stood still while the process kept moving. A document that lags is worse than no document: an agent reading it as truth acts on rules that no longer exist. It promised a pre-push hook that was never written, named labels in Russian that the repository has never used, listed a status set the gate no longer applies, and said nothing at all about the event-driven pipeline — the largest mechanism the process has. Label names are now English throughout and S8-merged is documented. Section 1 covers the configuration files the gate kept reporting as unclassified, and records that D beats A where paths overlap, since the built bundle lives inside custom_components/houseplan/frontend/. Section 10.1 admits that pre-push does not exist. Section 10.2 matches ALLOWED_STATUS in scripts/process-gate.mjs, including the two caveats that only surfaced once the pipeline ran. Section 10.4 is new and documents the four silent-failure traps that cost a working day each. The source-of-truth order now says that actual automation outranks its own description — this document included. Issue: #119 User-Visible: no --- PROCESS.md | 353 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 262 insertions(+), 91 deletions(-) diff --git a/PROCESS.md b/PROCESS.md index 314168a4..d71a0101 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -1,16 +1,23 @@ # Процесс работы над House Plan -> **Статус документа:** черновик 3 (2026-08-12), на согласование владельцу. -> Решения владельца, зафиксированные в этой редакции: прямые коммиты в `dev` без -> PR · канон статуса — **метки** · лёгкий трек для мелких задач **включён**. +> **Статус документа: канон** (редакция 2026-08-13). Решения владельца, на +> которых он стоит: прямые коммиты в `dev` **без PR** · канон статуса — **метки**, +> имена английские · лёгкий трек **включён** · автор и ревьюер — разные модели · +> инфраструктурные задачи идут **вне** флоу. > -> **Область действия:** обязателен для владельца и для любого агента (Cowork, -> Cursor Cloud, Codex, локальные сессии). Читается сразу после `AGENTS.md`, до -> `docs/STATUS.md`. +> **Область действия:** обязателен для владельца и для любого агента. Читается +> сразу после `docs/SCOPE.md` и `AGENTS.md`, до `docs/STATUS.md`. Живёт в +> репозитории: до августа 2026 канон лежал только в папке владельца, и свежий клон +> его не содержал вовсе. > -> **Приоритет источников:** GitHub Issues + Project v2 — канонический бэклог. -> Статус живёт в метках issue. При расхождении документации с GitHub побеждает -> GitHub; при расхождении процесса и привычки побеждает процесс. +> **Приоритет источников.** Канонический бэклог — GitHub Issues; статус живёт в +> метках, Project v2 остаётся человеческим представлением. При расхождении +> документации с GitHub побеждает GitHub. При расхождении этого документа с +> `.github/workflows/*.yml` и `scripts/*` побеждает **фактическая автоматизация**: +> она исполняется, а описание — нет. Расхождение при этом не игнорируется, а +> заводится issue с меткой `process`. +> +> При расхождении процесса и привычки побеждает процесс. --- @@ -26,29 +33,49 @@ | Класс | Что входит | Нужен ли issue | |---|---|---| | **A. Продукт** | `src/**`, `custom_components/houseplan/**/*.py`, `manifest.json`, `hacs.json`, `src/i18n/*.json`, `custom_components/**/translations/*` | **Да, обязательно.** Только из «Готово к разработке» или дальше | -| **B. Гейты и инструменты** | `test/**`, `tests_backend/**`, `demo/**`, `scripts/**`, `.github/workflows/**`, `rollup.config.mjs`, `tsconfig*.json` | **Да.** Может использовать issue того изменения, которое покрывает; самостоятельная работа над гейтом получает свой issue (тип «техдолг») | -| **C. Документация** | `docs/**`, `README*`, `CHANGELOG*`, `AGENTS.md` | Документирование A/B в том же коммите — часть DoD своего issue. Самостоятельная работа над документацией — свой issue | +| **B. Гейты и инструменты** | `test/**`, `tests_backend/**`, `demo/**`, `scripts/**`, весь `.github/**`, `.githooks/**`, `rollup.config.mjs`, `tsconfig*.json`, `package.json`, `package-lock.json`, `pytest.ini`, `.gitignore`, `.gitattributes` | **Да.** Может использовать issue того изменения, которое покрывает; самостоятельная работа над гейтом получает свой issue (тип `tech-debt`) | +| **C. Документация** | `docs/**`, `README*`, `CHANGELOG*`, `AGENTS.md`, `CONTRIBUTING.md`, `PROCESS*.md`, `LICENSE`, `(CODE\|SPEC)-REVIEW-*.md` | Документирование A/B в том же коммите — часть DoD своего issue. Самостоятельная работа над документацией — свой issue | | **D. Сгенерированное** | `dist/**`, `custom_components/houseplan/frontend/**`, `demo/srv/assets/houseplan-card.js`, `demo/golden/baselines/**` | Никогда не меняется само по себе. Коммит **только** класса D допустим лишь как релизный промоушен или как принятие эталонов с доказательством ревью | Практический смысл таблицы: «я только поправил тест» и «я только пересобрал бандл» перестают быть лазейками. +Классы неупорядочены, но при пересечении путей **D сильнее A**: собранный бандл +лежит внутри `custom_components/houseplan/frontend/`, и без этого правила он +считался бы продуктовым исходником. + +**Инфраструктурная задача идёт вне флоу** (решение владельца 2026-08-13, +issue #118). Признак механический: **ни одного файла класса A**. Такая задача +делается без ТЗ, ревью ТЗ, код-ревью и без прохода по статусам — флоу построен +для изменений, у которых есть персона и видимое поведение, а в инфраструктуре ТЗ +пересказывало бы очевидное, и автор с ревьюером оказались бы одной ролью. +Проверкой служат гейты и CI. Обязательным остаётся issue, трейлеры и зелёные +`typecheck`, `test`, `build`. + +Задача, задевающая класс A хотя бы одним файлом, инфраструктурной **не +является** и идёт полным флоу. «В основном инфраструктурная» не бывает: иначе +это дорога, по которой продуктовые правки минуют ревью. Признак задан через +класс файлов, а не через самоощущение исполнителя, именно поэтому. + --- ## 2. Жизненный цикл -Семь рабочих статусов и два служебных. Фазы тестирования в цикле сознательно +Восемь рабочих статусов и два служебных. Фазы тестирования в цикле сознательно **нет**: найденные позже дефекты заводятся отдельными issue и проходят цикл заново. Issue закрывается после выпуска беты. ``` -Новое → Аналитика и оценка → ТЗ в работе → ТЗ на ревью ⟲ → Готово к разработке → - → В разработке → Код-ревью ⟲ → Закрыт (после выпуска беты) +S1-new → S2-analysis → S3-spec → S4-spec-review ⟲ → S5-ready → + → S6-in-progress → S7-code-review ⟲ → S8-merged → закрыт при выпуске беты -служебные: Заблокировано (parking) Отклонено (закрыт) -⟲ — возврат на правки, не более 4 циклов (§4) +служебные: blocked (поверх статуса) rejected (закрыт) +⟲ — возврат на правки, не более 4 циклов (§4), на лёгком треке 2 ``` +Переходы `S4-spec-review` и `S7-code-review` выполняются **автоматически**: метка +порождает событие, событие запускает ревью (§10.4). Остальные ставит исполнитель. + ### 2.1 Новое — заведение задачи - **Кто:** любой — владелец, агент, пользователь (Telegram, GitHub). @@ -208,7 +235,7 @@ 16. **Стабильный релиз — promotion-only:** версии, сгенерированные бандлы, changelog и release-метаданные. Продуктового кода там нет. 17. **История `dev` не перезаписывается.** На неё ссылаются теги. Нарушение - исправляется следующим коммитом плюс issue с меткой `процесс` — не + исправляется следующим коммитом плюс issue с меткой `process` — не force-push'ем. 18. **AC доказывает автотест или запись ревьюера.** Фразы «проверил локально, всё работает» в процессе не существует: либо тест, который умеет падать, либо @@ -222,7 +249,7 @@ ## 4. Лимит циклов ревью: 4 Оба ревью-гейта возвращают задачу на правки не более **4 раз**. Счётчик виден в -имени документа: `-r1` … `-r4`; на четвёртом заходе ставится метка `ревью-4`. +имени документа: `-r1` … `-r4`; на четвёртом заходе ставится метка `review-4`. - **Что считается циклом:** отправка на ревью → вердикт с блокирующими находками → возврат. Уточняющий вопрос без вердикта циклом не считается. @@ -241,7 +268,7 @@ --- -## 5. Лёгкий трек (метка `малое`) +## 5. Лёгкий трек (метка `small`) **Критерии — все одновременно:** @@ -263,7 +290,7 @@ никогда — именно оно в этом процессе заменяет тестирование. Если по ходу выясняется, что критерий нарушен (появилась миграция, задело второй -модуль) — метка `малое` снимается, issue возвращается в «ТЗ в работе» и получает +модуль) — метка `small` снимается, issue возвращается в `S3-spec` и получает нормальный файл ТЗ. Это не провал, это ранняя диагностика. --- @@ -286,9 +313,19 @@ **Правило разделения:** ревьюер работает состязательно. Ему передаётся тег или диапазон коммитов и ТЗ — не рассказ автора о том, как всё хорошо. -**Принято по умолчанию, поправь если не так:** ревьюер — отдельная сессия -(Cowork / Codex / Cursor Cloud), выбор чередуется, лишь бы это была не та сессия, -что делала артефакт; релиз-менеджер — владелец. +**Роли закреплены за исполнителями** (решение владельца 2026-08-12): + +| Исполнитель | Роли | +|---|---| +| **Codex** | аналитик, автор ТЗ, разработчик, релиз-инженер по команде владельца | +| **Claude** | ревьюер ТЗ, ревьюер кода, вся инфраструктура и дистрибуция | +| **Владелец** | приоритет, скоуп, арбитраж, закрытие issue, команда на выпуск | + +Автор и ревьюер — **разные модели**, и это сильнее требования «другая сессия»: +одна модель, читая свой же артефакт заново, повторяет свои же слепые пятна. + +Ревью ТЗ и код-ревью держатся в **разных сессиях** Claude: ревьюер кода не должен +приходить с контекстом того, как обсуждали ТЗ. --- @@ -298,8 +335,8 @@ ``` issue #NN - ↔ ТЗ docs/specs/NN-slug.md (или тело issue при `малое`) - ↔ ревью ТЗ docs/reviews/SPEC-REVIEW-NN-rN.md (или комментарий при `малое`) + ↔ ТЗ docs/specs/NN-slug.md (или тело issue при `small`) + ↔ ревью ТЗ docs/reviews/SPEC-REVIEW-NN-rN.md (или комментарий при `small`) ↔ ветка issue/NN-slug ↔ коммиты трейлеры Issue: #NN · User-Visible: yes|no ↔ ревью кода docs/reviews/CODE-REVIEW--rN.md @@ -307,9 +344,44 @@ issue #NN ↔ бета тег, зелёный CI на точном SHA → закрытие ``` -Обязательные разделы ТЗ: проблема · скоуп и **не-скоуп** · контракт поведения · -UX · модель данных и миграция · i18n · критерии приёмки AC1…ACn с указанием -доказательства · план автотестов · риски · откат · release-артефакты. +Обязательные разделы ТЗ: **сценарий** · **что человек увидит до и после** · +проблема · скоуп и **не-скоуп** · контракт поведения · UX · модель данных и +миграция · i18n · критерии приёмки AC1…ACn с указанием доказательства · план +автотестов · риски · откат · release-артефакты. + +Два первых раздела — продуктовые, и они идут первыми не случайно. **Сценарий:** +какая персона (`docs/SCOPE.md`), на какой поверхности, в какой момент это +встретит. **Что человек увидит:** одной фразой, без терминов реализации. ТЗ, +которое не может ответить на эти два вопроса, описывает работу, а не изменение +продукта. + +**Размытое место не додумывается, а выносится владельцу.** Догадка, записанная +как факт, — худший вид дефекта: она проходит ревью, потому что выглядит решением. + +Но спрашивать обо всём нельзя: владелец один, и анкета из двадцати пунктов хуже +угадывания. Порог такой (решение владельца 2026-08-13). + +**Владельцу задаются только продуктовые вопросы** — что человек видит или делает +и какой объём видимых изменений входит в этот issue. Поведение в пограничном +случае; какая из персон важнее в конфликте; что считать приемлемой деградацией; +относится ли смежное поведение сюда или становится отдельной задачей. + +**Всё, чего пользователь не наблюдает, агенты решают сами** либо согласовывают +между собой: где хранится состояние, в каком модуле стоит гвард, именование, +раскладка файлов, стратегия тестов, механика миграции. Решение записывается явным +блоком в конце ТЗ — «принято предположительно, поменять свободно», и ревьюер +вправе его оспорить. Технический спор автора и ревьюера решается вердиктом, а не +владельцем; до него он доходит только при исчерпании лимита циклов (§4). + +**Смешанный вопрос делится, а не эскалируется целиком.** «Где живёт это +состояние» — техническое. «Переживает ли оно перезагрузку страницы и общее ли оно +для всех экранов» — продуктовое. + +Вопросы задаются **одним комментарием, пачкой**, каждый в форме: что неясно · +что изменится от ответа · **предлагаемый вариант по умолчанию**. Вопрос с готовым +вариантом стоит владельцу пяти секунд, вопрос без него — пяти минут. Пока ждём +ответа, issue остаётся в `S3-spec` и получает `blocked`: статус не подменяется, +`blocked` его дополняет, иначе конвейер считает задачу в работе, а она стоит. ### 7.2 Шаблоны комментариев @@ -320,20 +392,26 @@ UX · модель данных и миграция · i18n · критерии - **Занятие:** `Взял: <роль> · сессия · ветка issue/NN-slug` - **Хендофф:** `Сделано: … · Файлы: … · Гейты: <команда → результат> · НЕ сделано: … · Риски: … · Следующий статус: … · Новые issue: #…` -- **Вердикт ревью:** `Вердикт: зелёный/жёлтый/красный · цикл r/4 · High: N · - Medium: N → #… · Документ: docs/reviews/…` +- **Вердикт ревью:** `Вердикт: зелёный/жёлтый/красный · цикл r/<лимит> · + High: N · Medium: N → #… · Документ: docs/reviews/…` - **Закрытие:** `Выпущено в <тег беты> · CI: <ссылка> · Changelog: <ссылка>` +**Вперёд двигает только зелёный вердикт.** Жёлтый и красный возвращают автору; +разница между ними содержательна для человека, но не для маршрута. Первая +редакция конвейера (§10.4) пропускала жёлтый при `High: 0`, и первый же живой +прогон показал, почему это неверно: жёлтый там означал, что AC описывает неверное +изменение контракта — реализовать такое ТЗ значило бы сделать ошибку по инструкции. + ### 7.3 Расхождения с текущим состоянием, которые надо закрыть -1. **Ревью живут вне репозитория.** 20+ файлов `CODE-REVIEW-*.md` и - `SPEC-REVIEW-*.md` лежат только в личной папке владельца. Агент, пришедший - через месяц, не видит, почему решение принято именно так, и повторяет - разобранную ошибку. → `docs/reviews/`. -2. **Статус ТЗ дублирует статус issue.** `docs/specs/README.md` держит колонку +1. **Статус ТЗ дублирует статус issue.** `docs/specs/README.md` держит колонку «Статус ТЗ» со своим словарём («черновик решения», «в реализации», «реализовано»). Два источника статуса уже расходятся. Колонку убрать, оставить таблицу «issue ↔ ТЗ». +2. **Ревью до релиза 1.62 живут вне репозитория.** Документы `CODE-REVIEW-*.md` и + `SPEC-REVIEW-*.md` за прежний период лежат в папке владельца, и переносить их + задним числом смысла нет: они описывают код, которого уже нет. Новые документы + ревью кладёт в `docs/reviews/` сам конвейер, в ветку задачи. --- @@ -365,23 +443,41 @@ Performance зелёные на точном SHA; статусов issue не к доступом к Issues, в отличие от Project v2, который требует отдельного скоупа. Project v2 остаётся человеческим представлением и синхронизируется по меткам. +**Имена меток английские** (решение владельца 2026-08-12). Русские имена в этом +документе были только на бумаге; репозиторий с самого начала жил на английских. + | Метка | Статус | |---|---| -| `S1-новое` | Новое | -| `S2-аналитика` | Аналитика и оценка | -| `S3-тз` | ТЗ в работе | -| `S4-тз-ревью` | ТЗ на ревью | -| `S5-к-разработке` | Готово к разработке | -| `S6-в-разработке` | В разработке | -| `S7-код-ревью` | Код-ревью | -| `заблокировано` | Заблокировано (поверх статусной метки) | -| `отклонено` | Отклонено, issue закрыт | +| `S1-new` | Новое, не разобрано | +| `S2-analysis` | Аналитика и оценка | +| `S3-spec` | ТЗ в работе | +| `S4-spec-review` | ТЗ на ревью | +| `S5-ready` | Готово к разработке — единственный статус, из которого можно начать трогать код | +| `S6-in-progress` | В разработке, занято исполнителем | +| `S7-code-review` | Код-ревью | +| `S8-merged` | Ревью пройдено, код в `dev`, ждёт беты. Issue закрывается пачкой при выпуске | +| `blocked` | Ждём внешнего или владельца, **поверх** статусной метки | +| `rejected` | Отклонено, issue закрыт | -Модификаторы: `малое` (лёгкий трек), `hotfix`, `процесс`, `ревью-4`, -приоритет `P1`/`P2`/`P3`, тип `баг`/`фича`/`техдолг`. +Модификаторы: `small` (лёгкий трек, сложность ≤3), `hotfix`, `process`, +`review-4`; приоритет `P1`/`P2`/`P3`; тип `bug`/`feature`/`tech-debt`. +Тематические метки (`polish`, `infra`, `tests`, `docs`, `security`, `vacuum`) +ортогональны процессу. -Правила: ровно одна `S*`-метка; закрытый issue статусных меток не несёт; -`заблокировано` не заменяет статус, а дополняет его. +Инварианты: **ровно одна `S*`-метка** на открытом issue; закрытый issue статусных +меток не несёт; `blocked` не заменяет статус, а дополняет его. + +**В процесс берутся только issue, созданные владельцем** (решение владельца +2026-08-13). Репозиторий публичный, задачи заводят и посторонние; такие issue +бывают плохо оформлены или невалидны, и статусных меток им не ставят — инварианты +на них не распространяются. Проверять `user.login`. Что делать с чужим issue: +прочитать, при необходимости переформулировать и завести **свой** со ссылкой на +исходный, либо оставить до решения владельца. Не размечать и не брать в работу. + +`S8-merged` появился позже остальных и закрывает разрыв, который раньше +закрывался памятью человека: код принят, но бета ещё не вышла, и issue закрывать +рано. Без него принятая задача либо висела в `S7-code-review`, либо закрывалась +досрочно. --- @@ -402,46 +498,109 @@ Project v2 остаётся человеческим представление `npm ci` вызывает `prepare` сам — значит, хуки появляются в каждом окружении, включая свежий контейнер облачного агента, без отдельного шага в инструкции. -- **`commit-msg`** — отклоняет коммит без `Issue: #NN`, если тронут класс A или B; - проверяет `User-Visible`. -- **`pre-push`** — прогоняет `scripts/process-gate.mjs` по всему пушимому - диапазону. Это и есть блокирующий гейт вместо PR. +- **`commit-msg`** — есть, работает. Отклоняет коммит без терминального + `Issue: #NN`, требует ровно один `User-Visible: yes|no`, а для коммитов, + трогающих `demo/golden/baselines/**`, — `Release:` плюс `Baseline-Reviewed:`. + Реализация — `scripts/validate-commit-provenance.mjs`, тот же скрипт вызывается + job `provenance` в `validate.yml`. +- **`pre-push`** — **не реализован.** Задумывался как блокирующий гейт вместо PR; + фактически блокирующей проверки на клиенте нет, и `process-gate.mjs` работает + только догоняющим job в CI (§10.3). Долг известен, отдельная задача. + +Файл хука обязан быть исполняемым: `assertHookMode` проверяет бит в индексе. +Через GitHub API режим не выставляется — хук, отправленный так, приезжает +`100644`, и проверка его отвергает. Ставить `git update-index --chmod=+x`. ### 10.2 Что проверяет `process-gate.mjs` -Офлайн, без GitHub API: +Реализовано, `scripts/process-gate.mjs`, issue #105. Офлайн, без GitHub API: -1. трейлер `Issue: #NN` у каждого коммита класса A/B; +1. трейлер `Issue: #NN` у каждого коммита класса A/B, допускается несколько; 2. имя ветки `issue/NN-slug` соответствует трейлерам; -3. для класса A существует `docs/specs/NN*-*.md` со ссылкой на issue — **или** - issue помечен `малое` (для этого нужен этап 2, до него — исключение по списку); +3. для класса A существует `docs/specs/NN-*.md` — **или** issue помечен `small`. + Офлайн это предупреждение: лёгкий трек держит ТЗ в теле issue, и без чтения + меток «ТЗ в issue» неотличимо от «ТЗ не написано». С `--issues` — отказ; 4. `User-Visible: yes` → правки в обоих changelog в том же коммите; 5. коммит только класса D невалиден без `Release: vX.Y.Z` либо `Baseline-Reviewed: <ссылка на прогон CI>`; 6. релизный коммит не содержит изменений в `src/` и `custom_components/**/*.py`; 7. документов ревью на один issue не больше четырёх (`-r1`…`-r4`). -С токеном GitHub (PAT уже есть у релизных скриптов): +С токеном GitHub: 8. `--issues` тянет каждый упомянутый issue и требует метку из - {`S5-к-разработке`, `S6-в-разработке`, `S7-код-ревью`}; закрытый или - отсутствующий issue — отказ (fail closed); -9. `npm run release:prerelease -- --issues=…` отказывается, если у issue нет - зелёного вердикта код-ревью; -10. закрытие issue и снятие статусных меток автоматизируются по факту публикации - беты — в `publish-prerelease.yml`, а не по памяти человека. + {`S5-ready`, `S6-in-progress`, `S7-code-review`, `S8-merged`}; закрытый, + недоступный или помеченный `blocked` — отказ (**fail closed**). + +Две оговорки к проверке 8, обе выяснились при реализации. + +**`S8-merged` входит в множество**, хотя по смыслу задача уже принята. Причина +механическая: конвейер (§10.4) сливает ветку в `dev` **раньше**, чем ставит метку, +Validate стартует от этого push и успевает прочитать issue уже в `S8-merged`. +Строгое множество красило бы каждую принятую задачу. Локальная строгость +возвращается флагом `--no-merged`. + +**Статус спрашивается только у коммитов класса A/B.** Правило №1 говорит о +продуктовом коде и инструментах, а не о документации. Иначе краснел бы каждый +документ ревью: он ложится в ветку задачи, пока та в `S4-spec-review` или +`S7-code-review`, то есть заведомо вне рабочего множества. + +Не реализовано и остаётся долгом: + +9. `npm run release:prerelease -- --issues=…` не проверяет, есть ли у issue + зелёный вердикт код-ревью; +10. закрытие issue и снятие статусных меток при публикации беты делаются руками — + `node process-labels/apply.mjs cleanup --apply`, а не `publish-prerelease.yml`. + Пропуск этого шага уже ломал инвариант «закрытый issue без статусной метки». ### 10.3 Страховка и разбор -- **Тот же `process-gate.mjs` — job в `validate.yml`.** При прямом push проверка - догоняющая: код уже в `dev`, CI краснеет после. Это принятая цена отказа от PR. +- **`process-gate.mjs` — job `process-gate` в `validate.yml`**, без `needs`: + краснеет сам и не роняет остальные. При прямом push проверка догоняющая: код уже + в `dev`, CI краснеет после. Это принятая цена отказа от PR — и, пока `pre-push` + не написан, единственная машинная проверка процесса. - **Нарушение не откатывается force-push'ем** (правило 17): исправляющий коммит - плюс issue с меткой `процесс`. Починить надо проверку, а не только симптом. -- **Еженедельная гигиена** (workflow): issue в «Новое» дольше 14 дней и в - «В разработке» дольше 7; issue класса A в `S5` без ТЗ; issue с нулём или двумя - `S*`-метками; коммиты без трейлера за неделю — **цель 0**; rework rate и число - issue, дошедших до `ревью-4`; **баги, заведённые после закрытия беты** — прямая - цена отказа от фазы тестирования. + плюс issue с меткой `process`. Починить надо проверку, а не только симптом. +- **Еженедельная гигиена** (workflow): issue в `S1-new` дольше 14 дней и в + `S6-in-progress` дольше 7; issue класса A в `S5-ready` без ТЗ; issue с нулём или + двумя `S*`-метками; коммиты без трейлера за неделю — **цель 0**; rework rate и + число issue, дошедших до `review-4`; **баги, заведённые после закрытия беты** — + прямая цена отказа от фазы тестирования. + +### 10.4 Событийный конвейер: метка как триггер + +`.github/workflows/process.yml`, issue #114. Смена статусной метки — не запись в +журнал, а **сообщение**: она порождает событие, событие запускает следующий шаг. + +``` +S4-spec-review → ревью ТЗ → S5-ready либо возврат в S3-spec +S7-code-review → код-ревью → слияние в dev → S8-merged либо возврат в S6-in-progress +``` + +Ревьюер — `anthropics/claude-code-action`. Он читает `docs/SCOPE.md`, `AGENTS.md`, +этот документ и тело issue, публикует разбор комментарием, заводит issue на каждую +Medium-находку, кладёт документ в `docs/reviews/` ветки задачи и возвращает вердикт +структурированным JSON. **Метку переставляет отдельный детерминированный шаг по +вердикту, а не модель.** + +Четыре вещи, без которых конвейер молча не работает: + +1. метки переставляет **PAT**, а не `GITHUB_TOKEN`: GitHub намеренно не порождает + события от `GITHUB_TOKEN`, чтобы не было циклов, и цепочка обрывалась бы после + первого шага без ошибок в логах; +2. `process.yml` обязан лежать в **ветке по умолчанию**: для события `issues` + GitHub берёт workflow только оттуда, независимо от содержимого `dev`; +3. слияние в `dev` происходит **до** простановки `S8-merged`, иначе метка врёт в + промежутке — она утверждает, что код в `dev`; +4. многострочный текст внутри `run:` — только через heredoc: строка с нулевым + отступом обрывает блок YAML, и скрипт обрезается без ошибки парсера. + +**Автор обязан дождаться вердикта, а не заканчивать сессию.** Ревью идёт от десяти +минут до сорока пяти. Отчёт «передал на ревью» останавливает конвейер там, где он +мог идти сам: вердикт придёт, а подхватить его будет некому. У агента нет часов — +он существует только в момент своего хода, поэтому ожидание это опрос: раз в 90 +секунд, не более 30 попыток. Смотреть на метку, а не на комментарий: метка и есть +состояние. При `blocked` не ждать — задача ждёт владельца. --- @@ -486,27 +645,35 @@ Project v2 остаётся человеческим представление - force-push в `dev`; - ручное копирование на домашний инстанс. -**Нарушение процесса — тоже issue** (метка `процесс`): если правило удалось +**Нарушение процесса — тоже issue** (метка `process`): если правило удалось нарушить незаметно, виновата проверка. --- ## 13. Внедрение -1. Создать метки §9; разметить 38 открытых issue. Всё, что по - `docs/specs/README.md` «в реализации», но не прошло ревью, — в честный статус. -2. Перенести существующие `CODE-REVIEW-*.md` и `SPEC-REVIEW-*.md` в - `docs/reviews/`; убрать колонку «Статус ТЗ» из `docs/specs/README.md`. -3. Завести issue на сам гейт (класс B, техдолг): `scripts/process-gate.mjs`, - `.githooks/`, `prepare`-скрипт, job в `validate.yml`. По новому процессу он - сам обязан пройти ТЗ → ревью → реализацию. -4. Закрыть текущий долг ревью: `beta.2…beta.4` без код-ревью, среди них две новые - фичи (#90, #94). -5. Завести issue на находку «смок `visual_continuity` не умеет падать» из разбора - 11.08 — это ровно тот класс дефектов, который в процессе без ручного - тестирования стоит дороже всего. -6. `BACKLOG-2026-08-11.md` объявить разовым отчётом: решения — в issue. -7. Добавить в `AGENTS.md` блок §14. +Состояние на 2026-08-13. + +1. ✅ **Метки созданы, бэклог размечен.** У всех открытых issue владельца ровно + одна `S*`-метка, инварианты чистые. +2. ⏳ **Колонку «Статус ТЗ» из `docs/specs/README.md` убрать** — не сделано, §7.3 + п.1. Перенос старых документов ревью в `docs/reviews/` отменён: они описывают + код, которого уже нет. +3. ✅ **Гейт написан** — `scripts/process-gate.mjs` плюс job в `validate.yml`, + issue #105. Прошёл **вне** флоу как инфраструктурная задача (§1, issue #118), а + не через ТЗ и ревью, как предполагала прежняя редакция этого пункта. +4. ✅ **Долг ревью списан решением владельца.** Беты `beta.2`…`beta.10` сделаны по + прежнему процессу и не пересматриваются. Точка отсчёта — релиз 1.62.0; отсчёт + начинается с первой беты следующей линии. +5. ⏳ Завести issue на находку «смок `visual_continuity` не умеет падать» — это + ровно тот класс дефектов, который в процессе без ручного тестирования стоит + дороже всего. +6. ✅ `BACKLOG-2026-08-11.md` — разовый отчёт, решения живут в issue. +7. ✅ `AGENTS.md` переписан целиком, шире блока §14. +8. ✅ **Канон перенесён в репозиторий** (issue #112). До этого полный процесс жил + только в папке владельца, а в репозитории лежал файл на 51 строку про трейлеры + коммитов — из свежего клона канон не был виден вообще. +9. ⏳ **`pre-push` не написан** (§10.1). Блокирующей проверки на клиенте нет. --- @@ -519,10 +686,14 @@ Project v2 остаётся человеческим представление «Готово к разработке» или дальше. Полные правила, критерии статусов и гейты — `docs/PROCESS.md`, читать до начала работы. -Жизненный цикл (статус = метка issue): `S1-новое` → `S2-аналитика` → `S3-тз` → -`S4-тз-ревью` → `S5-к-разработке` → `S6-в-разработке` → `S7-код-ревью` → -закрытие после выпуска беты. Оба ревью возвращают на правки не более 4 циклов; -пятый заход — разбор у владельца (разделить / отклонить / арбитраж). +Жизненный цикл (статус = метка issue): `S1-new` → `S2-analysis` → `S3-spec` → +`S4-spec-review` → `S5-ready` → `S6-in-progress` → `S7-code-review` → `S8-merged` +→ закрытие пачкой при выпуске беты. Оба ревью возвращают на правки не более 4 +циклов; пятый заход — разбор у владельца (разделить / отклонить / арбитраж). + +Ревью запускается **само** от меток `S4-spec-review` и `S7-code-review` и идёт до +45 минут. Поставив такую метку, автор не заканчивает работу, а ждёт смены метки +опросом и продолжает по тому, чем она стала. - ветка `issue/-`, коммиты с трейлерами `Issue: #NN` и `User-Visible: yes|no`; - работаем прямыми коммитами в `dev`, без PR: блокирующий гейт — локальный @@ -531,7 +702,7 @@ Project v2 остаётся человеческим представление - автор ≠ ревьюер, ни для ТЗ, ни для кода; - фазы ручного тестирования нет: автотесты пишутся в реализации, AC проверяет код-ревью, найденные позже дефекты — новые issue типа «баг»; -- мелкие задачи (метка `малое`, сложность ≤3): ТЗ в теле issue, ревью ТЗ +- мелкие задачи (метка `small`, сложность ≤3): ТЗ в теле issue, ревью ТЗ комментарием, код-ревью — как обычно; - найденное вне скоупа — новый issue, а не попутная правка; - issue закрывает релиз-менеджер после выпуска беты, не исполнитель.