@rt-tools/agent-kit 0.14.0 → 0.16.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 (90) hide show
  1. package/README.md +17 -0
  2. package/assets/checks/archive-age.mjs +107 -0
  3. package/assets/checks/archive-prune.mjs +46 -0
  4. package/assets/checks/check-archive-age.mjs +42 -0
  5. package/assets/checks/check-board.github.mjs +16 -0
  6. package/assets/checks/check-descriptions.mjs +123 -0
  7. package/assets/checks/check-dupes.mjs +31 -3
  8. package/assets/checks/check-file-size.mjs +47 -2
  9. package/assets/checks/check-turn-map.mjs +20 -3
  10. package/assets/checks/lib-common.mjs +12 -1
  11. package/assets/checks/lib-domains.mjs +1 -1
  12. package/assets/checks/rt-kit-checks.config.mjs +24 -1
  13. package/assets/checks/spec-anchors.mjs +18 -3
  14. package/assets/checks/spec-common.mjs +5 -1
  15. package/assets/defaults/project.sh +22 -17
  16. package/assets/defaults/turn-map.md +15 -19
  17. package/assets/docs/GLOSSARY.md +52 -58
  18. package/assets/hooks/rule-article.sh +12 -0
  19. package/assets/hooks/skill-gate.sh +5 -4
  20. package/assets/hooks/task-flow-guard.sh +20 -0
  21. package/assets/hooks/turn-exit-guard.sh +229 -4
  22. package/assets/laws/delivery.md +92 -104
  23. package/assets/laws/frontend-application.md +4 -0
  24. package/assets/laws/project-documentation.md +64 -68
  25. package/assets/laws/verifiability.md +32 -33
  26. package/assets/laws/work-conduct.md +167 -157
  27. package/assets/patterns/doc-style-sweep.md +1 -1
  28. package/assets/patterns/doc-style-trace.md +1 -1
  29. package/assets/patterns/git-workflow-commit.azure.md +1 -1
  30. package/assets/patterns/git-workflow-commit.github.md +7 -1
  31. package/assets/patterns/git-workflow-commit.gitlab.md +1 -1
  32. package/assets/patterns/git-workflow-docker.md +1 -1
  33. package/assets/patterns/git-workflow-merge.md +14 -3
  34. package/assets/patterns/git-workflow-pr.azure.md +1 -1
  35. package/assets/patterns/git-workflow-pr.github.md +1 -1
  36. package/assets/patterns/git-workflow-pr.gitlab.md +1 -1
  37. package/assets/patterns/git-workflow-restart.md +1 -1
  38. package/assets/patterns/git-workflow-secrets.md +1 -1
  39. package/assets/patterns/git-workflow-stack.md +93 -0
  40. package/assets/patterns/seo-page.md +1 -1
  41. package/assets/patterns/spec-driven-rule.md +55 -0
  42. package/assets/patterns/status-report-table.github.md +88 -0
  43. package/assets/patterns/task-flow-archive.md +3 -4
  44. package/assets/patterns/task-flow-close.md +6 -1
  45. package/assets/patterns/task-flow-start.md +17 -5
  46. package/assets/patterns/ts-procedure.md +1 -1
  47. package/assets/pitfalls/doc-style.md +5 -0
  48. package/assets/pitfalls/git-workflow.github.md +47 -0
  49. package/assets/pitfalls/task-flow.md +28 -0
  50. package/assets/pitfalls/testing.md +14 -0
  51. package/assets/pitfalls/turn-conduct.md +33 -0
  52. package/assets/rules/angular-patterns.md +1 -1
  53. package/assets/rules/api-layer.md +3 -3
  54. package/assets/rules/browser-verification.md +15 -1
  55. package/assets/rules/dependencies.md +1 -1
  56. package/assets/rules/deploy-flow.azure.md +1 -1
  57. package/assets/rules/deploy-flow.github.md +1 -1
  58. package/assets/rules/deploy-flow.gitlab.md +1 -1
  59. package/assets/rules/doc-style.md +18 -0
  60. package/assets/rules/entity-conventions.needs-admin.md +1 -1
  61. package/assets/rules/entity-models.md +1 -1
  62. package/assets/rules/git-workflow.azure.md +1 -1
  63. package/assets/rules/git-workflow.github.md +154 -181
  64. package/assets/rules/git-workflow.gitlab.md +1 -1
  65. package/assets/rules/lib-layers.md +1 -1
  66. package/assets/rules/observability.needs-app.md +1 -1
  67. package/assets/rules/platform-access.md +1 -1
  68. package/assets/rules/reuse-first.md +1 -1
  69. package/assets/rules/seo.md +4 -3
  70. package/assets/rules/shared-code.md +1 -1
  71. package/assets/rules/spec-driven.md +68 -1
  72. package/assets/rules/status-report.md +97 -0
  73. package/assets/rules/styling-bem.md +12 -0
  74. package/assets/rules/task-flow.md +102 -100
  75. package/assets/rules/testing.md +67 -66
  76. package/assets/rules/turn-conduct.md +146 -105
  77. package/assets/rules/turn-entry.md +7 -1
  78. package/assets/rules/typescript-conventions.md +1 -1
  79. package/assets/skills/agent-kit-extend.md +1 -1
  80. package/assets/skills/agent-kit.md +18 -1
  81. package/bin/agent-kit.d.ts.map +1 -1
  82. package/bin/agent-kit.js +25 -0
  83. package/bin/agent-kit.js.map +1 -1
  84. package/lib/cost.d.ts +44 -0
  85. package/lib/cost.d.ts.map +1 -0
  86. package/lib/cost.js +181 -0
  87. package/lib/cost.js.map +1 -0
  88. package/package.json +1 -1
  89. package/rt-tools-agent-kit-0.16.0.tgz +0 -0
  90. package/rt-tools-agent-kit-0.14.0.tgz +0 -0
