@rt-tools/agent-kit 0.8.2 → 0.9.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 (170) hide show
  1. package/README.md +13 -0
  2. package/assets/agents/rules-reviewer.md +83 -0
  3. package/assets/checks/board.github.mjs +48 -1
  4. package/assets/checks/check-board.github.mjs +84 -1
  5. package/assets/checks/check-dupes.mjs +66 -6
  6. package/assets/checks/check-lib-layers.mjs +13 -524
  7. package/assets/checks/check-specs.mjs +61 -747
  8. package/assets/checks/check-styles.mjs +185 -15
  9. package/assets/checks/lib-boundaries.mjs +143 -0
  10. package/assets/checks/lib-common.mjs +149 -0
  11. package/assets/checks/lib-domains.mjs +205 -0
  12. package/assets/checks/lib-manifests.mjs +60 -0
  13. package/assets/checks/lib-reexports.mjs +101 -0
  14. package/assets/checks/rt-kit-checks.config.mjs +26 -0
  15. package/assets/checks/spec-anchors.mjs +297 -0
  16. package/assets/checks/spec-common.mjs +222 -0
  17. package/assets/checks/spec-contract.mjs +152 -0
  18. package/assets/checks/spec-scenarios.mjs +201 -0
  19. package/assets/commands/feedback.md +95 -0
  20. package/assets/commands/rules-review.md +98 -0
  21. package/assets/commands/skill-curator.md +39 -22
  22. package/assets/defaults/project.sh +8 -0
  23. package/assets/docs/GLOSSARY.md +21 -20
  24. package/assets/hooks/git-guard-push-tests.sh +8 -4
  25. package/assets/hooks/reuse-first-guard.sh +16 -2
  26. package/assets/hooks/skill-gate.sh +1 -1
  27. package/assets/hooks/sql-guard-parse.sh +187 -0
  28. package/assets/hooks/sql-guard-request.sh +117 -0
  29. package/assets/hooks/sql-guard-target.sh +134 -0
  30. package/assets/hooks/sql-guard-write.sh +212 -0
  31. package/assets/hooks/sql-guard.sh +26 -596
  32. package/assets/hooks/task-flow-guard.sh +16 -2
  33. package/assets/hooks/waiting-turn-guard.sh +116 -0
  34. package/assets/laws/delivery.md +35 -0
  35. package/assets/laws/project-documentation.md +18 -0
  36. package/assets/laws/work-conduct.md +25 -0
  37. package/assets/patterns/admin-lists-screen.md +25 -14
  38. package/assets/patterns/admin-nav-item.md +1 -1
  39. package/assets/patterns/component-structure-new.md +1 -1
  40. package/assets/patterns/entity-aside.md +4 -2
  41. package/assets/patterns/git-workflow-commit.azure.md +74 -2
  42. package/assets/patterns/git-workflow-commit.github.md +75 -2
  43. package/assets/patterns/git-workflow-commit.gitlab.md +75 -4
  44. package/assets/patterns/git-workflow-docker.md +30 -0
  45. package/assets/patterns/observability-record.md +9 -0
  46. package/assets/patterns/shared-code-new.md +2 -2
  47. package/assets/patterns/task-flow-close.md +160 -47
  48. package/assets/patterns/task-flow-handoff.md +1 -1
  49. package/assets/patterns/task-flow-resume.md +3 -3
  50. package/assets/patterns/task-flow-start.md +32 -5
  51. package/assets/rules/angular-patterns.md +22 -0
  52. package/assets/rules/api-layer.md +25 -0
  53. package/assets/rules/browser-verification.md +32 -0
  54. package/assets/rules/component-structure.md +21 -0
  55. package/assets/rules/dependencies.md +22 -0
  56. package/assets/rules/doc-style.md +24 -0
  57. package/assets/rules/entity-conventions.needs-admin.md +21 -0
  58. package/assets/rules/entity-models.md +21 -0
  59. package/assets/rules/git-workflow.azure.md +57 -1
  60. package/assets/rules/git-workflow.github.md +89 -2
  61. package/assets/rules/git-workflow.gitlab.md +56 -1
  62. package/assets/rules/lib-layers.md +29 -0
  63. package/assets/rules/lists.md +37 -10
  64. package/assets/rules/navigation.md +21 -0
  65. package/assets/rules/observability.needs-app.md +23 -0
  66. package/assets/rules/permissions.md +23 -0
  67. package/assets/rules/platform-access.md +21 -0
  68. package/assets/rules/reuse-first.md +20 -0
  69. package/assets/rules/seo.md +19 -0
  70. package/assets/rules/shared-code.md +20 -1
  71. package/assets/rules/spec-driven.md +32 -0
  72. package/assets/rules/styling-bem.md +19 -0
  73. package/assets/rules/task-flow.md +148 -18
  74. package/assets/rules/testing.md +62 -0
  75. package/assets/rules/translations.md +21 -0
  76. package/assets/rules/typescript-conventions.md +28 -0
  77. package/assets/samples/specs/_template/spec.md +83 -0
  78. package/assets/samples/tasks/_template/grill.md +28 -0
  79. package/assets/samples/tasks/_template/plan.md +39 -0
  80. package/assets/samples/tasks/_template/progress.md +23 -0
  81. package/assets/skills/agent-kit.md +52 -2
  82. package/assets/templates/proposal.md +21 -0
  83. package/assets/templates/rule.md +31 -2
  84. package/bin/agent-kit.d.ts.map +1 -1
  85. package/bin/agent-kit.js +115 -87
  86. package/bin/agent-kit.js.map +1 -1
  87. package/index.d.ts +1 -0
  88. package/index.d.ts.map +1 -1
  89. package/index.js +1 -0
  90. package/index.js.map +1 -1
  91. package/lib/argv.d.ts.map +1 -1
  92. package/lib/argv.js +6 -4
  93. package/lib/argv.js.map +1 -1
  94. package/lib/assets.d.ts.map +1 -1
  95. package/lib/assets.js +2 -1
  96. package/lib/assets.js.map +1 -1
  97. package/lib/cargo.d.ts +20 -0
  98. package/lib/cargo.d.ts.map +1 -1
  99. package/lib/cargo.js.map +1 -1
  100. package/lib/cascade.d.ts +55 -0
  101. package/lib/cascade.d.ts.map +1 -0
  102. package/lib/cascade.js +131 -0
  103. package/lib/cascade.js.map +1 -0
  104. package/lib/catalog.d.ts +0 -75
  105. package/lib/catalog.d.ts.map +1 -1
  106. package/lib/catalog.js +44 -127
  107. package/lib/catalog.js.map +1 -1
  108. package/lib/commands.d.ts.map +1 -1
  109. package/lib/commands.js +153 -85
  110. package/lib/commands.js.map +1 -1
  111. package/lib/companion.d.ts.map +1 -1
  112. package/lib/companion.js +5 -5
  113. package/lib/companion.js.map +1 -1
  114. package/lib/config.d.ts +12 -1
  115. package/lib/config.d.ts.map +1 -1
  116. package/lib/config.js +11 -5
  117. package/lib/config.js.map +1 -1
  118. package/lib/enroll.d.ts +56 -0
  119. package/lib/enroll.d.ts.map +1 -0
  120. package/lib/enroll.js +123 -0
  121. package/lib/enroll.js.map +1 -0
  122. package/lib/freshness.d.ts.map +1 -1
  123. package/lib/freshness.js +31 -17
  124. package/lib/freshness.js.map +1 -1
  125. package/lib/hooks-map.d.ts +30 -0
  126. package/lib/hooks-map.d.ts.map +1 -1
  127. package/lib/hooks-map.js +80 -18
  128. package/lib/hooks-map.js.map +1 -1
  129. package/lib/integrity.d.ts +1 -2
  130. package/lib/integrity.d.ts.map +1 -1
  131. package/lib/integrity.js +0 -1
  132. package/lib/integrity.js.map +1 -1
  133. package/lib/observations.d.ts.map +1 -1
  134. package/lib/observations.js +25 -12
  135. package/lib/observations.js.map +1 -1
  136. package/lib/order.d.ts +10 -0
  137. package/lib/order.d.ts.map +1 -0
  138. package/lib/order.js +14 -0
  139. package/lib/order.js.map +1 -0
  140. package/lib/picker.d.ts.map +1 -1
  141. package/lib/picker.js +8 -2
  142. package/lib/picker.js.map +1 -1
  143. package/lib/plan.js +1 -1
  144. package/lib/plan.js.map +1 -1
  145. package/lib/proposals.d.ts.map +1 -1
  146. package/lib/proposals.js +25 -8
  147. package/lib/proposals.js.map +1 -1
  148. package/lib/sections.js +1 -1
  149. package/lib/sections.js.map +1 -1
  150. package/lib/ship.d.ts.map +1 -1
  151. package/lib/ship.js +9 -1
  152. package/lib/ship.js.map +1 -1
  153. package/lib/shipment.d.ts.map +1 -1
  154. package/lib/shipment.js +14 -10
  155. package/lib/shipment.js.map +1 -1
  156. package/lib/snapshot.d.ts.map +1 -1
  157. package/lib/snapshot.js +2 -1
  158. package/lib/snapshot.js.map +1 -1
  159. package/lib/stamp.js +1 -1
  160. package/lib/stamp.js.map +1 -1
  161. package/lib/sync.d.ts +12 -2
  162. package/lib/sync.d.ts.map +1 -1
  163. package/lib/sync.js +11 -10
  164. package/lib/sync.js.map +1 -1
  165. package/lib/vars.d.ts.map +1 -1
  166. package/lib/vars.js +2 -3
  167. package/lib/vars.js.map +1 -1
  168. package/package.json +1 -1
  169. package/rt-tools-agent-kit-0.9.0.tgz +0 -0
  170. package/rt-tools-agent-kit-0.8.2.tgz +0 -0
