@rt-tools/agent-kit 0.5.2 → 0.6.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.
Files changed (52) hide show
  1. package/README.md +34 -6
  2. package/assets/checks/check-file-size.mjs +127 -0
  3. package/assets/checks/rt-kit-checks.config.mjs +10 -0
  4. package/assets/defaults/gate-map.sh +90 -34
  5. package/assets/defaults/project.sh +26 -3
  6. package/assets/hooks/skill-gate-layers.sh +156 -0
  7. package/assets/hooks/skill-gate.sh +11 -2
  8. package/assets/laws/code-structure.md +3 -0
  9. package/assets/laws/delivery.md +9 -0
  10. package/assets/laws/observability.md +46 -0
  11. package/assets/laws/project-documentation.md +4 -0
  12. package/assets/laws/reuse-first.md +2 -0
  13. package/assets/laws/verifiability.md +5 -0
  14. package/assets/patterns/browser-verification-stand.md +22 -2
  15. package/assets/patterns/doc-style-trace.md +111 -0
  16. package/assets/patterns/git-workflow-commit.github.md +1 -1
  17. package/assets/patterns/git-workflow-docker.md +203 -0
  18. package/assets/patterns/git-workflow-secrets.md +93 -0
  19. package/assets/patterns/observability-record.md +114 -0
  20. package/assets/patterns/ownership-session-procedure.md +102 -0
  21. package/assets/patterns/seo-verify.md +1 -1
  22. package/assets/patterns/spec-driven-rule.md +5 -0
  23. package/assets/patterns/styling-bem-sheet.md +178 -0
  24. package/assets/patterns/task-flow-close.md +20 -0
  25. package/assets/patterns/task-flow-resume.md +5 -0
  26. package/assets/patterns/translations-content.md +107 -0
  27. package/assets/patterns/translations-key.md +1 -1
  28. package/assets/rules/angular-patterns.md +5 -0
  29. package/assets/rules/browser-verification.md +17 -12
  30. package/assets/rules/component-structure.md +6 -2
  31. package/assets/rules/doc-style.md +16 -0
  32. package/assets/rules/git-workflow.azure.md +45 -1
  33. package/assets/rules/git-workflow.github.md +52 -1
  34. package/assets/rules/git-workflow.gitlab.md +46 -1
  35. package/assets/rules/lists.md +13 -0
  36. package/assets/rules/observability.md +147 -0
  37. package/assets/rules/ownership-scope.md +5 -2
  38. package/assets/rules/ownership-session.md +124 -0
  39. package/assets/rules/permissions.md +23 -0
  40. package/assets/rules/pricing.md +4 -0
  41. package/assets/rules/reuse-first.md +9 -0
  42. package/assets/rules/seo.md +57 -9
  43. package/assets/rules/shared-code.md +6 -0
  44. package/assets/rules/spec-driven.md +9 -0
  45. package/assets/rules/styling-bem.md +34 -1
  46. package/assets/rules/task-flow.md +5 -0
  47. package/assets/rules/testing.md +46 -8
  48. package/assets/rules/translations.md +11 -5
  49. package/assets/rules/typescript-conventions.md +5 -0
  50. package/package.json +1 -1
  51. package/rt-tools-agent-kit-0.6.0.tgz +0 -0
  52. package/rt-tools-agent-kit-0.5.2.tgz +0 -0
@@ -2,7 +2,7 @@
2
2
  name: browser-verification
3
3
  kind: rule
4
4
  law: verifiability
5
- description: Правило под «Закон о проверяемости». Брать при любой проверке через браузер и при запросах curl или wget к дев-серверу. Называет порты сайта, админки и API, чему на дев-сервере верить нельзя и чем измерять вместо взгляда. Готовый код — в паттернах browser-verification-stand и browser-verification-measure.
5
+ description: Правило под «Закон о проверяемости». Брать при любой проверке через браузер и при запросах curl или wget к дев-серверу. Называет, где подняты приложения дерева, чему на дев-сервере верить нельзя и чем измерять вместо взгляда. Готовый код — в паттернах browser-verification-stand и browser-verification-measure.
6
6
  ---
7
7
 
8
8
  # Проверка работающего приложения — как это устроено здесь
@@ -16,7 +16,7 @@ description: Правило под «Закон о проверяемости».
16
16
  | В законе | Здесь |
17
17
  | --------------------------------- | ----------------------------------------------------------------------------------------------- |
18
18
  | работающее приложение | то, что поднято в этом дереве; перечень и порты — в `implementation.md` рядом |
19
- | место, где его видит пользователь | прод-сборка за настоящим `deploy/nginx.conf`, а не дев-сервер |
19
+ | место, где его видит пользователь | прод-сборка за настоящим прокси дерева, а не дев-сервер |
20
20
  | замер | `getComputedStyle`, `getBoundingClientRect`, контраст, совпадение центров, попадание во вьюпорт |
21
21
  | драйвер браузера | `claude-in-chrome` на закреплённом профиле этого дерева |
22
22
 
@@ -39,6 +39,11 @@ description: Правило под «Закон о проверяемости».
39
39
  имена, которые не опознают ничего, а выбор из него ведёт на профиль без входа.