@@ -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-pr, git-workflow-merge. Выкатка, образы и миграции — правило deploy-flow.
5
+ description: Правило под «Закон о поставке» для дерева на GitHub. Брать на заведение задачи, ветки, коммит, пуш, открытие PR и мерж. Называет соответствие задачи и ветки один к одному, имена, машинную учётную запись и гарды поставки. Паттерны: git-workflow-commit, -pr, -merge. Выкатка — правило deploy-flow.
6
6
  ---
7
7
 
8
8
  # Поставка — как это устроено здесь
@@ -62,206 +62,179 @@ flowchart TD
62
62
 
63
63
  ## Как закон применяется здесь
64
64
 
65
- - **Коммит в главную ветку отбивается гардом.** Гард ищет вызов коммита в любом месте команды
66
- и смотрит текущую ветку на момент запуска, поэтому составная «создать ветку и сразу
67
- коммитить» отклоняется целиком: ветки в момент разбора ещё нет.
68
- - **Ветка без номера задачи PR не открывает.** Гард поставки отбивает `gh pr create` с такой
69
- ветки: локально она законна, но правка из неё это выкатка, за которой в очереди работ
70
- ничего не стоит. Заводится задача, и работа переносится в ветку с её номером.
71
- - **Главная ветка влита в ветку задачи до открытия PR.** Гард поставки отбивает открытие, пока
72
- вершина главной ветки не стала предком текущей, и называет расхождение числом коммитов. PR с
73
- разошедшейся ветки показывает ревьюверу свою правку вперемешку с чужой, а всё, что автор
74
- проверил до публикации, он проверил от основания, которого в главной ветке уже нет.
75
- - **Несошедшиеся условия поставки называются одним отказом, а не по одному.** Гард копит их все
76
- и печатает разом. Отбитый по первому промаху исполнитель правит основание, повторяет вызов,
77
- упирается в заголовок, правит заголовок, упирается в задачу — и каждый круг стоит ещё одного
78
- вызова, хотя всё несошедшееся было известно уже на первом.
65
+ - **Коммит в главную ветку отбивается гардом.** Гард ищет вызов коммита в любом месте команды и
66
+ смотрит текущую ветку на момент запуска: составная «создать ветку и сразу коммитить»
67
+ отклоняется целиком ветки в момент разбора ещё нет.
68
+ - **Ветка без номера задачи PR не открывает.** Локально она законна, но правка из неё — выкатка,
69
+ за которой в очереди работ ничего не стоит. Заводится задача, и работа переносится в ветку с
70
+ её номером.
71
+ - **Главная ветка влита в ветку задачи до открытия PR.** Гард отбивает открытие, пока вершина
72
+ главной не стала предком текущей, и называет расхождение числом коммитов: иначе ревьювер видит
73
+ свою правку вперемешку с чужой, а проверено всё было от основания, которого уже нет.
74
+ - **Несошедшиеся условия поставки называются одним отказом, а не по одному.** Гард копит их все и
75
+ печатает разом: круг «правь повтори упрись в следующее» стоит вызова за вызовом, хотя всё
76
+ несошедшееся известно на первом.
79
77
  - **Условие, известное в начале работы, спрашивается в начале.** Заведение ветки отбивает
80
- основание, в котором нет вершины главной ветки, и рабочую копию, подписывающую коммиты не той
81
- почтой, что объявило дерево. На пуше и на открытии PR те же проверки остаются вторым рубежом,
82
- но там они стоят дороже: основание чинится вливанием с разбором конфликта, подпись —
83
- переписыванием всей ветки.
84
- - **Судится то основание, которое названо командой, а не вершина рабочей копии.** Ветку заводят
85
- и от `origin/main` прямо этой командой основание как раз и берут свежим, — и гард, читающий
86
- только текущую вершину, отбивал бы её наравне с веткой от вчерашнего дерева. Основание, о
87
- котором дерево ничего не знает, не судится вовсе.
88
- - **Ветка без номера задачи условий поставки не получает.** Локальная ветка под пробу законна, и
89
- требовать от неё свежего основания значило бы отбивать работу, которая в главную не поедет:
90
- PR с такой ветки не откроется.
91
- - **Ключ задач задаётся один раз, и все три формы имени выводятся из него.** Заголовок задачи,
92
- имя ветки и заголовок PR строит один и тот же ключ: команда заведения задачи собирает по
93
- нему заголовок, гард поставки достаёт по нему номер из имени ветки, сверка очереди — из
94
- заголовка. Форма ветки в профиле дерева пишется той же парой `<КЛЮЧ>-<номер>`, а не своей
95
- похожей: разойдясь, они не отказывают, а перестают узнавать номер, и проверка, искавшая
96
- работу без задачи, пропускает всё подряд.
97
- - **Незаданный ключ отбивает работу с очередью на месте.** Модуль борды отказывает при первом
98
- же вызове и называет, где ключ задаётся. Умолчания у ключа нет намеренно: собранный из
99
- пустого значения заголовок `[-317]` не совпадает ни с чем, и сверка очереди помечает
100
- неправильно названной каждую задачу — настоящее расхождение тонет среди этих строк.
78
+ основание без вершины главной и рабочую копию с чужой почтой в подписи. На пуше и на открытии
79
+ PR те же проверки остаются вторым рубежом, но стоят дороже: основание чинится вливанием с
80
+ конфликтом, подпись переписыванием всей ветки.
81
+ - **Судится то основание, которое названо командой, а не вершина рабочей копии.** Ветку заводят и
82
+ от `origin/main` прямо этой командой основание как раз и берут свежим. Основание, о котором
83
+ дерево ничего не знает, не судится вовсе.
84
+ - **Ветка без номера задачи условий поставки не получает.** Локальная ветка под пробу законна, а
85
+ требовать от неё свежего основания значило бы отбивать работу, которая в главную не поедет.
86
+ - **Ключ задач задаётся один раз, и все три формы имени выводятся из него.** По нему собирается
87
+ заголовок задачи, из него достаётся номер ветки, по нему же сверка читает заголовок PR. Форма
88
+ ветки в профиле дерева пишется той же парой `<КЛЮЧ>-<номер>`: разойдясь, они не отказывают, а
89
+ перестают узнавать номер проверка, искавшая работу без задачи, пропускает всё подряд.
90
+ - **Незаданный ключ отбивает работу с очередью на месте.** Модуль борды отказывает при первом же
91
+ вызове и называет, где ключ задаётся. Умолчания нет намеренно: собранный из пустого значения
92
+ заголовок не совпадает ни с чем, и настоящее расхождение тонет среди ложных строк.
101
93
  - **Заведённая задача подтверждается ответом очереди работ, а не выводом команды заведения.**