@@ -107,7 +107,34 @@ Workflow(name: "plan", args: "docs/tasks/_draft-<slug>")
107
107
  «не входит». Находка критика, расходящаяся с ответом владельца, относится владельцу — она не
108
108
  исполняется молча и не считается закрытой правкой текста.
109
109
 
110
- ### 4. Задача, ветка, папка
110
+ ### 4. Серия задач объявляется эпиком
111
+
112
+ Разбор кончился одной задачей — шаг пропускается. Вышло несколько, и порядок между ними
113
+ значим — эпик объявляется здесь, до первой из них, и дважды: карточкой в очереди работ с меткой
114
+ эпика и замыслом эпика рядом с ней.
115
+
116
+ Замысел эпика называет три вещи, и ни одна не выводится из остальных:
117
+
118
+ ```markdown
119
+ # <Возможность, которая разрабатывается>
120
+
121
+ Одной фразой: что у владельца появится, когда эпик кончится.
122
+
123
+ | № | Задача | Почему здесь |
124
+ | --- | ------------ | ------------------------ |
125
+ | 1 | <что делает> | <на чём стоят следующие> |
126
+ | 2 | <что делает> | <что из первой ей нужно> |
127
+ ```
128
+
129
+ Состав без порядка порядком не является: две задачи, у которых он держался пониманием, ушли в
130
+ работу наоборот, и вторая переделывалась под первую. Назначенный здесь порядок держится до конца
131
+ эпика; пересмотр — решение владельца, и записывается он в ход работы той задачи, которая его
132
+ вызвала.
133
+
134
+ Лежит замысел вне папки задачи: та умирает с мержем первой же задачи. Каталог для него называет
135
+ компаньон правила — у пакета своего пути нет.
136
+
137
+ ### 5. Задача, ветка, папка
111
138
 