40
40
  - **Прод-конфигурация проверяется только за настоящим прокси.** Голый сервер отдачи страниц
41
41
  про кэш, перенаправления и заголовки не знает ничего.
42
+ - **Первый заход на публичный экран метится признаком служебного посещения.** Драйвер водит
43
+ обычный браузер, и счётчик посещений не отличает проверку от гостя: `navigator.webdriver` у
44
+ него `false`, строка `User-Agent` — живого браузера. Чем метится заход, сказано в именах
45
+ дерева; признак, который живёт в хранилище браузера, дописывается один раз на профиль, а не
46
+ к каждому адресу.
42
47
 
43
48
  Вывод о вёрстке подкрепляется числом: «выглядит нормально» результатом проверки не является.
44
49
  Этого не стережёт ничто — как измерять, разобрано в паттерне `browser-verification-measure`.
@@ -50,21 +55,21 @@ description: Правило под «Закон о проверяемости».
50
55
 
51
56
  ## Паттерны
52
57
 
53
- - `browser-verification-stand` — честный стенд из прод-сборки, вход в админку, разбор порта.
58
+ - `browser-verification-stand` — честный стенд из прод-сборки, вход в закрытое приложение,
59
+ разбор порта.
54
60
  - `browser-verification-measure` — замер вместо взгляда, ловушки инструмента `computer`.
55
61
 
56
62
  ## Ловушки
57
63
 
58
64
  - **Сначала выяснить, что отвечает на порту:** `lsof -nP -iTCP:<порт> -sTCP:LISTEN` до первого
59
- запроса. На 3333 регулярно висит собранный артефакт из прошлой сессии — он отвечает 200
60
- старым кодом, а заведённой в ветке процедуры у него нет вовсе, и 404 читается как дефект
61
- регистрации. Таких процессов бывает несколько; `pkill` по `nx serve api` не попадает ни в
62
- один — убивать по PID из `lsof`, каждый.
63
- - Инкрементальная сборка протухает поштучно: разметка на 4900 бывает уже новая, а клиентский
64
- чанк — от компиляции до правки. Признак дев-сборки — имена бандла без хеша (`main.js`).
65
- Расхождение между `curl` и страницей после гидратации — повод пересобрать, а не искать
66
- дефект в коде. Отсюда же нельзя делать вывод «такого маршрута нет»: сверяться с
67
- `app.routes.ts`.
65
+ запроса. На порту приложения регулярно висит собранный артефакт из прошлой сессии — он
66
+ отвечает 200 старым кодом, а заведённого в ветке обработчика у него нет вовсе, и 404 читается
67
+ как дефект регистрации. Таких процессов бывает несколько; снятие по шаблону команды не
68
+ попадает ни в один — убивать по PID из `lsof`, каждый.
69
+ - Инкрементальная сборка протухает поштучно: разметка бывает уже новая, а клиентский чанк — от
70
+ компиляции до правки. Признак дев-сборки — имена бандла без хеша (`main.js`). Расхождение
71
+ между `curl` и страницей после гидратации — повод пересобрать, а не искать дефект в коде.
72
+ Отсюда же нельзя делать вывод «такого маршрута нет»: сверяться с объявлением маршрутов.
68
73
  - **Кэш объясняет расхождение, но не подтверждает его.** В `.angular/cache/…/vite/deps` лежат
69
74
  только пакеты из `node_modules`, кода репозитория там нет вовсе. Вывод «дефекта нет, это
70
75
  кэш» закрывает разбор, поэтому принимается только после проверки на чистой сборке — три
@@ -16,10 +16,10 @@ description: Правило под «Закон о фронтовом прило
16
16
 
17
17
  | В законе | Здесь |
18
18
  | ---------------------------------- | ---------------------------------------------------------------------------- |
19
- | компонент | `vm-<имя>` — префикс один на сайт и админку |
19
+ | компонент | `<префикс>-<имя>` — префикс один на все приложения дерева |
20
20
  | готовое, а не вычисление в шаблоне | `computed()`; там, где значение приходит из контекста шаблона, — чистый пайп |
21
21
  | якорь для проверки | атрибут `qa-dataid` в kebab-case по смыслу элемента |
22
- | корень разметки | `:host` с классом блока от `host: { class: 'vm-<имя>' }` |
22
+ | корень разметки | `:host` с классом блока от `host: { class: '<префикс>-<имя>' }` |
23
23
 
24
24
  ## Где это лежит
25
25
 