102
- Команда отвечает за свои вызовы: она может завести задачу и не довести её до борды, и её
103
- собственный разбор ошибок этот случай называет. Напечатанный номер значит «вызов прошёл», а не
104
- «задача видна тому, кто по ней работает». Спрашивается очередь по номеру, одним вызовом, и
105
- ответ читается присутствием задачи на борде, её колонкой и исполнителем.
94
+ Напечатанный номер значит «вызов прошёл», а не «задача видна тому, кто по ней работает»:
95
+ команда может завести задачу и не довести её до борды. Спрашивается очередь — по номеру, одним
96
+ вызовом,и ответ читается колонкой и исполнителем.
106
97
  - **Номер ветки и номер в заголовке PR сверяются на месте, а состояние задачи — по борде.**
107
- Формат читается из текста команды и работает без сети; существование задачи, её присутствие
108
- на борде, её колонка, исполнитель, то, что она ещё открыта, и разбор у PR только когда есть
109
- чем спросить. Нет сети или нет токена — второй ярус молча пропускается: проверка, падающая в
110
- самолёте, перестаёт что-либо значить.
111
- - **Колонка задачи двигается тем же движением, что и работа.** Ветка заведена задача
112
- переставляется во взятые в работу, PR открыт в ждущие разбора; делает это команда
113
- перевода, а не набор вызовов GraphQL по памяти. Перевод идёт сразу за шагом, который его
114
- вызвал: очередь работ читают между шагами, а не после них.
115
- - **Задача, оставшаяся в первой колонке, PR не открывает.** Гард поставки называет её колонку и
116
- команду перевода: по очереди работ такая задача читается как невзятая, хотя работа по ней
117
- сделана и выложена. На заведении ветки колонка не спрашивается — там её ещё не двигали, и
118
- требование отбивало бы первую же команду работы вместе с той, которая его и снимает. Имя
119
- первой колонки дерево называет само; не названо — колонка не судится вовсе.
98
+ Формат читается из текста команды и работает без сети; существование задачи, колонка,
99
+ исполнитель и разбор только когда есть чем спросить. Нет сети или токенавторой ярус молча
100
+ пропускается: проверка, падающая в самолёте, перестаёт что-либо значить.
101
+ - **Колонка задачи двигается тем же движением, что и работа.** Ветка заведена — задача во взятых
102
+ в работу, PR открыт в ждущих разбора; делает это команда перевода, а не вызовы GraphQL по
103
+ памяти. Перевод идёт сразу за шагом: очередь читают между шагами, а не после них.
104
+ - **Задача, оставшаяся в первой колонке, PR не открывает.** По очереди работ она читается как
105
+ невзятая, хотя работа сделана и выложена. На заведении ветки колонка не спрашивается — там её
106
+ ещё не двигали. Имя первой колонки дерево называет само; не названо колонка не судится.
120
107
  - **На борде стоят задачи, а не PR о них.** Борда показывает, что сделано и что осталось; PR