112
139
  ```bash
113
140
  npm run task:new -- --title '<Что не так>' --slug <slug> --label documentation --label area:tooling < тело.md
@@ -135,7 +162,7 @@ cp docs/tasks/_template/plan.md docs/tasks/<КЛЮЧ>-<номер>-<slug>/plan.m
135
162
  cp docs/tasks/_template/progress.md docs/tasks/<КЛЮЧ>-<номер>-<slug>/progress.md
136
163
  ```
137
164
 
138
- ### 5. Шапка замысла
165
+ ### 6. Шапка замысла
139
166
 
140
167
  Её читает гард:
141
168
 
@@ -159,9 +186,9 @@ cp docs/tasks/_template/progress.md docs/tasks/<КЛЮЧ>-<номер>-<slug>/pr
159
186
  заведённая заранее задача после разбивки закрывается и остаётся мусором в очереди работ.
160
187
  - **Разбор пишется на диск сразу, а не копится в переписке.** Сессия обрывается, и разбор,
161
188
  прожитый в разговоре, восстанавливается только пересказом владельца.
162
- - **Из одного разбора вышло несколько задач — общее уезжает в `docs/plans/<линия>.md`.**
163
- Папка задачи умирает с мержем, а порядок задач и зависимости между ними должны его
164
- пережить.
189
+ - **Из одного разбора вышло несколько задач — общее уезжает в замысел эпика.** Папка задачи
190
+ умирает с мержем, а порядок задач и зависимости между ними должны его пережить. Каталог для
191
+ замысла называет компаньон правила.
165
192
  - **Задача заводится командой, а не четырьмя вызовами подряд.** Борда к репозиторию не
166
193
  привязана, и задача попадает на неё только явным добавлением.
167
194
  - **Slug ветки берётся из терминологии договорённости, а не из слов просьбы.** Договорённость
@@ -31,6 +31,28 @@ description: Правило под «Закон о фронтовом прило
31
31
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
32
32
  же дереве, которое держит код иначе.
33
33
 
34
+ ## Ход
35
+
36
+ Ход правки класса приложения: с чего исполнитель начинает, где развилка между производным
37
+ значением и действием, и чем кончается каждая ветка.
38
+
39
+ ```mermaid
40
+ flowchart TD
41
+ A[Правится класс приложения] --> B{Что заводится}
42
+ B -->|Значение, выводимое из другого| C[computed: следит за сигналами, а не зовёт сервис]
43
+ B -->|Действие пользователя| D[Источник действия с суффиксом Source]
44
+ B -->|Состояние списка| E[Наследуется общая основа списочного стора]
45
+ D --> F[Подписка объявлена один раз при заведении, а не в методе]
46
+ F --> G{Прежний запрос ещё идёт}
47
+ G -->|Ответ нужен последний| H[Поток переключается]
48
+ G -->|Нужны все| I[Поток склеивается по очереди]
49
+ H --> J[Подписка гасится вместе с владельцем]
50
+ I --> J
51
+ C --> K[Готово]
52
+ E --> K
53
+ J --> K
54
+ ```
55
+
34
56
  ## Как закон применяется здесь
35
57
 
36
58
  - **Подписка объявляется один раз, а не в методе действия.** Метод толкает значение в
@@ -30,6 +30,31 @@ description: Правило под «Закон о фронтовом прило
30
30
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
31
31
  же дереве, которое держит код иначе.
32
32
 
33
+ ## Ход
34
+
35
+ Ход похода домена за данными: пара классов, границы типов между ними и развилка между списком
36
+ и одиночной записью.
37
+
38
+ ```mermaid
39
+ flowchart TD
40
+ A[Домену нужны данные] --> B{Что за домен}
41
+ B -->|Своя сущность| C[Заводится своя пара: фасад и сервис]
42
+ B -->|Чужая сущность| D[Зовётся её пара, своя не заводится]
43
+ C --> E{Что читается}
44
+ E -->|Список| F[Один вход: выборка целиком]
45
+ E -->|Одна запись| G[Вход — её признак]
46
+ F --> H[Ответ кладётся в общий конвертер целиком]
47
+ H --> I[В ответе стоит применённая выборка, а не запрошенная]
48
+ G --> J[Фасад отдаёт контракт, сервис переводит в состояние домена]
49
+ I --> J
50
+ J --> K{Данные приходят разом}
51
+ K -->|Да| L[Пара отдаёт поток]
52
+ K -->|Нет, живой срез| M[Серверный стрим — объявленное исключение]
53
+ L --> N[Готово]
54
+ M --> N
55
+ D --> N
56
+ ```
57
+
33
58
  ## Как закон применяется здесь
34
59
 
35
60
  - **Домен ходит за данными парой классов: фасад зовёт процедуру, сервис переводит модели.**
@@ -26,6 +26,38 @@ description: Правило под «Закон о проверяемости».
26
26
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
27
27
  же дереве, которое держит код иначе.
28
28
 
29
+ ## Ход
30
+
31
+ Ход проверки через браузер: что выясняется до первого запроса, где развилка между поднятым и
32
+ не поднятым приложением и чем подтверждается вывод.
33
+
34
+ ```mermaid
35
+ flowchart TD
36
+ A[Нужна проверка в браузере] --> B{Порт занят}
37
+ B -->|Да| C[Выясняется, что именно отвечает]
38
+ B -->|Нет| D{Кто поднимает стенд}
39
+ C --> E{Отвечает то самое приложение}
40
+ E -->|Да| F[Второй экземпляр не поднимается]
41
+ E -->|Нет| T[Занявшее порт останавливается по идентификатору процесса, а не по имени команды]
42
+ T --> D
43
+ D -->|Владелец| U[Ему говорят сразу, а не в конце захода: агента отбивает гард]
44
+ D -->|Агент| V[Стенд поднимается]
45
+ U --> G[Драйвер водит браузер на закреплённом профиле]
46
+ V --> G
47
+ F --> G
48
+ G --> W{Экран публичный и это первый заход}
49
+ W -->|Да| X[Заход метится признаком служебного посещения: иначе он попадёт в счёт гостей]
50
+ W -->|Нет| H{Что проверяется}
51
+ X --> H
52
+ H -->|Путь запроса и отдача страницы| I[Проверка идёт за настоящим прокси]
53
+ H -->|Вёрстка| J[Замер вычисленных значений, а не взгляд]
54
+ I --> K{Расхождение объясняется кэшем}
55
+ J --> K
56
+ K -->|Да| L[Кэш чистится и замер повторяется: объяснение не подтверждение]
57
+ K -->|Нет| M[Вывод называет число и способ его получить]
58
+ L --> M
59
+ ```
60
+
29
61
  ## Как закон применяется здесь