@@ -33,6 +33,10 @@ description: Правило под «Закон о фронтовом прило
33
33
  (computeFlag())`, чтения сигналов не трогает.
34
34
  - **Каждый интерактивный элемент несёт `qa-dataid`.** Это единственный якорь спек: классы BEM
35
35
  меняются вместе с вёрсткой, а поиск по роли и тексту ломается на локалях перевода.
36
+ - **Компоненту разрешён только элементный селектор.** Правило линтера требует у компонента
37
+ элемент с приставкой дерева и именем через дефис, у директивы — атрибут и имя одним словом.
38
+ Приём, который вешается на чужой тег, пишется директивой с самого начала: у компонента с
39
+ селектором-атрибутом линт краснеет уже после того, как написаны все три файла и стили.
36
40
  - **Класс блока висит на хосте, а не на обёртке внутри шаблона.** Лишняя обёртка вокруг всех
37
41
  детей — это раскладка, и ей место на `:host`.
38
42
 
@@ -56,6 +56,20 @@ description: Правило под «Закон о документации пр
56
56
  имена веток и правила линтеров: выглядят адресом, адресом не являются.
57
57
  - **Документ едет в том же коммите, что и правка, которую он описывает.** Обход — строка
58
58
  `Docs-skip: <причина>` в теле коммита; пустая причина не принимается.
59
+ - **Документ не длиннее предела длины.** Текст, который не влезает на экран целиком, дописывают
60
+ в конец, не перечитав начала, — так в одном документе и оказываются два ответа на один вопрос.
61
+ Предел тот же, что у кода, и считается так же — все строки; выросший спек делится на
62
+ поддомены, а не переносит границу. Описание прошлого из счёта выведено: архив по устройству
63
+ перечисляет то, чего в дереве уже нет, а папка задачи умирает со слиянием.
64
+ - **Файл, уезжающий в описание прошлого, называет в шапке свой прежний адрес.** Записи архива
65
+ ссылались на него, пока он был живым, и после переезда эти ссылки ведут в пустоту: проверка
66
+ путей архив не читает вовсе, поэтому промах не краснеет никогда. Найти переехавшее нечем —
67
+ имя записи архива с прежним адресом не совпадает, и поиск по нему её не показывает. Одна
68
+ строка в шапке дешевле правки всех ссылающихся записей и прошлого не трогает.
69
+ - **Текст, называющий состояние машины, устаревает без единой правки в дереве.** Ловушка о том,
70
+ что на машине установлено, верна в день, когда её пишут, и становится неправдой сама собой —
71
+ ни одна сверка этого не видит: они читают дерево, а состарилась машина. Утверждение о машине
72
+ пишется способом её спросить: команда и то, с чем сверять ответ, вместо снимка ответа.
59
73
 
60
74
  ## Чего из закона здесь нет
61
75
 
@@ -74,6 +88,8 @@ description: Правило под «Закон о документации пр
74
88
 
75
89
  - `doc-style-write` — как формулировать: примеры «так» и «не так», правила для комментариев.
76
90
  - `doc-style-sweep` — разбор документа, накопившего список работ, на действующее и закрытое.
91
+ - `doc-style-trace` — обратный проход: закрытые задачи против текстов, поиск того, чего не
92
+ написали.
77
93
 
78
94
  ## Скилы дерева
79
95
 
@@ -2,7 +2,7 @@
2
2
  name: git-workflow
3
3
  kind: rule
4
4
  law: delivery
5
- description: Правило под «Закон о поставке» для дерева в Azure DevOps. Брать на заведение задачи, ветки, коммит, пуш, создание PR, слияние, а также на правку схемы хранилища, её миграций и вызовы миграций. Называет рабочий элемент как начало работы, его состояние как ход работы, соответствие задачи и ветки один к одному, имя ветки, формат коммита, учётную запись машинной работы, обязательный состав PR, гарды поставки и сверку очереди работ. Готовый код — в паттернах git-workflow-commit, git-workflow-merge, git-workflow-migration и git-workflow-restart.
5
+ description: Правило под «Закон о поставке» для дерева в Azure DevOps. Брать на заведение задачи, ветки, коммит, пуш, создание PR, слияние, а также на правку схемы хранилища, её миграций и вызовы миграций. Называет рабочий элемент как начало работы, его состояние как ход работы, соответствие задачи и ветки один к одному, имя ветки, формат коммита, учётную запись машинной работы, обязательный состав PR, гарды поставки и сверку очереди работ. Готовый код — в паттернах git-workflow-commit, git-workflow-merge, git-workflow-migration, git-workflow-restart, git-workflow-docker и git-workflow-secrets.
6
6
  ---
7
7
 
8
8
  # Поставка — как это устроено здесь
@@ -63,6 +63,11 @@ description: Правило под «Закон о поставке» для д
63
63
  - **Задачи, чинящиеся одной правкой, сливаются до слияния ветки.** Вторая закрывается как
64
64
  дубликат, а недостающее из неё дописывается в первую. После слияния слить уже нельзя: ветка
65
65
  въехала, и откатывается она целиком.
66
+ - **Работа, которую одним заходом не закрыть, помечена в двух местах, и они сверяются.** Метка
67
+ на доске и строка о заходах с передачей в линии работ говорят одно и то же двум читателям:
68
+ исполнитель открывает карточку раньше, чем линию, а планирует по линии. Одна пометка без
69
+ другой лжёт молча, поэтому сверка очереди судит пару в обе стороны. Помечается только то, что
70
+ законно не делится: пометка объёма правом делить не становится.
66
71
  - **Слияние в главную ветку выкатывает прод.** Фильтры путей конвейера покрывают документы
67
72
  отдельно, поэтому переменные окружения, секреты и записи имён ставятся до слияния, а не
68
73
  после.
@@ -72,6 +77,24 @@ description: Правило под «Закон о поставке» для д
72
77
  умолчаниями, которые он разрешает. Умолчание образа задаётся в самом образе.
73
78
  - **Образы выкатываются по sha коммита, а не по метке «последний».** Метка в реестре отстаёт
74
79
  от главной ветки, и прод молча возвращается к прежней версии, продолжая отвечать.
80
+ - **Выкатка убирает за собой старые образы, оставляя три последних sha.** Помеченный sha образ
81
+ висячим не бывает никогда, и чистка висячего его не касается: за полгода они съедают диск
82
+ сервера целиком. Три sha — это глубина отката, и меньше брать нельзя: поломка, замеченная
83
+ через две выкатки, откатывается уже некуда.
84
+ - **Описание прода правится вместе с составом прода.** Устройство, путь запроса, гейты и
85
+ бэкапы описаны текстами вне слоёв правил, и ни линтер, ни сборка их не читают: расхождение
86
+ копится молча, а читают эти тексты как действующие. Пару стережёт гард документов.
87
+ - **Правка конвейера прогоняется до слияния ручным запуском.** Конвейер запускается на любой
88
+ ветке, а задание выкатки прибито условием к главной: прогон ради проверки доходит до сборок и
89
+ там кончается. Прогон команд задания на своей машине его не покрывает: он проверяет команды,
90
+ а не файл конвейера, — верность самого файла читается только по списку прогонов после пуша.
91
+ - **Отчёт проверяется до слияния тем же конвейером, что и главная ветка.** Проверки и сборки
92
+ образов идут на конвейере проверки PR, выкатка — нет: её держит условие по главной ветке у
93
+ своего задания, а образ отчёта в реестр не уезжает.
94
+ - **Расхождение прода с главной веткой видно сверкой очереди работ.** Рабочий элемент уходит из
95
+ очереди слиянием, но слияние — ещё не прод: отказавшая выкатка не трогает ни элемент, ни его
96
+ состояние, и заметить её неоткуда. Сверка спрашивает последний прогон главной ветки и судит
97
+ только завершённый: идущий ещё может кончиться выкаткой.
75
98
  - **Цепочка миграций прогоняется с пустого хранилища до слияния.** Порядок применения
76
99
  лексикографический по имени каталога, а метку времени ставит момент создания: миграция из
77
100
  ветки, начатой раньше, встаёт перед той, от которой зависит.
@@ -81,6 +104,10 @@ description: Правило под «Закон о поставке» для д
81
104
  заголовок читается списком, а свободный текст — только целиком.
82
105
  - **Перед пушем прогоняются все линтеры, а не один.** Линтер кода обычно не читает файлы
83
106
  стилей вовсе, и правила оформления без второго прогона не проверяет ничто.
107
+ - **Сборка входит в набор наравне с линтом и юнитами.** Линтер типов не читает, а юниты читают
108
+ только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
109
+ образа, то есть до слияния. Четыре слияния подряд так и уехали в главную ветку, ломая
110
+ выкатку.
84
111
  - **Рабочий элемент привязывается к PR при создании, а не после.** `az repos pr create`
85
112
  принимает `--work-items`; привязка второй командой обходится молча, когда у токена нет права
86
113
  править чужой элемент, и PR остаётся ни с чем не связанным.
@@ -124,6 +151,8 @@ description: Правило под «Закон о поставке» для д
124
151
  - `git-workflow-merge` — главная ветка влита в ветку задачи, конфликт разобран.
125
152
  - `git-workflow-migration` — правка схемы хранилища и её миграций.
126
153
  - `git-workflow-restart` — ручной перезапуск прода.
154
+ - `git-workflow-docker` — образы на своей машине: демон, реестр, сборка под платформу сервера.
155
+ - `git-workflow-secrets` — ключи внешних служб: где лежат, как заводятся, что говорит их состояние.
127
156
 
128
157
  ## Ловушки
129
158
 
@@ -148,6 +177,21 @@ description: Правило под «Закон о поставке» для д
148
177
  записи, на следующий вызов это не переносится: PR открывают токеном учётной записи машинной
149
178
  работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
150
179
  смена записи ради пуша утекла в публикацию — отчёт вышел от владельца.
180
+ - **Невалидный файл конвейера виден прогоном нулевой длительности сразу после пуша.** Прогон
181
+ заводится и кончается на разборе файла, не начав ни одного задания: в списке он стоит
182
+ отказом, а внутри нет ни задания, ни лога — читается только длительность. Поэтому список
183
+ прогонов ветки смотрится тем же движением, что и пуш: `az pipelines runs list` по своей
184
+ ветке.
185
+ - **`online` у агента на своей машине означает запущенный процесс, а не работающий конвейер.**
186
+ Две стороны сходятся отдельно: требования заданий и возможности самого агента в его пуле.
187
+ Пока пересечения нет, агент стоит `online` и не берёт ничего, а задания ждут размещённого
188
+ пула — по состоянию это выглядит настроенным. Владельцу называют выполненное задание с его
189
+ номером, а не строку состояния.
190
+ - **Вход в реестр образов из агента, запущенного службой, отказывает молча.** Служба идёт без
191
+ сеанса пользователя, а клиент реестра уходит в системный помощник хранения ключей и получает
192
+ отказ во взаимодействии — задание падает до сборки. Свой каталог настроек с пустым помощником
193
+ не спасает: клиент переписывает пустое значение обратно сам. Готовые команды — паттерн
194
+ `git-workflow-docker`.
151
195
  - **Новое рабочее дерево получает только то, что лежит в индексе.** `git worktree add`
152
196
  разворачивает коммит, а настройки, ключи, локальные разрешения и зависимости в коммит не
153
197
  входят: свежее дерево выглядит готовым и упирается в нехватку не сразу, а на первом гарде,
@@ -2,7 +2,7 @@
2
2
  name: git-workflow
3
3
  kind: rule
4
4
  law: delivery
5
- description: Правило под «Закон о поставке» для дерева на GitHub. Брать на заведение задачи, ветки, коммит, пуш, создание PR, мерж, а также на правку схемы хранилища, её миграций и вызовы миграций. Называет задачу на борде как начало работы, колонку задачи как ход работы, соответствие задачи и ветки один к одному, имя ветки, формат коммита, учётную запись машинной работы, обязательный состав PR, гарды поставки и сверку очереди работ. Готовый код — в паттернах git-workflow-commit, git-workflow-merge, git-workflow-migration и git-workflow-restart.
5
+ description: Правило под «Закон о поставке» для дерева на GitHub. Брать на заведение задачи, ветки, коммит, пуш, создание PR, мерж, а также на правку схемы хранилища, её миграций и вызовы миграций. Называет задачу на борде как начало работы, колонку задачи как ход работы, соответствие задачи и ветки один к одному, имя ветки, формат коммита, учётную запись машинной работы, обязательный состав PR, гарды поставки и сверку очереди работ. Готовый код — в паттернах git-workflow-commit, git-workflow-merge, git-workflow-migration, git-workflow-restart, git-workflow-docker и git-workflow-secrets.
6
6
  ---
7
7
 
8
8
  # Поставка — как это устроено здесь
@@ -73,6 +73,11 @@ description: Правило под «Закон о поставке» для д
73
73
  - **Задачи, чинящиеся одной правкой, сливаются до мержа.** Вторая стирается вместе с номером,
74
74
  а недостающее из неё дописывается в первую. После мержа слить уже нельзя: ветка въехала, и
75
75
  откатывается она целиком.
76
+ - **Работа, которую одним заходом не закрыть, помечена в двух местах, и они сверяются.** Метка
77
+ на борде и строка о заходах с передачей в линии работ говорят одно и то же двум читателям:
78
+ исполнитель открывает карточку раньше, чем линию, а планирует по линии. Одна пометка без
79
+ другой лжёт молча, поэтому сверка очереди судит пару в обе стороны. Помечается только то, что
80
+ законно не делится: пометка объёма правом делить не становится.
76
81
  - **Мерж в главную ветку выкатывает прод.** Исключения по путям покрывают только документы,
77
82
  поэтому переменные окружения, секреты и записи имён ставятся до мержа, а не после.
78
83
  - **Признак режима объявлен в образе, а не только в составе прода.** Значение, заданное
@@ -81,6 +86,26 @@ description: Правило под «Закон о поставке» для д
81
86
  умолчаниями, которые он разрешает. Умолчание образа задаётся в самом образе.
82
87
  - **Образы выкатываются по sha коммита, а не по метке «последний».** Метка в реестре отстаёт
83
88
  от главной ветки, и прод молча возвращается к прежней версии, продолжая отвечать.
89
+ - **Выкатка убирает за собой старые образы, оставляя три последних sha.** Помеченный sha образ
90
+ висячим не бывает никогда, и чистка висячего его не касается: за полгода они съедают диск
91
+ сервера целиком. Три sha — это глубина отката, и меньше брать нельзя: поломка, замеченная
92
+ через две выкатки, откатывается уже некуда.
93
+ - **Описание прода правится вместе с составом прода.** Устройство, путь запроса, гейты и
94
+ бэкапы описаны текстами вне слоёв правил, и ни линтер, ни сборка их не читают: расхождение
95
+ копится молча, а читают эти тексты как действующие. Пару стережёт гард документов.
96
+ - **Правка конвейера прогоняется до мержа ручным запуском.** `workflow_dispatch` у выкатки
97
+ запускает её на любой ветке, а сама выкатка прибита условием к главной: прогон ради проверки
98
+ доходит до сборок и там кончается. Триггер регистрируется по главной ветке, поэтому правку,
99
+ которая его заводит или переносит, ручной запуск не покрывает. Прогон команд задания на своей
100
+ машине не покрывает её тоже: он проверяет команды, а не файл конвейера, — верность самого
101
+ файла читается только по списку прогонов после пуша.
102
+ - **Отчёт проверяется до мержа тем же конвейером, что и главная ветка.** Проверки и сборки
103
+ образов идут на событии `pull_request`, выкатка — нет: её держит условие по главной ветке у
104
+ своего задания, а образ отчёта в реестр не уезжает.
105
+ - **Расхождение прода с главной веткой видно сверкой очереди работ.** Задача уходит из очереди
106
+ мержем, но мерж — ещё не прод: отказавшая выкатка не трогает ни задачу, ни её колонку, и
107
+ заметить её неоткуда. Сверка спрашивает последний прогон главной ветки и судит только
108
+ завершённый: идущий ещё может кончиться выкаткой.
84
109
  - **Цепочка миграций прогоняется с пустого хранилища до мержа.** Порядок применения
85
110
  лексикографический по имени каталога, а метку времени ставит момент создания: миграция из
86
111
  ветки, начатой раньше, встаёт перед той, от которой зависит.
@@ -90,6 +115,9 @@ description: Правило под «Закон о поставке» для д
90
115
  заголовок читается списком, а свободный текст — только целиком.
91
116
  - **Перед пушем прогоняются все линтеры, а не один.** Линтер кода обычно не читает файлы
92
117
  стилей вовсе, и правила оформления без второго прогона не проверяет ничто.
118
+ - **Сборка входит в набор наравне с линтом и юнитами.** Линтер типов не читает, а юниты читают
119
+ только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
120
+ образа, то есть до мержа. Четыре мержа подряд так и уехали в главную ветку, ломая выкатку.
93
121
  - **Автор PR не может быть его ревьювером.** Запрос разбора на самого себя GitHub принимает и
94
122
  молча не создаёт — разбор при этом выглядит запрошенным.
95
123
  - **Метки, исполнитель и ревьювер PR ставятся вызовами `gh api`, а не `gh pr edit`.** На
@@ -131,6 +159,8 @@ description: Правило под «Закон о поставке» для д
131
159
  - `git-workflow-merge` — главная ветка влита в ветку задачи, конфликт разобран.
132
160
  - `git-workflow-migration` — правка схемы хранилища и её миграций.
133
161
  - `git-workflow-restart` — ручной перезапуск прода.
162
+ - `git-workflow-docker` — образы на своей машине: демон, реестр, сборка под платформу сервера.
163
+ - `git-workflow-secrets` — ключи внешних служб: где лежат, как заводятся, что говорит их состояние.
134
164
 
135
165
  ## Ловушки
136
166
 
@@ -154,6 +184,27 @@ description: Правило под «Закон о поставке» для д
154
184
  записи, на следующий вызов это не переносится: PR открывают токеном учётной записи машинной
155
185
  работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
156
186
  смена записи ради пуша утекла в публикацию — отчёт вышел от владельца.
187
+ - **Невалидный файл конвейера виден прогоном нулевой длительности сразу после пуша.** GitHub
188
+ заводит такой прогон и на ветке, на которую ни один триггер не подписан: в списке он стоит
189
+ отказом, а внутри у него нет ни задания, ни лога — читается только длительность. Поэтому
190
+ список прогонов ветки смотрится тем же движением, что и пуш — `gh run list --branch <ветка>`.
191
+ Один такой отказ простоял в списке до мержа, и на него никто не посмотрел: выкатка после
192
+ мержа отказала ровно тем же.
193
+ - **Контекст `runner` в `env` задания отбивает весь файл конвейера.** Там доступны только
194
+ `github`, `needs`, `strategy`, `matrix`, `vars`, `secrets` и `inputs`; `runner` появляется на
195
+ уровне шага, где то же значение приходит переменной окружения. Такой файл не принимается
196
+ вовсе: прогон кончается за ноль секунд, не начав ни одного задания. Разбор YAML этого не
197
+ ловит — синтаксис верный, а доступность контекстов синтаксисом не является.
198
+ - **`online` у раннера на своей машине означает запущенный процесс, а не работающий
199
+ конвейер.** Две стороны сходятся отдельно: `runs-on` у заданий и метки самого раннера. Пока
200
+ пересечения нет, раннер стоит `online` и не берёт ничего, а задания уходят в облако — по
201
+ состоянию это выглядит настроенным. Владельцу называют выполненное задание с его номером, а
202
+ не строку состояния.
203
+ - **Вход в реестр образов из раннера, запущенного службой, отказывает молча.** Служба идёт без
204
+ сеанса пользователя, а клиент реестра уходит в системный помощник хранения ключей и получает
205
+ отказ во взаимодействии — задание падает до сборки. Свой каталог настроек с пустым помощником
206
+ не спасает: клиент переписывает пустое значение обратно сам. Готовые команды — паттерн
207
+ `git-workflow-docker`.
157
208
  - **Новое рабочее дерево получает только то, что лежит в индексе.** `git worktree add`
158
209
  разворачивает коммит, а настройки, ключи, локальные разрешения и зависимости в коммит не
159
210
  входят: свежее дерево выглядит готовым и упирается в нехватку не сразу, а на первом гарде,
@@ -2,7 +2,7 @@
2
2
  name: git-workflow
3
3
  kind: rule
4
4
  law: delivery
5
- description: Правило под «Закон о поставке» для дерева на GitLab. Брать на заведение задачи, ветки, коммит, пуш, создание MR, слияние, а также на правку схемы хранилища, её миграций и вызовы миграций. Называет задачу на борде как начало работы, колонку задачи как ход работы, соответствие задачи и ветки один к одному, имя ветки, формат коммита, учётную запись машинной работы, обязательный состав MR, гарды поставки и сверку очереди работ. Готовый код — в паттернах git-workflow-commit, git-workflow-merge, git-workflow-migration и git-workflow-restart.
5
+ description: Правило под «Закон о поставке» для дерева на GitLab. Брать на заведение задачи, ветки, коммит, пуш, создание MR, слияние, а также на правку схемы хранилища, её миграций и вызовы миграций. Называет задачу на борде как начало работы, колонку задачи как ход работы, соответствие задачи и ветки один к одному, имя ветки, формат коммита, учётную запись машинной работы, обязательный состав MR, гарды поставки и сверку очереди работ. Готовый код — в паттернах git-workflow-commit, git-workflow-merge, git-workflow-migration, git-workflow-restart, git-workflow-docker и git-workflow-secrets.
6
6
  ---
7
7
 
8
8
  # Поставка — как это устроено здесь
@@ -62,6 +62,11 @@ description: Правило под «Закон о поставке» для д
62
62
  - **Задачи, чинящиеся одной правкой, сливаются до слияния ветки.** Вторая стирается вместе с
63
63
  номером, а недостающее из неё дописывается в первую. После слияния слить уже нельзя: ветка
64
64
  въехала, и откатывается она целиком.
65
+ - **Работа, которую одним заходом не закрыть, помечена в двух местах, и они сверяются.** Метка
66
+ на доске и строка о заходах с передачей в линии работ говорят одно и то же двум читателям:
67
+ исполнитель открывает карточку раньше, чем линию, а планирует по линии. Одна пометка без
68
+ другой лжёт молча, поэтому сверка очереди судит пару в обе стороны. Помечается только то, что
69
+ законно не делится: пометка объёма правом делить не становится.
65
70
  - **Слияние в главную ветку выкатывает прод.** Правила `only`/`rules` конвейера покрывают
66
71
  документы отдельно, поэтому переменные окружения, секреты и записи имён ставятся до слияния,
67
72
  а не после.
@@ -71,6 +76,25 @@ description: Правило под «Закон о поставке» для д
71
76
  умолчаниями, которые он разрешает. Умолчание образа задаётся в самом образе.
72
77
  - **Образы выкатываются по sha коммита, а не по метке «последний».** Метка в реестре отстаёт
73
78
  от главной ветки, и прод молча возвращается к прежней версии, продолжая отвечать.
79
+ - **Выкатка убирает за собой старые образы, оставляя три последних sha.** Помеченный sha образ
80
+ висячим не бывает никогда, и чистка висячего его не касается: за полгода они съедают диск
81
+ сервера целиком. Три sha — это глубина отката, и меньше брать нельзя: поломка, замеченная
82
+ через две выкатки, откатывается уже некуда.
83
+ - **Описание прода правится вместе с составом прода.** Устройство, путь запроса, гейты и
84
+ бэкапы описаны текстами вне слоёв правил, и ни линтер, ни сборка их не читают: расхождение
85
+ копится молча, а читают эти тексты как действующие. Пару стережёт гард документов.
86
+ - **Правка конвейера прогоняется до слияния ручным запуском.** Конвейер запускается на любой
87
+ ветке, а задание выкатки прибито правилом к главной: прогон ради проверки доходит до сборок и
88
+ там кончается. Прогон команд задания на своей машине его не покрывает: он проверяет команды,
89
+ а не файл конвейера, — верность самого файла читается только по списку конвейеров после
90
+ пуша, и синтаксис отдельно судит проверка `.gitlab-ci.yml` в проекте.
91
+ - **Отчёт проверяется до слияния тем же конвейером, что и главная ветка.** Проверки и сборки
92
+ образов идут на конвейере запроса слияния, выкатка — нет: её держит правило по главной ветке
93
+ у своего задания, а образ отчёта в реестр не уезжает.
94
+ - **Расхождение прода с главной веткой видно сверкой очереди работ.** Задача уходит из очереди
95
+ слиянием, но слияние — ещё не прод: отказавшая выкатка не трогает ни задачу, ни её список, и
96
+ заметить её неоткуда. Сверка спрашивает последний конвейер главной ветки и судит только
97
+ завершённый: идущий ещё может кончиться выкаткой.
74
98
  - **Цепочка миграций прогоняется с пустого хранилища до слияния.** Порядок применения
75
99
  лексикографический по имени каталога, а метку времени ставит момент создания: миграция из
76
100
  ветки, начатой раньше, встаёт перед той, от которой зависит.
@@ -80,6 +104,10 @@ description: Правило под «Закон о поставке» для д
80
104
  заголовок читается списком, а свободный текст — только целиком.
81
105
  - **Перед пушем прогоняются все линтеры, а не один.** Линтер кода обычно не читает файлы
82
106
  стилей вовсе, и правила оформления без второго прогона не проверяет ничто.
107
+ - **Сборка входит в набор наравне с линтом и юнитами.** Линтер типов не читает, а юниты читают
108
+ только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
109
+ образа, то есть до слияния. Четыре слияния подряд так и уехали в главную ветку, ломая
110
+ выкатку.
83
111
  - **Слияние по кнопке «Merge when pipeline succeeds» не заменяет проверок до пуша.** Конвейер
84
112
  видит только то, что уже отправлено, а отправленная красная ветка занимает очередь работ и
85
113
  выглядит готовой к разбору.
@@ -121,6 +149,8 @@ description: Правило под «Закон о поставке» для д
121
149
  - `git-workflow-merge` — главная ветка влита в ветку задачи, конфликт разобран.
122
150
  - `git-workflow-migration` — правка схемы хранилища и её миграций.
123
151
  - `git-workflow-restart` — ручной перезапуск прода.
152
+ - `git-workflow-docker` — образы на своей машине: демон, реестр, сборка под платформу сервера.
153
+ - `git-workflow-secrets` — ключи внешних служб: где лежат, как заводятся, что говорит их состояние.
124
154
 
125
155
  ## Ловушки
126
156
 
@@ -144,6 +174,21 @@ description: Правило под «Закон о поставке» для д
144
174
  записи, на следующий вызов это не переносится: MR открывают токеном учётной записи машинной
145
175
  работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
146
176
  смена записи ради пуша утекла в публикацию — отчёт вышел от владельца.
177
+ - **Невалидный файл конвейера виден отказом сразу после пуша, а не упавшим заданием.** Конвейер
178
+ на такой файл не заводится вовсе: в списке стоит запись об ошибке разбора, а внутри нет ни
179
+ задания, ни лога. Поэтому список конвейеров ветки смотрится тем же движением, что и пуш —
180
+ `glab ci list --branch <ветка>`, — а сам файл до пуша судит проверка `.gitlab-ci.yml` в
181
+ проекте.
182
+ - **`online` у раннера на своей машине означает запущенный процесс, а не работающий
183
+ конвейер.** Две стороны сходятся отдельно: `tags` у заданий и теги самого раннера. Пока
184
+ пересечения нет, раннер стоит `online` и не берёт ничего, а задания ждут общего раннера — по
185
+ состоянию это выглядит настроенным. Владельцу называют выполненное задание с его номером, а
186
+ не строку состояния.
187
+ - **Вход в реестр образов из раннера, запущенного службой, отказывает молча.** Служба идёт без
188
+ сеанса пользователя, а клиент реестра уходит в системный помощник хранения ключей и получает
189
+ отказ во взаимодействии — задание падает до сборки. Свой каталог настроек с пустым помощником
190
+ не спасает: клиент переписывает пустое значение обратно сам. Готовые команды — паттерн
191
+ `git-workflow-docker`.
147
192
  - **Новое рабочее дерево получает только то, что лежит в индексе.** `git worktree add`
148
193
  разворачивает коммит, а настройки, ключи, локальные разрешения и зависимости в коммит не
149
194
  входят: свежее дерево выглядит готовым и упирается в нехватку не сразу, а на первом гарде,
@@ -30,11 +30,24 @@ description: Правило под «Закон о списке записей»
30
30
 
31
31
  ## Как закон применяется здесь
32
32
 
33
+ - **Страница собирается общим компонентом страницы списка, а не своей разметкой.** Заголовок,
34
+ панель действий, зона прокрутки и переключатель страниц одинаковы у всех списков, и
35
+ переписанные заново они расходятся молча.
36
+ - **Механика экрана берётся из общей основы списочного экрана, а не пишется заново.** Экран
37
+ домена объявляет стор, ключ таблицы, поля сортировки и столбцы; выборка из адреса и в адрес,
38
+ страница, её размер, сортировка, тост отказа и переходы в панель уже там.
39
+ - **Таблицу экран объявляет сам и кладёт внутрь шаблона.** Обернуть её нельзя: столбцы она
40
+ собирает собственным запросом по содержимому, и через посредника они до неё не доходят.
33
41
  - **Список собирается `<префикс>-table`, а не своей разметкой.** Скелетоны, пустое состояние,
34
42
  карточки на узком экране и настройка столбцов — входы таблицы; свой
35
43
  `@if (rows().length === 0)` означает, что экран собран мимо неё.
36
44
  - **Строки объявляются на `rowsTable.displayedColumns()`, а не на своём списке.** Столбец с
37
45
  меню таблица добавляет сама.
46
+ - **Заголовок сортируемой колонки называет поле сервера, а не ключ колонки.** Колонка и поле
47
+ совпадают не всегда, и пока в разметке стоит ключ колонки, экран держит две карты перевода в
48
+ обе стороны.
49
+ - **Сортируема та колонка, у чьей ячейки шапки стоит заголовок сортировки.** Отдельного
50
+ признака рядом со списком столбцов нет, и расходиться нечему.
38
51
  - **Клик по строке открывает запись, а меню — для действий над ней.** Вид нажимаемой строки
39
52
  даёт `clickable`, активацию мышью и с клавиатуры — `vmTableRow`; клик по кнопке внутри строки
40
53
  активацией не считается.