121
- отвечает на другой вопрос как именно сделано, и открывается из карточки задачи, где связь
122
- с ним заполняется сама полем «Linked pull requests». Карточка PR живёт своей жизнью: колонки
123
- под неё нет, из очереди она не уходит и остаётся в ней после слияния навсегда. Заводится она
124
- либо встроенным правилом борды, либо рукой; и то и другое выключается, а накопившееся
125
- снимается. Находит их сверка очередистрокой на каждую.
126
- - **Отставшая колонка находится сверкой очереди, а не глазами.** Сверка судит колонку по
127
- PR в обе стороны: открытый PR при задаче не в разборе и разбор без открытого PR — оба
128
- расхождения. Момента, когда задачу берут в работу, ей не видно: ветки на борде нет.
129
- - **Задачи, чинящиеся одной правкой, сливаются до мержа.** Вторая стирается вместе с номером,
130
- а недостающее из неё дописывается в первую. После мержа слить уже нельзя: ветка въехала, и
131
- откатывается она целиком.
132
- - **Работа, которую одним заходом не закрыть, помечена в двух местах, и они сверяются.** Метка
133
- на борде и строка о заходах с передачей в замысле эпика говорят одно и то же двум читателям:
134
- исполнитель открывает карточку раньше, чем замысел эпика, а планирует по замыслу. Одна пометка без
135
- другой лжёт молча, поэтому сверка очереди судит пару в обе стороны. Помечается только то, что
136
- законно не делится: пометка объёма правом делить не становится.
137
- - **Вершина открытого PR без прогона видна сверкой очереди работ.** Страница PR без прогона
138
- выглядит так же, как страница с зелёным: цвета у неё нет ни там, ни там, — и вершину, за
139
- которой прогон не встал, замечали только тем, что открывали список прогонов руками. Сверка
140
- спрашивает вершину, а не ветку, считает сам факт прогона, а не его цвет, и свежей вершине
141
- даёт время: между пушем и прогоном проходят минуты.
142
- - **Прогон, вытесненный из очереди конвейера, сверка называет отдельной строкой.** Ждущего
143
- прогона группа очереди не бережёт: следующий встающий вытесняет прежний, и тот выглядит
144
- упавшим, хотя ветку не проверял ни строчкой. Отличает их число заданий — у вытесненного оно
145
- ноль; строка называет обе команды по порядку, сперва чтение прогона.
108
+ отвечает на другой вопрос и связывается с карточкой сам. Карточка PR колонки не имеет, из
109
+ очереди не уходит и остаётся навсегда заводится она правилом борды или рукой, и то и другое
110
+ выключается. Находит их сверка очереди строкой на каждую.
111
+ - **Отставшая колонка находится сверкой очереди, а не глазами.** Сверка судит колонку по PR в обе
112
+ стороны: открытый PR при задаче не в разборе и разбор без открытого PR оба расхождения.
113
+ Момента, когда задачу берут в работу, ей не видно: ветки на борде нет.
114
+ - **Задачи, чинящиеся одной правкой, сливаются до мержа.** Вторая стирается вместе с номером, а
115
+ недостающее дописывается в первую. После мержа слить уже нельзя: ветка въехала целиком.
116
+ - **Работа, которую одним заходом не закрыть, помечена в двух местах, и они сверяются.** Метка на
117
+ борде и строка о заходах в замысле эпика говорят одно и то же двум читателям, и одна без другой
118
+ лжёт молча. Помечается только то, что законно не делится: пометка объёма правом делить не
119
+ становится.
120
+ - **Вершина открытого PR без прогона видна сверкой очереди работ.** Страница без прогона выглядит
121
+ так же, как с зелёным: цвета нет ни там, ни там. Сверка спрашивает вершину, а не ветку, считает
122
+ сам факт прогона, а не цвет, и свежей вершине даёт время.
123
+ - **Прогон, вытесненный из очереди конвейера, сверка называет отдельной строкой.** Следующий
124
+ встающий вытесняет ждущего, и тот выглядит упавшим, хотя ветку не проверял ни строчкой.
125
+ Отличает их число заданий у вытесненного оно ноль.
146
126
  - **Черновик при зелёном прогоне на вершине — расхождение сверки.** У черновика кнопка слияния
147
- заблокирована самим хостингом: зелёная страница PR владельцу ничего не разрешает, а список, в
148
- котором всё серое, читается как «работа не сделана». Гард снятия черновика сюда не достаёт
149
- он судит один ход, а PR стоит в очереди днями.
150
- - **Открытие PR отбивается, пока ветка везёт папку своей задачи.** Уборка стоит до открытия, а
151
- не после одобрения: кнопку слияния нажимает человек на странице хостинга, где гардов нет
152
- вовсе, и вливает он, как только видит зелёное. Отказ на слиянии остаётся вторым рубежом — он
153
- ловит слияние, идущее командой, но первым спрашивается открытие: это последняя точка, где
154
- отказ ещё виден тому, кто может его выполнить.
155
- - **Конфликтующий открытый PR расхождение сверки очереди работ.** Конфликт приезжает в
156
- отданный PR чужим слиянием, без единого действия автора: основание, проверенное на открытии,
157
- устаревает в ту минуту, когда владелец влил соседнюю работу. Гард снятия черновика сюда не
158
- достаёт он судит один ход, а PR стоит в очереди днями, и по списку конфликт не виден вовсе:
159
- метку хостинг показывает только внутри самого PR. Непосчитанная сливаемость расхождением не
160
- считается: хостинг считает её заново после каждой правки главной ветки, и строка на
161
- «ещё не посчитано» краснела бы на каждой свежей вершине.
162
- - **Документ едет в том же коммите, что и правка.** Обход строка `Docs-skip: <причина>` в
163
- теле коммита; пустая причина не принимается.
164
- - **Заголовок коммита сверяется с форматом на месте.** Разобранный по типу и области
165
- заголовок читается списком, а свободный текст — только целиком.
166
- - **Перед пушем прогоняются все линтеры, а не один.** Линтер кода обычно не читает файлы
167
- стилей вовсе, и правила оформления без второго прогона не проверяет ничто.
127
+ заблокирована хостингом: зелёная страница PR владельцу ничего не разрешает, а список, в котором
128
+ всё серое, читается как «работа не сделана». Гард закрывает это внутри хода; между ходами
129
+ ночью, в чужой сессии, после закрытого разговора заявку находит сверка.
130
+ - **Свои черновики судятся все разом, а не тот один, чья ветка сейчас взята.** Проверка по
131
+ текущей ветке меняет предмет суждения вместе с переключением и молчит там, где работа брошена:
132
+ прогон по оставленной заявке доходит, черновик стоит, главная уходит вперёд. Спрашиваются все
133
+ открытые черновики машинной записи, и каждый судится двумя признаками зелёный прогон на его
134
+ вершине и разобранная папка задачи в его ветке; лежащая папка означает идущую работу. Дерево,
135
+ не назвавшее машинной записи, этого не получает.
136
+ - **Открытие PR отбивается, пока ветка везёт папку своей задачи.** Уборка стоит до открытия:
137
+ кнопку слияния нажимает человек там, где гардов нет, и вливает он, как только видит зелёное.
138
+ Отказ на слиянии остаётся вторым рубежом, но первым спрашивается открытие это последняя
139
+ точка, где отказ ещё виден тому, кто может его выполнить.
140
+ - **Конфликтующий открытый PR расхождение сверки очереди работ.** Конфликт приезжает в отданный
141
+ PR чужим слиянием, без единого действия автора, и по списку не виден вовсе: метку хостинг
142
+ показывает только внутри самого PR. Непосчитанная сливаемость расхождением не считается
143
+ хостинг считает её заново после каждой правки главной.
144
+ - **Документ едет в том же коммите, что и правка.** Обход строка `Docs-skip: <причина>` в теле
145
+ коммита; пустая причина не принимается.
146
+ - **Заголовок коммита сверяется с форматом на месте.** Разобранный по типу и области заголовок
147
+ читается списком, а свободный текст только целиком.
148
+ - **Перед пушем прогоняются все линтеры, а не один.** Линтер кода обычно не читает файлы стилей
149
+ вовсе, и правила оформления без второго прогона не проверяет ничто.
168
150
  - **Сборка входит в набор наравне с линтом и юнитами.** Линтер типов не читает, а юниты читают