30
62
 
31
63
  - **Второй экземпляр уже поднятого приложения не поднимается.** До первого запроса выясняется,
@@ -27,6 +27,27 @@ description: Правило под «Закон о фронтовом прило
27
27
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
28
28
  же дереве, которое держит код иначе.
29
29
 
30
+ ## Ход
31
+
32
+ Ход правки компонента: где решается разметка, где — привязка, и что ставится на каждый
33
+ интерактивный элемент.
34
+
35
+ ```mermaid
36
+ flowchart TD
37
+ A[Правится компонент] --> B[Селектор элементный, класс блока на хосте]
38
+ B --> C{В шаблоне нужен вычисленный вид}
39
+ C -->|Да| D[Значение считается в классе, шаблон методов не зовёт]
40
+ C -->|Нет| E[Разметка пишется как есть]
41
+ D --> F{Есть интерактивный элемент}
42
+ E --> F
43
+ F -->|Да| G[Ставится якорь для спек, а доступность — отдельными атрибутами]
44
+ F -->|Нет| H[Готово]
45
+ G --> I{Один компонент в обеих ветках условия}
46
+ I -->|Да| J[Это условная привязка: ветки сводятся в одну]
47
+ I -->|Нет| H
48
+ J --> H
49
+ ```
50
+
30
51
  ## Как закон применяется здесь
31
52
 
