mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
docs: bring the process canon back in line with what actually runs
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
This commit is contained in:
+262
-91
@@ -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-<tag|NN>-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 · критерии
|
||||
- **Занятие:** `Взял: <роль> · сессия <id> · ветка issue/NN-slug`
|
||||
- **Хендофф:** `Сделано: … · Файлы: … · Гейты: <команда → результат> ·
|
||||
НЕ сделано: … · Риски: … · Следующий статус: … · Новые issue: #…`
|
||||
- **Вердикт ревью:** `Вердикт: зелёный/жёлтый/красный · цикл r<N>/4 · High: N ·
|
||||
Medium: N → #… · Документ: docs/reviews/…`
|
||||
- **Вердикт ревью:** `Вердикт: зелёный/жёлтый/красный · цикл r<N>/<лимит> ·
|
||||
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/<NN>-<slug>`, коммиты с трейлерами `Issue: #NN` и `User-Visible: yes|no`;
|
||||
- работаем прямыми коммитами в `dev`, без PR: блокирующий гейт — локальный
|
||||
@@ -531,7 +702,7 @@ Project v2 остаётся человеческим представление
|
||||
- автор ≠ ревьюер, ни для ТЗ, ни для кода;
|
||||
- фазы ручного тестирования нет: автотесты пишутся в реализации, AC проверяет
|
||||
код-ревью, найденные позже дефекты — новые issue типа «баг»;
|
||||
- мелкие задачи (метка `малое`, сложность ≤3): ТЗ в теле issue, ревью ТЗ
|
||||
- мелкие задачи (метка `small`, сложность ≤3): ТЗ в теле issue, ревью ТЗ
|
||||
комментарием, код-ревью — как обычно;
|
||||
- найденное вне скоупа — новый issue, а не попутная правка;
|
||||
- issue закрывает релиз-менеджер после выпуска беты, не исполнитель.
|
||||
|
||||
Reference in New Issue
Block a user