169
- только то, что импортировано тестом: ошибка типов в непокрытом коде доживает до сборки
170
- образа, то есть до мержа. Четыре мержа подряд так и уехали в главную ветку, ломая выкатку.
151
+ только импортированное тестом: ошибка типов в непокрытом коде доживает до сборки образа, то
152
+ есть до мержа.
171
153
  - **Набор гейта пуша не бывает уже набора конвейера.** Гейт — обещание, что пуш не приедет
172
- красным; набор, из которого выкинуты сборка и снимки, обещает то, чего не проверяет. Шаг
173
- конвейера, которому в наборе гейта нет ни строки, ни объявленного исключения с причиной,
174
- отбивает пуш, а не печатается рядом с ним: напечатанное предупреждение исполнитель читает как
175
- разрешение. Дважды подряд правка, прошедшая гейт целиком, была отбита конвейером и оба раза
176
- зелёный гейт был прочитан как «локально всё зелено».
177
- - **Сверка раскладки стоит в наборе гейта пуша наравне с линтом и сборкой.** Правка, положенная
178
- в разложенную копию мимо источника, в день, когда её делают, не ломает ничего: дерево
179
- работает, проверки зелёные, а расхождение видно только тому, кто позовёт сверку сам. Копится
180
- оно молча и всплывает на чужой работе — раскладка отказывает по правленому файлу целиком и не
181
- кладёт ни одного другого, так что цену платит тот, кто правил соседний ресурс. Статьёй выше
182
- эта строка не покрывается: сверки нет в конвейере, а значит нет и шага, который она бы
183
- закрывала, — в набор она ставится прямо, а не выводится из его полноты.
154
+ красным; набор без сборки и снимков обещает то, чего не проверяет. Шаг конвейера, которому в
155
+ наборе гейта нет ни строки, ни объявленного исключения с причиной, отбивает пуш, а не
156
+ печатается рядом с ним: напечатанное предупреждение исполнитель читает как разрешение.
157
+ - **Сверка раскладки стоит в наборе гейта пуша наравне с линтом и сборкой.** Правка мимо
158
+ источника в день, когда её делают, не ломает ничего и копится молча, а всплывает на чужой
159
+ работе: раскладка отказывает по правленому файлу целиком. Статьёй выше это не покрывается
160
+ сверки нет в конвейере, значит нет и шага, который она бы закрывала.
184
161
  - **После вливания главной ветки набор проверок пересматривается по тому, что ветка везёт
185
162
  теперь.** Вливание меняет состав правки: проверять по тому, что правил автор, — значит
186
- проверять половину, а отвечает ветка целиком. Ветка, не тронувшая ни строки показа, прогоняет
187
- снимки витрин с того момента, как вливание принесло чужую правку оформления.
163
+ проверять половину, а отвечает ветка целиком.
188
164
  - **Утверждение о главной ветке делается по удалённой ссылке, а не по локальной.** Локальная
189
- протухает в ту минуту, когда её подтянули в последний раз, и молчит об этом: она не пуста и не
190
- сломана, она описывает вчерашний день. Сравнение веток пишется от `origin/main` целиком
191
- смешав в одной команде удалённую ссылку для одной стороны и локальную для другой, промах
192
- изнутри выглядит правильным.
193
- - **Правка кода отдаётся человеку открытым PR, а не запушенной веткой.** Ветка в списке ветвей
194
- ему не показывается, во входящие не приходит и обсуждения не имеет: до открытия PR правки
195
- для человека нет. Открывается он тем же ходом, которым исполнитель говорит, что работу
196
- отдаёт, и в ответе называется номером.
165
+ протухает в ту минуту, когда её подтянули, и молчит об этом. Сравнение пишется от `origin/main`
166
+ целиком: смешав удалённую ссылку с локальной в одной команде, промах изнутри выглядит верным.
167
+ - **Правка кода отдаётся человеку открытым PR, а не запушенной веткой.** Ветка ему не
168
+ показывается, во входящие не приходит и обсуждения не имеет: до открытия PR правки для человека
169
+ нет. Открывается он тем же ходом, которым исполнитель говорит, что работу отдаёт.
197
170
  - **Не готовое к слиянию открывается черновиком — `gh pr create --draft`.** Кнопка слияния у
198
- черновика заблокирована самим хостингом, поэтому состояние «выложено на обозрение» и
199
- состояние «можно вливать» перестают выглядеть одинаково. Черновиком идёт всё, что ждёт
200
- прогона конвейера, доработки или ответа на вопрос; вопрос задаётся в самом PR.
171
+ черновика заблокирована хостингом, поэтому «выложено на обозрение» и «можно вливать» перестают
172
+ выглядеть одинаково. Черновиком идёт всё, что ждёт прогона, доработки или ответа на вопрос.
201
173
  - **Черновик снимается отдельным вызовом — `gh pr ready <номер>`.** Им исполнитель отвечает за
202
174
  готовность: проверки пройдены, доработок не осталось, работа сходится с задачей. Снятие