32
53
  - **Шаблон не зовёт методов.** Правило линтера банит `{{ getTotal() }}` и `@if
@@ -27,6 +27,28 @@ description: Правило под «Закон о поставке». Брат
27
27
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
28
28
  же дереве, которое держит код иначе.
29
29
 
30
+ ## Ход
31
+
32
+ Ход подъёма версии: где решается сама версия, где — граница переформатирования, и чем работа
33
+ кончается.
34
+
35
+ ```mermaid
36
+ flowchart TD
37
+ A[Нужна новая версия пакета] --> B{Верхняя граница чем задана}
38
+ B -->|Есть peer-диапазоны у зависимых| C[Граница берётся из них, а не из последнего номера в реестре]
39
+ B -->|Нет| D[Берётся последняя выпущенная]
40
+ C --> E{Версия выпущена недавно}
41
+ D --> E
42
+ E -->|Да, и она нужна прямо сейчас| F[Выписывается отдельно, с названной причиной]
43
+ E -->|Да, но не срочно| G[Выдерживается: свежая версия отзывается чаще старой]
44
+ E -->|Нет| H[Записывается точным номером, без диапазона]
45
+ F --> H
46
+ H --> I{Обновился форматтер или линтер}
47
+ I -->|Да| J[Переформатируется только то, что линтер и проверяет; новые правила разбираются поимённо]
48
+ I -->|Нет| K[Снимок дерева пересобирается, набор гоняется целиком]
49
+ J --> K
50
+ ```
51
+
30
52
  ## Как закон применяется здесь
31
53
 
32
54
  - **Версия пакета записана точным номером.** Из диапазона сегодня и через неделю поставится
@@ -27,6 +27,30 @@ description: Правило под «Закон о документации пр
27
27
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
28
28
  же дереве, которое держит код иначе.
29
29
 
30
+ ## Ход
31
+
32
+ Ход правки текста: что проверяется до записи, где развилка между новым словом и уже занятым, и
33
+ что делается со снятым именем.
34
+
35
+ ```mermaid
36
+ flowchart TD
37
+ A[Пишется текст проекта] --> B{Нужно слово для нового понятия}
38
+ B -->|Да| C{Оно есть в словаре}
39
+ C -->|Да| D[Берётся оттуда в том же значении]
40
+ C -->|Нет| E[Заводится в словаре той же правкой либо заменяется простым]
41
+ B -->|Нет| F{В тексте называется путь или имя файла}
42
+ D --> F
43
+ E --> F
44
+ F -->|Да| G[Путь проверяется командой: названный, но несуществующий читается как указание]
45
+ F -->|Нет| H{В тексте стоит число или утверждение о проверке}
46
+ G --> H
47
+ H -->|Число| I[Пересчитывается командой в том же изменении либо не пишется вовсе]
48
+ H -->|Проверка| J[Запускается, а не пересказывается]
49
+ H -->|Ни то ни другое| K[Документ едет тем же коммитом, что и правка, которую описывает]
50
+ I --> K
51
+ J --> K
52
+ ```
53
+
30
54
  ## Как закон применяется здесь
31
55
 
32
56
  - **Путь, названный в документе, существует.** Ссылка на переехавший файл читается как
@@ -28,6 +28,27 @@ description: Правило под «Закон о правке сущности
28
28
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
29
29
  же дереве, которое держит код иначе.
30
30
 
31
+ ## Ход
32
+
33
+ Ход правки записи из панели: чем панель открывается, что происходит с мутацией и чем кончается
34
+ уход с панели.
35
+
36
+ ```mermaid
37
+ flowchart TD
38
+ A[Нужна панель создания или правки] --> B[Открывается маршрутом во вспомогательном аутлете]
39
+ B --> C[Запись читается по признаку из адреса полной моделью, а не берётся из списка]
40
+ C --> D[Панель наследует общую основу и отдаёт ей поток мутации]
41
+ D --> E{Мутация чем кончилась}
42
+ E -->|Значение| F[Список перечитывается, и только после этого работа считается сделанной]
43
+ E -->|Ошибка потока| G[Панель показывает отказ и остаётся открытой]
44
+ E -->|Пусто| H[Так не бывает: пустой поток гасит панель навсегда]
45
+ F --> I{Уход с панели}
46
+ G --> I
47
+ I -->|Есть несохранённые правки| J[Гард спрашивает — на всех путях закрытия сразу]
48
+ I -->|Нет| K[Уход идёт общим переходом к связанной записи, а не своим маршрутом]
49
+ J --> K
50
+ ```
51
+
31
52
  ## Как закон применяется здесь
32
53
 
33
54
  - **Асайд открывается маршрутом в аутлете `ro`, а не вызовом сервиса.** Программного открытия
@@ -28,6 +28,27 @@ description: Правило под «Закон о моделях сущност
28
28
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
29
29
  же дереве, которое держит код иначе.
30
30
 
31
+ ## Ход
32
+
33
+ Ход заведения модели: две стороны сущности, кто из них пишется руками и где стоит перевод между
34
+ ними.
35
+
36
+ ```mermaid
37
+ flowchart TD
38
+ A[Заводится модель записи] --> B[Обе стороны живут в одном неймспейсе имени сущности]
39
+ B --> C{Сторона контракта}
40
+ C -->|Объявляется псевдонимом сгенерированного типа| D[Руками не пишется: своя копия разойдётся молча]
41
+ D --> E[Между сторонами встаёт маппер-наследник общей основы]
42
+ E --> F{Значение пришло не в том виде}
43
+ F -->|Да| G[Приведение идёт способом маппера, а не подстановкой по умолчанию]
44
+ F -->|Нет| H[Экраны читают только сторону состояния]
45
+ G --> H
46
+ H --> I{Нужны страница, порядок или отбор}
47
+ I -->|Да| J[Типы берутся из общего набора: второго такого не заводится]
48
+ I -->|Нет| K[Пустое выражается пустой строкой или нулём, а не отсутствием поля]
49
+ J --> K
50
+ ```
51
+
31
52
  ## Как закон применяется здесь
32
53
 
33
54
  - **У сущности две стороны, и обе лежат в неймспейсе `I<Сущность>`.** `Api` повторяет
@@ -35,6 +35,30 @@ description: Правило под «Закон о поставке» для д
35
35
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
36
36
  же дереве, которое держит код иначе.
37
37
 
38
+ ## Ход
39
+
40
+ Ход работы от задачи до слияния: где стоит гард, что двигает колонку очереди работ и чем
41
+ работа кончается.
42
+
43
+ ```mermaid
44
+ flowchart TD
45
+ A[Работа начинается] --> B[Задача заводится командой и встаёт в очередь работ]
46
+ B --> C[Ветка называется номером задачи; колонка двигается тем же движением]
47
+ C --> D{Правка готова}
48
+ D -->|Нет| C
49
+ D -->|Да| E[Главная ветка влита, набор гейта прогнан целиком]
50
+ E --> F{Ветка несёт номер задачи}
51
+ F -->|Нет| G[Гард поставки отбивает открытие: за правкой ничего не стоит в очереди]
52
+ F -->|Да| H[PR открывается; не готовое к слиянию идёт черновиком]
53
+ H --> I[Колонка задачи переходит в разбор, исполнитель берёт следующую задачу]
54
+ I --> J{Прогон и разбор кончились}
55
+ J -->|Прогон красный| K[Чинится в той же ветке]
56
+ K --> J
57
+ J -->|Зелено| L[Папка задачи разбирается последним коммитом, черновик снимается]
58
+ L --> M[Слияние нажимает человек: исполнитель просит и называет номер]
59
+ G --> B
60
+ ```
61
+
38
62
  ## Как закон применяется здесь
39
63
 
40
64
  - **Коммит в главную ветку отбивается гардом.** Гард ищет вызов коммита в любом месте команды
@@ -48,6 +72,20 @@ description: Правило под «Закон о поставке» для д
48
72
  открытие, пока вершина главной ветки не стала предком текущей, и называет расхождение числом
49
73
  коммитов. PR с разошедшейся ветки показывает ревьюверу свою правку вперемешку с чужой, а всё,
50
74
  что автор проверил до публикации, он проверил от основания, которого в главной ветке уже нет.
75
+ - **Правка кода отдаётся человеку открытым PR, а не запушенной веткой.** Ветка в списке ветвей
76
+ ему не показывается, в его дела не приходит и обсуждения не имеет: до открытия PR правки для
77
+ человека нет. Открывается он тем же ходом, которым исполнитель говорит, что работу отдаёт, и
78
+ в ответе называется номером.
79
+ - **Не готовое к слиянию открывается черновиком — `az repos pr create --draft true`.** Кнопка
80
+ завершения у черновика заблокирована самим хостингом, поэтому состояние «выложено на
81
+ обозрение» и состояние «можно вливать» перестают выглядеть одинаково. Черновиком идёт всё,
82
+ что ждёт прогона конвейера, доработки или ответа на вопрос; вопрос задаётся в самом PR.
83
+ Конвейер проверок черновика по умолчанию не запускает — до снятия черновика он молчит, и это
84
+ молчание за зелёный прогон не принимается.
85
+ - **Черновик снимается отдельным вызовом — `az repos pr update --id <номер> --draft false`.**
86
+ Им исполнитель отвечает за готовность: проверки пройдены, доработок не осталось, работа
87
+ сходится с рабочим элементом. Снятие черновика и просьба влить — один ход, а не два разных
88
+ дня.
51
89
  - **Заведённый рабочий элемент подтверждается ответом очереди работ, а не выводом команды
52
90
  заведения.** Команда отвечает за свои вызовы: она может завести элемент и не довести его до
53
91
  доски, и её собственный разбор ошибок этот случай называет. Напечатанный номер значит «вызов
@@ -62,6 +100,17 @@ description: Правило под «Закон о поставке» для д
62
100
  элемент переводится в `Active`, PR открыт — в `Resolved`; делает это команда перевода, а не
63
101
  набор вызовов по памяти. Перевод идёт сразу за шагом, который его вызвал: очередь работ
64
102
  читают между шагами, а не после них.
103
+ - **На доске стоят рабочие элементы, а не PR о них.** Доска показывает, что сделано и что
104
+ осталось; PR отвечает на другой вопрос — как именно сделано, — и открывается из элемента, где
105
+ связь с ним стоит сама. Здесь эта связь ставится при создании PR, поэтому отдельная карточка
106
+ не нужна вовсе, а заведённая живёт своей жизнью: состояния под неё нет, из очереди она не
107
+ уходит и остаётся в ней после слияния навсегда. Находит такие сверка очереди — строкой на
108
+ каждую.
109
+ - **Конвейер судит по составу правки, а не гоняет всё подряд.** Шаги, которым нечего проверять,
110
+ пропускаются по признаку, посчитанному от главной ветки: ветка, не тронувшая ни строки кода,
111
+ не поднимает стенда, не снимает кадров и не собирает образов. Признак объявляется переменной
112
+ задания и считается один раз, а не переспрашивается в каждом условии. Пропущенный шаг виден в
113
+ прогоне пропущенным — молча выпавший читается как пройденный.
65
114
  - **Отставшее состояние находится сверкой очереди, а не глазами.** Сверка судит состояние по
66
115
  PR в обе стороны: открытый PR при элементе не в разборе и разбор без открытого PR — оба
67
116
  расхождения. Момента, когда задачу берут в работу, ей не видно: ветки на доске нет.
@@ -70,7 +119,7 @@ description: Правило под «Закон о поставке» для д
70
119
  въехала, и откатывается она целиком.
71
120
  - **Работа, которую одним заходом не закрыть, помечена в двух местах, и они сверяются.** Метка
72
121
  на доске и строка о заходах с передачей в замысле эпика говорят одно и то же двум читателям:
73
- исполнитель открывает карточку раньше, чем линию, а планирует по линии. Одна пометка без
122
+ исполнитель открывает карточку раньше, чем замысел эпика, а планирует по замыслу. Одна пометка без
74
123
  другой лжёт молча, поэтому сверка очереди судит пару в обе стороны. Помечается только то, что
75
124
  законно не делится: пометка объёма правом делить не становится.
76
125
  - **Слияние в главную ветку выкатывает прод.** Фильтры путей конвейера покрывают документы
@@ -119,6 +168,13 @@ description: Правило под «Закон о поставке» для д
119
168
  отбивает пуш, а не печатается рядом с ним: напечатанное предупреждение исполнитель читает как
120
169
  разрешение. Дважды подряд правка, прошедшая гейт целиком, была отбита конвейером — и оба раза
121
170
  зелёный гейт был прочитан как «локально всё зелено».
171
+ - **Сверка раскладки стоит в наборе гейта пуша наравне с линтом и сборкой.** Правка, положенная
172
+ в разложенную копию мимо источника, в день, когда её делают, не ломает ничего: дерево
173
+ работает, проверки зелёные, а расхождение видно только тому, кто позовёт сверку сам. Копится
174
+ оно молча и всплывает на чужой работе — раскладка отказывает по правленому файлу целиком и не
175
+ кладёт ни одного другого, так что цену платит тот, кто правил соседний ресурс. Статьёй выше
176
+ эта строка не покрывается: сверки нет в конвейере, а значит нет и шага, который она бы
177
+ закрывала, — в набор она ставится прямо, а не выводится из его полноты.
122
178
  - **После вливания главной ветки набор проверок пересматривается по тому, что ветка везёт
123
179
  теперь.** Вливание меняет состав правки: проверять по тому, что правил автор, — значит
124
180
  проверять половину, а отвечает ветка целиком. Ветка, не тронувшая ни строки показа, прогоняет
@@ -36,6 +36,30 @@ description: Правило под «Закон о поставке» для д
36
36
  переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
37
37
  же дереве, которое держит код иначе.
38
38
 
39
+ ## Ход
40
+
41
+ Ход работы от задачи до слияния: где стоит гард, что двигает колонку очереди работ и чем
42
+ работа кончается.
43
+
44
+ ```mermaid
45
+ flowchart TD
46
+ A[Работа начинается] --> B[Задача заводится командой и встаёт в очередь работ]
47
+ B --> C[Ветка называется номером задачи; колонка двигается тем же движением]
48
+ C --> D{Правка готова}
49
+ D -->|Нет| C
50
+ D -->|Да| E[Главная ветка влита, набор гейта прогнан целиком]
51
+ E --> F{Ветка несёт номер задачи}
52
+ F -->|Нет| G[Гард поставки отбивает открытие: за правкой ничего не стоит в очереди]
53
+ F -->|Да| H[PR открывается; не готовое к слиянию идёт черновиком]
54
+ H --> I[Колонка задачи переходит в разбор, исполнитель берёт следующую задачу]
55
+ I --> J{Прогон и разбор кончились}
56
+ J -->|Прогон красный| K[Чинится в той же ветке]
57
+ K --> J
58
+ J -->|Зелено| L[Папка задачи разбирается последним коммитом, черновик снимается]
59
+ L --> M[Слияние нажимает человек: исполнитель просит и называет номер]
60
+ G --> B
61
+ ```
62
+
39
63
  ## Как закон применяется здесь
40
64
 
41
65
  - **Коммит в главную ветку отбивается гардом.** Гард ищет вызов коммита в любом месте команды
@@ -72,6 +96,17 @@ description: Правило под «Закон о поставке» для д
72
96
  переставляется во взятые в работу, PR открыт — в ждущие разбора; делает это команда
73
97
  перевода, а не набор вызовов GraphQL по памяти. Перевод идёт сразу за шагом, который его
74
98
  вызвал: очередь работ читают между шагами, а не после них.
99
+ - **На борде стоят задачи, а не PR о них.** Борда показывает, что сделано и что осталось; PR
100
+ отвечает на другой вопрос — как именно сделано, — и открывается из карточки задачи, где связь
101
+ с ним заполняется сама полем «Linked pull requests». Карточка PR живёт своей жизнью: колонки
102
+ под неё нет, из очереди она не уходит и остаётся в ней после слияния навсегда. Заводится она
103
+ либо встроенным правилом борды, либо рукой; и то и другое выключается, а накопившееся
104
+ снимается. Находит их сверка очереди — строкой на каждую.
105
+ - **Конвейер судит по составу правки, а не гоняет всё подряд.** Шаги, которым нечего проверять,
106
+ пропускаются по признаку, посчитанному от главной ветки: ветка, не тронувшая ни строки кода,
107
+ не поднимает стенда, не снимает кадров и не собирает образов. Признак считается один раз и
108
+ объявляется выводом шага, а не переспрашивается в каждом условии. Пропущенный шаг виден в
109
+ прогоне пропущенным — молча выпавший читается как пройденный.
75
110
  - **Отставшая колонка находится сверкой очереди, а не глазами.** Сверка судит колонку по
76
111
  PR в обе стороны: открытый PR при задаче не в разборе и разбор без открытого PR — оба
77
112
  расхождения. Момента, когда задачу берут в работу, ей не видно: ветки на борде нет.
@@ -80,7 +115,7 @@ description: Правило под «Закон о поставке» для д
80
115
  откатывается она целиком.
81
116
  - **Работа, которую одним заходом не закрыть, помечена в двух местах, и они сверяются.** Метка
82
117
  на борде и строка о заходах с передачей в замысле эпика говорят одно и то же двум читателям:
83
- исполнитель открывает карточку раньше, чем линию, а планирует по линии. Одна пометка без
118
+ исполнитель открывает карточку раньше, чем замысел эпика, а планирует по замыслу. Одна пометка без
84
119
  другой лжёт молча, поэтому сверка очереди судит пару в обе стороны. Помечается только то, что
85
120
  законно не делится: пометка объёма правом делить не становится.
86
121
  - **Мерж в главную ветку выкатывает прод.** Исключения по путям покрывают только документы,
@@ -91,6 +126,12 @@ description: Правило под «Закон о поставке» для д
91
126
  умолчаниями, которые он разрешает. Умолчание образа задаётся в самом образе.
92
127
  - **Образы выкатываются по sha коммита, а не по метке «последний».** Метка в реестре отстаёт
93
128
  от главной ветки, и прод молча возвращается к прежней версии, продолжая отвечать.
129
+ - **Убирает за собой и та машина, которая образы собирает.** Отбор у обеих один — своё имя
130
+ реестра, три последних sha, поднятые контейнеры остаются, — и зовётся он одним сценарием:
131
+ разойдясь, две чистки начали бы оставлять разное, а заметить это нечем. Отличаются они
132
+ хвостом: сервер снимает следом висячие слои и кэш сборки, машина сборки оставляет их себе,
133
+ иначе каждая сборка идёт как первая. Чистка на сборке не ждёт мержа: образ ветки занимает
134
+ столько же места, в реестр не уезжает вовсе и точкой отката не бывает.
94
135
  - **Выкатка убирает за собой старые образы, оставляя три последних sha.** Помеченный sha образ
95
136
  висячим не бывает никогда, и чистка висячего его не касается: за полгода они съедают диск
96
137
  сервера целиком. Три sha — это глубина отката, и меньше брать нельзя: поломка, замеченная
@@ -107,6 +148,15 @@ description: Правило под «Закон о поставке» для д
107
148
  - **PR проверяется до мержа тем же конвейером, что и главная ветка.** Проверки и сборки
108
149
  образов идут на событии `pull_request`, выкатка — нет: её держит условие по главной ветке у
109
150
  своего задания, а образ PR в реестр не уезжает.
151
+ - **Вершина открытого PR без прогона видна сверкой очереди работ.** Страница PR без прогона
152
+ выглядит так же, как страница с зелёным: цвета у неё нет ни там, ни там, — и вершину, за
153
+ которой прогон не встал, замечали только тем, что открывали список прогонов руками. Сверка
154
+ спрашивает вершину, а не ветку, считает сам факт прогона, а не его цвет, и свежей вершине
155
+ даёт время: между пушем и прогоном проходят минуты.
156
+ - **Черновик при зелёном прогоне на вершине — расхождение сверки.** У черновика кнопка слияния
157
+ заблокирована самим хостингом: зелёная страница PR владельцу ничего не разрешает, а список, в
158
+ котором всё серое, читается как «работа не сделана». Гард снятия черновика сюда не достаёт —
159
+ он судит один ход и молчит, пока ветка везёт папку своей задачи.
110
160
  - **Расхождение прода с главной веткой видно сверкой очереди работ.** Задача уходит из очереди
111
161
  мержем, но мерж — ещё не прод: отказавшая выкатка не трогает ни задачу, ни её колонку, и
112
162
  заметить её неоткуда. Сверка спрашивает последний прогон главной ветки и судит только
@@ -129,6 +179,13 @@ description: Правило под «Закон о поставке» для д
129
179
  отбивает пуш, а не печатается рядом с ним: напечатанное предупреждение исполнитель читает как
130
180
  разрешение. Дважды подряд правка, прошедшая гейт целиком, была отбита конвейером — и оба раза
131
181
  зелёный гейт был прочитан как «локально всё зелено».
182
+ - **Сверка раскладки стоит в наборе гейта пуша наравне с линтом и сборкой.** Правка, положенная
183
+ в разложенную копию мимо источника, в день, когда её делают, не ломает ничего: дерево
184
+ работает, проверки зелёные, а расхождение видно только тому, кто позовёт сверку сам. Копится
185
+ оно молча и всплывает на чужой работе — раскладка отказывает по правленому файлу целиком и не
186
+ кладёт ни одного другого, так что цену платит тот, кто правил соседний ресурс. Статьёй выше
187
+ эта строка не покрывается: сверки нет в конвейере, а значит нет и шага, который она бы
188
+ закрывала, — в набор она ставится прямо, а не выводится из его полноты.
132
189
  - **После вливания главной ветки набор проверок пересматривается по тому, что ветка везёт
133
190
  теперь.** Вливание меняет состав правки: проверять по тому, что правил автор, — значит
134
191
  проверять половину, а отвечает ветка целиком. Ветка, не тронувшая ни строки показа, прогоняет
@@ -138,10 +195,21 @@ description: Правило под «Закон о поставке» для д
138
195
  сломана, она описывает вчерашний день. Сравнение веток пишется от `origin/main` целиком —
139
196
  смешав в одной команде удалённую ссылку для одной стороны и локальную для другой, промах
140
197
  изнутри выглядит правильным.
198
+ - **Правка кода отдаётся человеку открытым PR, а не запушенной веткой.** Ветка в списке ветвей
199
+ ему не показывается, во входящие не приходит и обсуждения не имеет: до открытия PR правки
200
+ для человека нет. Открывается он тем же ходом, которым исполнитель говорит, что работу
201
+ отдаёт, и в ответе называется номером.
202
+ - **Не готовое к слиянию открывается черновиком — `gh pr create --draft`.** Кнопка слияния у
203
+ черновика заблокирована самим хостингом, поэтому состояние «выложено на обозрение» и
204
+ состояние «можно вливать» перестают выглядеть одинаково. Черновиком идёт всё, что ждёт
205
+ прогона конвейера, доработки или ответа на вопрос; вопрос задаётся в самом PR.
206
+ - **Черновик снимается отдельным вызовом — `gh pr ready <номер>`.** Им исполнитель отвечает за
207
+ готовность: проверки пройдены, доработок не осталось, работа сходится с задачей. Снятие
208
+ черновика и просьба влить — один ход, а не два разных дня.
141
209
  - **Мерж PR нажимает человек, а не исполнитель работы.** Кнопка и вызов слияния равны: запрет
142
210
  на них один. Исполнитель сливает свой PR только тогда, когда человек сказал это прямо и про
143
211
  этот PR; сказанное об одном PR на следующий не переносится, а молчание разрешением не
144
- бывает. Работа кончается открытым и зелёным PR, и в ответе называется его номер.
212
+ бывает. Работа кончается PR, с которого снят черновик, и в ответе называется его номер.
145
213
  - **Автор PR не может быть его ревьювером.** Запрос разбора на самого себя GitHub принимает и
146
214
  молча не создаёт — разбор при этом выглядит запрошенным.
147
215
  - **Метки, исполнитель и ревьювер PR ставятся вызовами `gh api`, а не `gh pr edit`.** На
@@ -223,6 +291,16 @@ description: Правило под «Закон о поставке» для д
223
291
  список прогонов ветки смотрится тем же движением, что и пуш — `gh run list --branch <ветка>`.
224
292
  Один такой отказ простоял в списке до мержа, и на него никто не посмотрел: выкатка после
225
293
  мержа отказала ровно тем же.
294
+ - **Прогон, не вставший на пуш, возвращается повтором события, а не разбором ветки.** Замером
295
+ проверены обе законные дороги: и открытие PR, и пуш в уже открытый PR прогон заводят —
296
+ текстовый коммит и учётная запись, которой пушат, тут ни при чём. Пропавшие события пришлись
297
+ на час, когда хостинг отвечал `429` на загрузке действия и `503` на API, а списком прогонов
298
+ «не завёлся» от «не создан» не отличить. Поэтому вершину без прогона называет сверка очереди
299
+ работ, а событие возвращается новым коммитом либо перезакрытием PR.
300
+ - **Красное на шаге подготовки задания — отказ хостинга, а не дефект ветки.** Раннер не смог
301
+ скачать действие чекаута и получил `429 Too Many Requests`; до кода прогон при этом не дошёл
302
+ вовсе. Лечится перезапуском прогона, и от красного по существу отличается тем, на каком шаге
303
+ оно встало: три прогона одного дня упали именно так.
226
304
  - **Контекст `runner` в `env` задания отбивает весь файл конвейера.** Там доступны только
227
305
  `github`, `needs`, `strategy`, `matrix`, `vars`, `secrets` и `inputs`; `runner` появляется на
228
306
  уровне шага, где то же значение приходит переменной окружения. Такой файл не принимается
@@ -233,6 +311,15 @@ description: Правило под «Закон о поставке» для д
233
311
  пересечения нет, раннер стоит `online` и не берёт ничего, а задания уходят в облако — по
234
312
  состоянию это выглядит настроенным. Владельцу называют выполненное задание с его номером, а
235
313
  не строку состояния.
314
+ - **Раннер на своей машине делает прогон общим ресурсом, и стенд у прогонов один.** Порт,
315
+ имя базы и каталог сборки зашиты в дереве одним значением на всех: два прогона разом
316
+ поднимают два стенда на один порт, и второй падает целиком. Дороже всего не падение, а его
317
+ вид — в отчёте оно выглядит десятком красных спек про экраны, то есть дефектом правки,
318
+ которого нет; три прогона подряд так и упали на трёх ветках, не тронувших кода. Лечится с
319
+ двух сторон сразу: конвейеру объявляется группа очереди на всё дерево, а имена стенда
320
+ читаются из окружения с нынешними значениями в умолчании — иначе прогон и гейт пуша, зовущий
321
+ ту же команду, столкнутся и при очереди. Одной очереди мало, одних имён — тоже: прогоны делят
322
+ ещё диск, кэш сборщика и демон образов.
236
323
  - **Вход в реестр образов из раннера, запущенного службой, отказывает молча.** Служба идёт без
237
324
  сеанса пользователя, а клиент реестра уходит в системный помощник хранения ключей и получает
238
325
  отказ во взаимодействии — задание падает до сборки. Свой каталог настроек с пустым помощником