203
175
  черновика и просьба влить — один ход, а не два разных дня.
204
- - **Черновик не снимается с ветки, которая не сливается.** Зелёный прогон говорит «не
205
- сломано», сливаемость — «кнопку можно нажать», и владельцу нужно второе: снятый черновик он
206
- читает как приглашение влить и идёт нажимать. Спрашивается это у хостинга тем же вызовом, что
207
- автор и ревьювер, `mergeable` приходит в том же ответе; выводить сливаемость из того, что
208
- вливание прошло локально, нельзя: между локальным вливанием и взглядом владельца главная
209
- ветка успевает уйти вперёд. За один заход так было снято три черновика подряд, и все три
210
- заявки владелец увидел конфликтующими. Держится это гардом поставки, а не памятью: статья
211
- стояла здесь и до того, и промах повторился в тот же день. Дерево, чей помощник очереди работ
212
- о сливаемости не говорит вовсе, работает как прежде — поля нет, требования нет.
176
+ - **Черновик не снимается с ветки, которая не сливается.** Зелёный прогон говорит «не сломано»,
177
+ сливаемость — «кнопку можно нажать», и владельцу нужно второе. Спрашивается у хостинга тем же
178
+ вызовом, что автор и ревьювер: `mergeable` приходит в том же ответе. Выводить её из локального
179
+ вливания нельзямежду ним и взглядом владельца главная уходит вперёд. Дерево, чей помощник
180
+ очереди о сливаемости не говорит, работает как прежде: поля нет, требования нет.
213
181
  - **Указателю, в который ветки только дописывают строки, объявляется сложение обеих сторон.**
214
- Конфликт там не спор: обе допись нужны целиком, а зовёт он человека при каждом слиянии в
215
- главную ветку за один заход одна и та же строка разрешалась шесть раз в шести ветках.
216
- Объявление снимает ручное разрешение: слияние проходит само. **Метку сливаемости на странице
217
- заявки оно при этом не снимает** — хостинг считает её своим приёмом и настройки слияния не
218
- читает. Гаснет метка только после того, как ветка вобрала главную и это уехало на хостинг.
219
- Обещать по этому объявлению «конфликтов больше не будет» нельзя: не будет ручной работы, а
220
- вливать главную в открытые ветки после каждого слияния придётся по-прежнему.
221
- - **Разрешённый конфликт, оставшийся незапушенным, хуже неразрешённого.** Владелец видит
222
- прежнее состояние и читает его как «не сделано ничего», а сделанное лежит в рабочем дереве
223
- исполнителя, где его не видит никто. Ветка, в которой разрешён конфликт, пушится тем же
224
- ходом либо конфликт не разрешается вовсе.
225
- - **Черновик не снимается, пока у PR нет разбора.** Гард поставки смотрит запрошенного ревьювера
226
- и оставленный отзыв: снятый черновик читается как «можно вливать», а вливать некому. Раньше
227
- этого хода спросить негде до открытия PR ревьювера нет вовсе. Судится и вызов без номера:
228
- без него клиент берёт PR текущей ветки, и требование снималось бы одним пробелом. Возврат PR
229
- в черновик `gh pr ready --undo` требования не получает: он делает то же, чего гард и
230
- добивается.
231
- - **Мерж PR нажимает человек, а не исполнитель работы.** Кнопка и вызов слияния равны: запрет
232
- на них один. Исполнитель сливает свой PR только тогда, когда человек сказал это прямо и про
233
- этот PR; сказанное об одном PR на следующий не переносится, а молчание разрешением не
234
- бывает. Работа кончается PR, с которого снят черновик, и в ответе называется его номер.
235
- - **Личность вызова, открывающего заявку, стережёт гард поставки, а не память исполнителя.**
236
- Она приходит окружением, и из текста команды видна только явной подстановкой токена — её гард
237
- и требует, называя переменную и готовую строку; дерево, не назвавшее машинной записи,
238
- требования не получает. Ответ хостинга об авторе он спрашивает позже, на снятии черновика:
239
- это последний ход, где промах ещё исправим — влитую заявку не переоткрыть, а автора у неё не
240
- сменить. Прежде обе стороны держались статьёй и разбором происшествия, и промах повторился на
241
- третий день.
182
+ Конфликт там не спор: обе допись нужны целиком, а человека он зовёт при каждом слиянии.
183
+ Объявление снимает ручное разрешение, но **метку сливаемости не гасит**: хостинг считает её
184
+ своим приёмом и настроек слияния не читает гаснет она, когда ветка вобрала главную и это
185
+ уехало на хостинг.
186
+ - **Правка, доведённая до коммита, доводится до хостинга тем же ходом.** Владелец видит прежнее
187
+ состояние и читает его как «не сделано ничего», а сделанное лежит там, где его не видит никто.
188
+ Оставшееся в дереве называется причиной словом владельца, а не списком остатков.
189
+ - **Черновик не снимается, пока у PR нет разбора.** Гард смотрит запрошенного ревьювера и
190
+ оставленный отзыв: снятый черновик читается как «можно вливать», а вливать некому. Раньше этого
191
+ хода спросить негде. Судится и вызов без номера без него клиент берёт PR текущей ветки, и
192
+ требование снималось бы одним пробелом.
193
+ - **Мерж PR нажимает человек, а не исполнитель работы.** Кнопка и вызов слияния равны: запрет на
194
+ них один. Исполнитель сливает свой PR только тогда, когда человек сказал это прямо и про этот
195
+ PR; сказанное об одном на следующий не переносится, а молчание разрешением не бывает.
196
+ - **Личность вызова, открывающего заявку, стережёт гард поставки, а не память исполнителя.** Она
197
+ приходит окружением и из текста команды видна только явной подстановкой токена её гард и
198
+ требует; дерево, не назвавшее машинной записи, требования не получает. Ответ хостинга об авторе
199
+ он спрашивает на снятии черновика: это последний ход, где промах исправим влитую заявку не
200
+ переоткрыть, а автора у неё не сменить.
242
201
 
243
202
  - **Автор PR не может быть его ревьювером.** Запрос разбора на самого себя GitHub принимает и
244
- молча не создаёт — разбор при этом выглядит запрошенным. Поэтому в разборе считаются только
245
- запрос и отзыв не от автора: гард снятия черновика читает состояние PR именно так.
203
+ молча не создаёт — разбор при этом выглядит запрошенным. В разборе считаются только запрос и
204
+ отзыв не от автора.
205
+ - **Вызов клиента хостинга идёт из дерева, а связка команд исхода не проверяет.** Репозиторий
206
+ клиент берёт у текущего каталога и вне дерева отказывает; следующее звено связки увозит на
207
+ хостинг то, что осталось от отказавшего, поэтому тело читается обратно тем же ходом.
246
208
  - **Метки, исполнитель и ревьювер PR ставятся вызовами `gh api`, а не `gh pr edit`.** На
247
- репозитории со старой бордой `gh pr edit` отвечает отказом про Projects (classic) и до
248
- правки не доходит вовсе.
249
- - **Борда правится запросом GraphQL по идентификатору проекта.** `gh project` с `--owner`
250
- отвечает `unknown owner type`, когда владелец борды — не та учётная запись, под которой
251
- идёт вызов.
209
+ репозитории со старой бордой `gh pr edit` отвечает отказом про Projects (classic) и до правки
210
+ не доходит.
211
+ - **Борда правится запросом GraphQL по идентификатору самой борды, а не по имени владельца.**
252
212
  - **Почта машинного коммита копируется из компаньона, а не набирается по памяти.** Служебный
253
- адрес GitHub — `<число>+<логин>@users.noreply.github.com`, и сопоставляется он по числу: логин
254
- рядом с ним не сверяет никто. Коммит с чужим числом уезжает подписанным посторонним человеком,
255
- а изнутри промах не виден имя учётной записи в истории то самое. Ту же строку держит профиль
256
- дерева, и гард поставки отбивает пуш при расхождении.
213
+ адрес — `<число>+<логин>@users.noreply.github.com`, и сопоставляется он по числу: логин рядом с
214
+ ним не сверяет никто. Коммит с чужим числом уезжает подписанным посторонним, а изнутри промах
215
+ не виден. Ту же строку держит профиль дерева, и гард отбивает пуш при расхождении.
257
216
  - **Личность машинной записи подтверждается ответом хостинга, а не узнаванием строки.** Знакомый
258
- вид строки подтверждением не бывает промах выглядел знакомо. Спрашивается токеном самой
259
- записи, ответом о себе: логин и число приходят вместе. Поиск по числу для ограниченной записи
260
- отвечает «не найдено» и её собственным токеном, поэтому годится только ответ о себе.
261
- - **Сценарии гардов задают настройки git сами, а не берут их с машины.** Коммит во временном
262
- репозитории сценария наследует общий конфиг: если включена подпись, git идёт в агент ключей,
263
- а заблокированный агент роняет весь набор — со стороны это выглядит сломанным гардом. Автор,
264
- почта и подпись передаются флагами `-c` прямо в команду.
217
+ вид строки подтверждением не бывает. Спрашивается токеном самой записи, ответом о себе: логин и
218
+ число приходят вместе поиск по числу для ограниченной записи отвечает «не найдено».
219
+ - **Сценарии гардов задают настройки git сами, а не берут их с машины.** Включённая на машине
220
+ подпись уводит git в агент ключей, а заблокированный агент роняет весь набор со стороны это
221
+ выглядит сломанным гардом. Автор, почта и подпись передаются флагами `-c` прямо в команду.
222
+
223
+ - **Каждый коммит вклада ветки подписан машинной записью, и это проверяется набором пуша.** Гард
224
+ поставки судит только коммит, назвавшийся ею, и подписанный человеком проходит мимо: там, где
225
+ человек не коммитит вовсе, это промах, а не законный случай.
226
+ - **Состояние заявки перечитывается у хостинга сразу после публикации, а не берётся из кода
227
+ возврата.** Открытие заявки и постановка ревьювера отвечают нулём и тогда, когда сделали не то
228
+ или не сделали ничего.
229
+ - **Автор открытой заявки и наличие у неё ревьювера сверяются очередью работ.** До слияния оба
230
+ промаха не видны ничем: заявка, открытая человеком, ревьювера не получит никогда, и выглядит
231
+ это как заявка, которой его просто не поставили.
232
+ - **Ревьюверы спрашиваются вызовом REST, а не выборкой клиента.** Её поля собираются запросом
233
+ GraphQL, а тот требует области чтения организации, которой у машинной записи нет: «сошлось»
234
+ перестаёт отличаться от «спросить было нечем».
235
+ - **Силовая отправка ветки, стоящей под другой в стопке, закрывает её заявку как слитую.**
236
+ Хостинг считает заявку слитой, когда вершина её ветки достижима из базы; состояние лживое — в
237
+ главной ветке правки нет, а задача остаётся открытой.
265
238
 
266
239
  ## Чего из закона здесь нет
267
240
 
@@ -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-pr, git-workflow-merge. Выкатка, образы и миграции — правило deploy-flow.
5
+ description: Правило под «Закон о поставке» для дерева на GitLab. Брать на заведение задачи, ветки, коммит, пуш, открытие MR и слияние. Называет соответствие задачи и ветки один к одному, имена, машинную учётную запись и гарды поставки. Паттерны: git-workflow-commit, -pr, -merge. Выкатка — правило deploy-flow.
6
6
  ---
7
7
 
8
8
  # Поставка — как это устроено здесь
@@ -2,7 +2,7 @@
2
2
  name: lib-layers
3
3
  kind: rule
4
4
  law: lib-imports
5
- description: Правило под «Закон об импортах между либами». Брать при правке project.json, tsconfig.base.json, eslint/boundaries/**, любого src/index.ts и проверок раскладки, а также когда решается, где живёт общий символ. Называет семьи, слои, теги и границы этого дерева. Готовый порядок действий — в паттернах lib-layers-new и lib-layers-move.
5
+ description: Правило под «Закон об импортах между либами». Брать при правке манифестов проектов, путей сборки, границ линтера, любого барреля и проверок раскладки, а также когда решается, где живёт общий символ. Паттерны: lib-layers-new, lib-layers-move.
6
6
  ---
7
7
 
8
8
  # Импорты между либами — как это устроено здесь
@@ -2,7 +2,7 @@
2
2
  name: observability
3
3
  kind: rule
4
4
  law: observability
5
- description: Правило под «Закон о наблюдаемости». Брать при правке логгера, контекста запроса, домена отказов и домена оповещений, при заведении новой строки лога и когда решается, что владелец узнает об отказе. Называет уровни, номер обращения, вычистку секретов, сводку старта и то, что уходит наружу при отказе. Готовый код — в паттерне observability-record.
5
+ description: Правило под «Закон о наблюдаемости». Брать при правке логгера, контекста запроса, домена отказов и оповещений, при заведении новой строки лога и когда решается, что владелец узнает об отказе. Паттерн observability-record.
6
6
  ---
7
7
 
8
8
  # Наблюдаемость — как это устроено здесь
@@ -2,7 +2,7 @@
2
2
  name: platform-access
3
3
  kind: rule
4
4
  law: frontend-application
5
- description: Правило под «Закон о фронтовом приложении». Брать, когда правка задевает глобальный объект или среду исполнения — window, globalThis, PLATFORM_ID, isPlatformBrowser, document.defaultView, localStorage, IntersectionObserver. Называет токены DI, приведение типа и подводные камни отдачи страницы сервером. Не действует под libs/api и apps/api. Готовый код в паттерне platform-access-di.
5
+ description: Правило под «Закон о фронтовом приложении». Брать, когда правка задевает глобальный объект или среду исполнения — window, globalThis, PLATFORM_ID, localStorage. Называет токены DI и подводные камни отдачи страницы сервером. Под libs/api и apps/api не действует. Паттерн platform-access-di.
6
6
  ---
7
7
 
8
8
  # Окружение браузера — как это устроено здесь
@@ -2,7 +2,7 @@
2
2
  name: reuse-first
3
3
  kind: rule
4
4
  law: reuse-first
5
- description: Правило под «Закон о единообразии приложения». Брать перед заведением любого нового экрана, компонента, поля, стора, сервиса, маппера или процедуры на что опираться, что уже готово в ките и базовых классах, по каким признакам видно, что готовое обошли. Что делать, когда готового не хватило, — в паттерне reuse-first-extend.
5
+ description: Правило под «Закон о единообразии приложения». Брать перед заведением любого нового экрана, компонента, поля, стора, сервиса, маппера или процедуры: на что опираться и по каким признакам видно, что готовое обошли. Паттерн reuse-first-extend.
6
6
  ---
7
7
 
8
8
  # Единообразие — как это устроено здесь
@@ -2,7 +2,7 @@
2
2
  name: seo
3
3
  kind: rule
4
4
  law: search-visibility
5
- description: Правило под «Закон о видимости в поиске». Брать при любой правке, доходящей до разметки публичного сайта шаблоны страниц, meta/title/description, JSON-LD, canonical, hreflang, маршруты сайта, sitemap, robots, nginx. Называет локали перевода, где что лежит и чего у нас нет. Готовый код — в паттернах seo-page и seo-verify.
5
+ description: Правило под «Закон о видимости в поиске». Брать при любой правке, доходящей до разметки публичного сайта: шаблоны страниц, мета-теги, микроразметка, канонический адрес, языковые версии, карта сайта. Паттерны: seo-page, seo-verify.
6
6
  ---
7
7
 
8
8
  # Видимость в поиске — как это устроено здесь
@@ -116,8 +116,9 @@ flowchart TD
116
116
 
117
117
  ## Чего из закона здесь нет
118
118
 
119
- Листинга объектов неткорень локали отдаёт единственный объект. Появится листинг
120
- канонический адрес корня пересматривается; это `Q-SV-1` в законе.
119
+ Что отдаёт корень локали единственную запись или список, правило не утверждает: это
120
+ состояние дерева, и живёт оно в компаньоне рядом. Развилка от этого не исчезает: там, где
121
+ список появляется, канонический адрес корня пересматривается; это `Q-SV-1` в законе.
121
122
 
122
123
  ## Паттерны
123
124
 
@@ -2,7 +2,7 @@
2
2
  name: shared-code
3
3
  kind: rule
4
4
  law: shared-code
5
- description: Правило под «Закон об общем коде приложений». Брать, когда значение должно одинаково пониматься сайтом, админкой и бэкендом предел выборки, набор операторов условия, направление порядка, длина поля, форма запроса и ответа списка. Называет, что берётся из @rt-tools/utils, что из @<область>/common/util и что ловит check:dupes. Готовый код — в паттерне shared-code-new.
5
+ description: Правило под «Закон об общем коде приложений». Брать, когда значение должно одинаково пониматься сайтом, админкой и бэкендом: предел выборки, набор операторов условия, длина поля, форма запроса и ответа списка. Паттерн shared-code-new.
6
6
  ---
7
7
 
8
8
  # Общий код — как это устроено здесь