@rt-tools/agent-kit 0.11.0 → 0.12.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 (115) hide show
  1. package/assets/checks/check-file-size.mjs +19 -4
  2. package/assets/checks/check-state-next.mjs +10 -2
  3. package/assets/checks/rt-kit-checks.config.mjs +16 -2
  4. package/assets/defaults/project.sh +9 -1
  5. package/assets/defaults/turn-map.md +8 -6
  6. package/assets/hooks/browser-guard-device-id.sh +3 -1
  7. package/assets/hooks/browser-guard-no-asking.sh +3 -1
  8. package/assets/hooks/browser-guard-no-other-drivers.sh +5 -3
  9. package/assets/hooks/browser-guard-require-select.sh +4 -2
  10. package/assets/hooks/claim-guard.sh +3 -1
  11. package/assets/hooks/conscience-guard.sh +3 -1
  12. package/assets/hooks/dev-server-guard.sh +5 -3
  13. package/assets/hooks/dispatch.sh +69 -0
  14. package/assets/hooks/docs-guard.sh +6 -4
  15. package/assets/hooks/exam-guard.sh +5 -3
  16. package/assets/hooks/git-guard-delivery.sh +37 -5
  17. package/assets/hooks/git-guard-main.sh +6 -4
  18. package/assets/hooks/git-guard-push-tests.sh +6 -4
  19. package/assets/hooks/grill-gate.sh +4 -2
  20. package/assets/hooks/handoff-entry-guard.sh +4 -2
  21. package/assets/hooks/handoff-write.sh +27 -6
  22. package/assets/hooks/hook-input.sh +54 -0
  23. package/assets/hooks/lint-after-edit.sh +5 -3
  24. package/assets/hooks/postmortem-guard.sh +3 -1
  25. package/assets/hooks/proposal-guard.sh +3 -1
  26. package/assets/hooks/prose-style-guard.sh +5 -3
  27. package/assets/hooks/qa-dataid-guard.sh +4 -2
  28. package/assets/hooks/rerun-guard.sh +5 -3
  29. package/assets/hooks/reuse-first-guard.sh +5 -3
  30. package/assets/hooks/rule-article.sh +99 -0
  31. package/assets/hooks/skill-gate-rearm.sh +3 -1
  32. package/assets/hooks/skill-gate.sh +23 -2
  33. package/assets/hooks/skill-loaded.sh +3 -1
  34. package/assets/hooks/sql-guard-request.sh +2 -1
  35. package/assets/hooks/sql-guard.sh +4 -2
  36. package/assets/hooks/task-flow-guard.sh +6 -4
  37. package/assets/hooks/turn-exit-guard.sh +42 -17
  38. package/assets/hooks/waiting-turn-guard.sh +3 -1
  39. package/assets/hooks/window-fill-guard.sh +6 -4
  40. package/assets/laws/work-conduct.md +5 -9
  41. package/assets/patterns/dependencies-upgrade.md +1 -1
  42. package/assets/patterns/doc-style-write.md +3 -3
  43. package/assets/patterns/git-workflow-commit.azure.md +2 -202
  44. package/assets/patterns/git-workflow-commit.github.md +2 -258
  45. package/assets/patterns/git-workflow-commit.gitlab.md +1 -217
  46. package/assets/patterns/git-workflow-docker.md +3 -3
  47. package/assets/patterns/git-workflow-merge.md +3 -2
  48. package/assets/patterns/git-workflow-migration.md +3 -3
  49. package/assets/patterns/git-workflow-pr.azure.md +224 -0
  50. package/assets/patterns/git-workflow-pr.github.md +280 -0
  51. package/assets/patterns/git-workflow-pr.gitlab.md +240 -0
  52. package/assets/patterns/git-workflow-restart.md +3 -3
  53. package/assets/patterns/git-workflow-secrets.md +3 -3
  54. package/assets/patterns/task-flow-archive.md +193 -0
  55. package/assets/patterns/task-flow-close.md +3 -173
  56. package/assets/patterns/task-flow-handoff.md +4 -4
  57. package/assets/pitfalls/doc-style.md +80 -0
  58. package/assets/pitfalls/git-workflow.azure.md +50 -0
  59. package/assets/pitfalls/git-workflow.github.md +78 -0
  60. package/assets/pitfalls/git-workflow.gitlab.md +49 -0
  61. package/assets/pitfalls/spec-driven.md +36 -0
  62. package/assets/pitfalls/styling-bem.md +45 -0
  63. package/assets/pitfalls/task-flow.md +62 -0
  64. package/assets/pitfalls/testing.md +70 -0
  65. package/assets/rules/deploy-flow.azure.md +106 -0
  66. package/assets/rules/deploy-flow.github.md +113 -0
  67. package/assets/rules/deploy-flow.gitlab.md +108 -0
  68. package/assets/rules/doc-style.md +25 -76
  69. package/assets/rules/git-workflow.azure.md +6 -92
  70. package/assets/rules/git-workflow.github.md +14 -127
  71. package/assets/rules/git-workflow.gitlab.md +6 -93
  72. package/assets/rules/spec-driven.md +39 -30
  73. package/assets/rules/styling-bem.md +20 -39
  74. package/assets/rules/task-flow.md +17 -199
  75. package/assets/rules/testing.md +3 -64
  76. package/assets/rules/turn-conduct.md +206 -0
  77. package/assets/rules/typescript-conventions.md +15 -0
  78. package/assets/skills/agent-kit.md +35 -12
  79. package/assets/templates/pitfalls.md +10 -0
  80. package/assets/templates/rule.md +5 -3
  81. package/bin/agent-kit.d.ts.map +1 -1
  82. package/bin/agent-kit.js +1 -42
  83. package/bin/agent-kit.js.map +1 -1
  84. package/lib/assets.d.ts.map +1 -1
  85. package/lib/assets.js +6 -1
  86. package/lib/assets.js.map +1 -1
  87. package/lib/cascade.d.ts.map +1 -1
  88. package/lib/cascade.js +19 -1
  89. package/lib/cascade.js.map +1 -1
  90. package/lib/commands.d.ts.map +1 -1
  91. package/lib/commands.js +1 -0
  92. package/lib/commands.js.map +1 -1
  93. package/lib/config.d.ts +16 -1
  94. package/lib/config.d.ts.map +1 -1
  95. package/lib/config.js +8 -0
  96. package/lib/config.js.map +1 -1
  97. package/lib/hooks-map.d.ts +13 -0
  98. package/lib/hooks-map.d.ts.map +1 -1
  99. package/lib/hooks-map.js +33 -1
  100. package/lib/hooks-map.js.map +1 -1
  101. package/lib/ship.d.ts +1 -2
  102. package/lib/ship.d.ts.map +1 -1
  103. package/lib/ship.js +0 -54
  104. package/lib/ship.js.map +1 -1
  105. package/package.json +1 -1
  106. package/rt-tools-agent-kit-0.12.0.tgz +0 -0
  107. package/assets/commands/agent-kit-digest.md +0 -89
  108. package/assets/commands/rules-review.md +0 -98
  109. package/assets/patterns/cargo-triage-mark.md +0 -119
  110. package/assets/rules/cargo-triage.md +0 -126
  111. package/lib/cargo-state.d.ts +0 -62
  112. package/lib/cargo-state.d.ts.map +0 -1
  113. package/lib/cargo-state.js +0 -118
  114. package/lib/cargo-state.js.map +0 -1
  115. package/rt-tools-agent-kit-0.11.0.tgz +0 -0
@@ -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, git-workflow-docker и git-workflow-secrets.
5
+ description: Правило под «Закон о поставке» для дерева на GitLab. Брать на заведение задачи, ветки, коммит, пуш, создание MR, слияние, а также на правку схемы хранилища, её миграций и вызовы миграций. Называет задачу на борде как начало работы, колонку задачи как ход работы, соответствие задачи и ветки один к одному, имя ветки, формат коммита, учётную запись машинной работы, обязательный состав MR, гарды поставки и сверку очереди работ. Готовый код — в паттернах git-workflow-commit, git-workflow-pr, git-workflow-merge. Выкатка, образы и миграции — правило deploy-flow.
6
6
  ---
7
7
 
8
8
  # Поставка — как это устроено здесь
@@ -12,6 +12,9 @@ description: Правило под «Закон о поставке» для д
12
12
  учётная запись машинной работы и области коммита — при этом дереве, в `implementation.md`
13
13
  рядом: их не угадать, и общими они не бывают.
14
14
 
15
+ **Холодная часть:** `pitfalls.md` рядом — ловушки, грабли, на которые уже наступали.
16
+ Грузится по требованию, а не вместе с правилом.
17
+
15
18
  ## Как это называется здесь
16
19
 
17
20
  | В законе | Здесь |
@@ -23,9 +26,6 @@ description: Правило под «Закон о поставке» для д
23
26
  | состояние задачи в очереди работ | список доски, за которым стоит метка: заведённая, взятая в работу, ждущая разбора. Имена меток — в `implementation.md`; закрытая задача уходит из очереди слиянием, а не переносом в последний список |
24
27
  | PR о задаче | заголовок MR `[<КЛЮЧ>-<номер>] <Что сделано>` — тот же номер, что у задачи, и её название, переведённое в сделанное; тип и область коммита сюда не идут |
25
28
  | обсуждение правки | разбор MR: ревьювер — владелец проекта, исполнитель — учётная запись машинной работы, метки — те же, что у задачи |
26
- | попадание правки в главную ветку | слияние MR; оно же запускает выкатку — `.gitlab-ci.yml` |
27
- | образ того коммита | `IMAGE_TAG=<sha>` в командах `docker compose` на сервере |
28
- | изменение хранилища | миграция в `prisma/migrations/<метка>_<имя>/` |
29
29
  | запись о правке | коммит формата `type(scope): description` — типы `feat`, `fix`, `refactor`, `docs`, `style`, `test`, `chore`, `perf`; области — в `implementation.md` |
30
30
  | автор машинной работы | отдельная учётная запись; её имя и место токена — в `implementation.md`. Токен лежит вне репозитория |
31
31
 
@@ -130,12 +130,6 @@ flowchart TD
130
130
  остаётся в ней после слияния навсегда. Здесь она заводится проще, чем где-либо: доска
131
131
  собирается по меткам, и метка списка, поставленная на MR, тут же делает его карточкой.
132
132
  Находит такие сверка очереди — строкой на каждую.
133
- - **Конвейер судит по составу правки, а не гоняет всё подряд.** Шаги, которым нечего проверять,
134
- пропускаются по признаку, посчитанному от главной ветки: ветка, не тронувшая ни строки кода,
135
- не поднимает стенда, не снимает кадров и не собирает образов. Правила `rules:changes` считают
136
- это сами, но по путям, а не по составу правки — совпадение пути ещё не значит, что задета
137
- сборка, поэтому признак объявляется явно и один раз. Пропущенный шаг виден в прогоне
138
- пропущенным — молча выпавший читается как пройденный.
139
133
  - **Отставший список находится сверкой очереди, а не глазами.** Сверка судит список по PR
140
134
  в обе стороны: открытый MR при задаче не в разборе и разбор без открытого MR — оба
141
135
  расхождения. Момента, когда задачу берут в работу, ей не видно: ветки на доске нет.
@@ -147,37 +141,6 @@ flowchart TD
147
141
  исполнитель открывает карточку раньше, чем замысел эпика, а планирует по замыслу. Одна пометка без
148
142
  другой лжёт молча, поэтому сверка очереди судит пару в обе стороны. Помечается только то, что
149
143
  законно не делится: пометка объёма правом делить не становится.
150
- - **Слияние в главную ветку выкатывает прод.** Правила `only`/`rules` конвейера покрывают
151
- документы отдельно, поэтому переменные окружения, секреты и записи имён ставятся до слияния,
152
- а не после.
153
- - **Признак режима объявлен в образе, а не только в составе прода.** Значение, заданное
154
- составом, действует лишь на контейнер, поднятый этим составом; ручной прогон того же образа
155
- идёт с пустым значением, а пусто здесь означает локалхост — со всеми отладочными
156
- умолчаниями, которые он разрешает. Умолчание образа задаётся в самом образе.
157
- - **Образы выкатываются по sha коммита, а не по метке «последний».** Метка в реестре отстаёт
158
- от главной ветки, и прод молча возвращается к прежней версии, продолжая отвечать.
159
- - **Выкатка убирает за собой старые образы, оставляя три последних sha.** Помеченный sha образ
160
- висячим не бывает никогда, и чистка висячего его не касается: за полгода они съедают диск
161
- сервера целиком. Три sha — это глубина отката, и меньше брать нельзя: поломка, замеченная
162
- через две выкатки, откатывается уже некуда.
163
- - **Описание прода правится вместе с составом прода.** Устройство, путь запроса, гейты и
164
- бэкапы описаны текстами вне слоёв правил, и ни линтер, ни сборка их не читают: расхождение
165
- копится молча, а читают эти тексты как действующие. Пару стережёт гард документов.
166
- - **Правка конвейера прогоняется до слияния ручным запуском.** Конвейер запускается на любой
167
- ветке, а задание выкатки прибито правилом к главной: прогон ради проверки доходит до сборок и
168
- там кончается. Прогон команд задания на своей машине его не покрывает: он проверяет команды,
169
- а не файл конвейера, — верность самого файла читается только по списку конвейеров после
170
- пуша, и синтаксис отдельно судит проверка `.gitlab-ci.yml` в проекте.
171
- - **PR проверяется до слияния тем же конвейером, что и главная ветка.** Проверки и сборки
172
- образов идут на конвейере запроса слияния, выкатка — нет: её держит правило по главной ветке
173
- у своего задания, а образ PR в реестр не уезжает.
174
- - **Расхождение прода с главной веткой видно сверкой очереди работ.** Задача уходит из очереди
175
- слиянием, но слияние — ещё не прод: отказавшая выкатка не трогает ни задачу, ни её список, и
176
- заметить её неоткуда. Сверка спрашивает последний конвейер главной ветки и судит только
177
- завершённый: идущий ещё может кончиться выкаткой.
178
- - **Цепочка миграций прогоняется с пустого хранилища до слияния.** Порядок применения
179
- лексикографический по имени каталога, а метку времени ставит момент создания: миграция из
180
- ветки, начатой раньше, встаёт перед той, от которой зависит.
181
144
  - **Документ едет в том же коммите, что и правка.** Обход — строка `Docs-skip: <причина>` в
182
145
  теле коммита; пустая причина не принимается.
183
146
  - **Заголовок коммита сверяется с форматом на месте.** Разобранный по типу и области
@@ -222,10 +185,6 @@ flowchart TD
222
185
  репозитории сценария наследует общий конфиг: если включена подпись, git идёт в агент ключей,
223
186
  а заблокированный агент роняет весь набор — со стороны это выглядит сломанным гардом. Автор,
224
187
  почта и подпись передаются флагами `-c` прямо в команду.
225
- - **Расхождение миграций со схемой меряется на теневом хранилище, а не на том, где работает
226
- тот, кто пушит.** Оно законно несёт след любой недоделанной ветки, и сверка с ним держала бы
227
- чужую правку. Гейт и выкатка зовут одну и ту же проверку — иначе «сошлось» станет значить в
228
- двух местах разное.
229
188
 
230
189
  ## Чего из закона здесь нет
231
190
 
@@ -248,52 +207,6 @@ flowchart TD
248
207
 
249
208
  ## Паттерны
250
209
 
251
- - `git-workflow-commit` — задача, ветка, коммит, пуш и MR от учётной записи машинной работы.
210
+ - `git-workflow-commit` — задача, ветка, коммит и пуш от учётной записи машинной работы.
211
+ - `git-workflow-pr` — открытие MR, черновик и его снятие, описание, ревьювер, метки, состояние.
252
212
  - `git-workflow-merge` — главная ветка влита в ветку задачи, конфликт разобран.
253
- - `git-workflow-migration` — правка схемы хранилища и её миграций.
254
- - `git-workflow-restart` — ручной перезапуск прода.
255
- - `git-workflow-docker` — образы на своей машине: демон, реестр, сборка под платформу сервера.
256
- - `git-workflow-secrets` — ключи внешних служб: где лежат, как заводятся, что говорит их состояние.
257
-
258
- ## Ловушки
259
-
260
- - **Одна работа — одна задача, сколько бы файлов она ни задела.** Числа, за которым правка
261
- становится второй задачей, здесь нет: делится то, что придётся откатывать порознь. Сплошная
262
- правка текстов дерева была заведена тремя задачами «по объёму» — пришлось стирать две,
263
- закрывать два MR и переносить коммиты по одному с двумя конфликтами. Одна из трёх не дала
264
- коммита вовсе: правка тел уже заведённых задач веткой не бывает и задачей под ветку тоже.
265
- - **Задача заводится командой, а не вызовами подряд.** Доска показывает те issue, чью метку
266
- знает, и задача без метки списка в очереди работ не видна: со стороны это выглядит так же, как
267
- незаведённая. Команда заведения ставит всё разом — issue, номер в его заголовке, метку списка,
268
- исполнителя, — и печатает готовую строку заведения ветки. Замеченный по ходу дефект проходит
269
- тот же путь.
270
- - **Ветка заводится вторым вызовом, а не тем же.** Гард главной ветки отклоняет составную
271
- «создать ветку и сразу коммитить» целиком: ветки в момент разбора ещё нет.
272
- - **Сторона конфликта бывает удалением, и «сохранить обе стороны» заводит второе объявление.**
273
- Главная ветка снимает объявление, потому что символ переехал, — в конфликте это выглядит как
274
- сторона, которая ничего не дописала. Разбирается чтением версии главной ветки целиком, а не по
275
- хунку, и сверяется проверкой повторов: обе копии сами по себе исправны, сборка и линт зелёные.
276
- - **Учётная запись для пуша и автор MR выбираются отдельно.** Если пушить пришлось из-под другой
277
- записи, на следующий вызов это не переносится: MR открывают токеном учётной записи машинной
278
- работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
279
- смена записи ради пуша утекла в публикацию — PR вышел от владельца.
280
- - **Невалидный файл конвейера виден отказом сразу после пуша, а не упавшим заданием.** Конвейер
281
- на такой файл не заводится вовсе: в списке стоит запись об ошибке разбора, а внутри нет ни
282
- задания, ни лога. Поэтому список конвейеров ветки смотрится тем же движением, что и пуш —
283
- `glab ci list --branch <ветка>`, — а сам файл до пуша судит проверка `.gitlab-ci.yml` в
284
- проекте.
285
- - **`online` у раннера на своей машине означает запущенный процесс, а не работающий
286
- конвейер.** Две стороны сходятся отдельно: `tags` у заданий и теги самого раннера. Пока
287
- пересечения нет, раннер стоит `online` и не берёт ничего, а задания ждут общего раннера — по
288
- состоянию это выглядит настроенным. Владельцу называют выполненное задание с его номером, а
289
- не строку состояния.
290
- - **Вход в реестр образов из раннера, запущенного службой, отказывает молча.** Служба идёт без
291
- сеанса пользователя, а клиент реестра уходит в системный помощник хранения ключей и получает
292
- отказ во взаимодействии — задание падает до сборки. Свой каталог настроек с пустым помощником
293
- не спасает: клиент переписывает пустое значение обратно сам. Готовые команды — паттерн
294
- `git-workflow-docker`.
295
- - **Новое рабочее дерево получает только то, что лежит в индексе.** `git worktree add`
296
- разворачивает коммит, а настройки, ключи, локальные разрешения и зависимости в коммит не
297
- входят: свежее дерево выглядит готовым и упирается в нехватку не сразу, а на первом гарде,
298
- которому нужен ключ. Что именно переносится руками, названо списком в компаньоне правила, и
299
- список пополняется тем же движением, которым заводится новый файл вне индекса.
@@ -11,6 +11,9 @@ description: Правило под «Закон о документации пр
11
11
  быть верно про тексты; здесь — из каких слоёв они сложены в этом дереве и что сверяет машина.
12
12
  Формулировки — правило `doc-style` под тем же законом.
13
13
 
14
+ **Холодная часть:** `pitfalls.md` рядом — ловушки, грабли, на которые уже наступали.
15
+ Грузится по требованию, а не вместе с правилом.
16
+
14
17
  ## Как это называется здесь
15
18
 
16
19
  ```
@@ -21,6 +24,7 @@ description: Правило под «Закон о документации пр
21
24
  ├─ ПРАВИЛО .claude/skills/<правило>/SKILL.md (kind: rule, law: <закон>)
22
25
  │ привязывает закон к этому проекту; несколько правил на закон
23
26
  │ .claude/skills/<правило>/implementation.md — привязка к коду
27
+ │ .claude/skills/<правило>/pitfalls.md — холодная часть: грузится по требованию
24
28
 
25
29
  │ └─ ПАТТЕРН .claude/skills/<правило>-<что>/SKILL.md (kind: pattern, rule: <правило>)
26
30
  │ готовый код и конкретные приёмы; минимум один на правило
@@ -125,6 +129,13 @@ flowchart TD
125
129
  - **Слоёв законов два, а имя закона одно на оба.** Общий лежит в корне конституции, закон
126
130
  приложения — в `application/`; ни `law:`, ни `**Законы:**` слоя не называют, поэтому имена
127
131
  законов уникальны по всему дереву конституции.
132
+ - **У правила бывает третий файл, и в него уходит то, что при решении не читают.** Ловушки и
133
+ поведение по разборам происшествий нужны не тому, кто принимает обычное решение, а тому, кто
134
+ разбирает промах или спорит с гардом, — а грузятся они вместе с правилом каждый раз и растут
135
+ быстрее статей. Такой текст уезжает в `pitfalls.md` рядом, правило называет его строкой в
136
+ шапке, и грузится он по требованию. Отказ гейта о холодной части молчит: он зовёт правило, а о
137
+ третьем файле говорит само правило.
138
+
128
139
  - **Спек объявляет законы, которые применяет, и связь сверяется в обе стороны.** Закон,
129
140
  названный в тексте спека, обязан стоять в шапке: иначе по закону не узнать, какие домены
130
141
  на нём стоят.
@@ -134,6 +145,28 @@ flowchart TD
134
145
  про дерево, где того гарда не разложили; поправить это дерево не может ничем, если у ресурса
135
146
  нет надстройки. Требование ресурса к ресурсу при этом объявляется строкой в шапке, а не
136
147
  выводится из такой фразы.
148
+ - **Статья правила говорит о своей применимости сама, строкой признака при себе.** Отказ гейта
149
+ зовёт правило целиком, а под конкретную правку подпадает одна его статья: платить за решение
150
+ полной ценой правила — значит учить не читать лишнего, то есть работать хуже разведанным.
151
+ Признак стоит при статье, а не в карте гейта: карта знает путь и правило, но не знает, какая
152
+ из двух десятков статей про этот путь.
153
+
154
+ ```markdown
155
+ - **Заголовок статьи.** Текст статьи, как обычно.
156
+ <!-- rt-when: *.scss *.css -->
157
+ ```
158
+
159
+ Образцы разделены пробелом и сверяются с путём правки как образцы оболочки, а не поиском по
160
+ словам: поиск называет не ту статью и молчит об этом. Образец без каталога сверяется и с
161
+ именем файла. Комментарий не виден в собранной разметке, поэтому статья читается человеком
162
+ как прежде.
163
+
164
+ - **Статья без признака законна, и правило без единого признака — тоже.** Признак ставится тем
165
+ статьям, чьё правило отбивает на правке файла; остальные размечаются по мере того, как их
166
+ отбития попадут в сводку. Отсутствие признака означает «эту статью по пути правки не
167
+ выбирают», а не промах: требовать его у всех значило бы размечать наугад те правила, которые
168
+ ни разу никого не отбили.
169
+
137
170
  - **Паттерн находится по полю `rule:`, а не по приставке имени.** Приставку имени несут не все
138
171
  паттерны, и поиск по имени правила таких не видит: сверка ищет их полем, человек — разделом
139
172
  «Паттерны» самого правила. Счёт паттернов, собранный приставками, выходит меньше настоящего, а
@@ -161,6 +194,12 @@ flowchart TD
161
194
  доменов раньше, чем код научился в него приходить, и всё это время читалось описанием
162
195
  работающего.
163
196
 
197
+ Полноту разметки статей признаком применимости не считает ничто. Правило, у которого признака
198
+ нет ни у одной статьи, отбивает прежним текстом — и от размеченного отличается только тем, что
199
+ исполнитель читает его целиком; ни одна проверка об этом не говорит. Судит это сводка
200
+ наблюдений: правило, которое чаще прочего отбивает на правке файла, и есть первое, что
201
+ размечают.
202
+
164
203
  Полноту разделов у самого закона, правила и паттерна здесь не проверяет ничто. Статьи о том,
165
204
  что текст судится не слабее своей копии, что невыбранная редакция судится наравне с выбранной и
166
205
  что набор разделов объявлен отдельно от образца, исполняются там, где эти тексты пишут, — в
@@ -172,33 +211,3 @@ flowchart TD
172
211
 
173
212
  - `spec-driven-domain` — заведение и правка спека домена, сценарии, привязка.
174
213
  - `spec-driven-rule` — заведение закона, правила и паттерна.
175
-
176
- ## Ловушки
177
-
178
- - **`tasks.md` в спеке не заводить.** Шаги — артефакт сессии, им место в ветке или в описании
179
- PR. Как только в директории появляются «шаги», спек снова становится планом и умирает после
180
- мержа.
181
- - **Спек описывает установившееся, а не предстоящее.** Единственное место, где он говорит о
182
- будущем, — `proposed/<фича>/`. После выкатки его текст вливается в спек домена, директория
183
- удаляется, идентификаторы сценариев не меняются.
184
- - **Семантику полей не сверяет ничто.** Проверка знает имена процедур, коды отказа и связь
185
- сценариев с тестами; что означает пустое поле — не знает. Правка `.proto` поэтому тянет
186
- спеки всех доменов, чьи процедуры она задела, в той же ветке.
187
- - **Живость символа считается совпадением имени по всему дереву, а не вызовом.** Символу
188
- хватает второго упоминания где угодно — в чужом поле с тем же именем, в атрибуте разметки.
189
- Место, где правило исполняется на самом деле, подтверждается только чтением кода.
190
- - **Якорь в `tools/*.mjs` сверяется почти ничем:** живость считается только для `.ts`, а
191
- исходники обходятся по `apps`, `libs` и `prisma`. Правило, привязанное к проверке, поэтому
192
- читается вместе с её телом.
193
- - **Зелёная проверка не значит, что структура верна.** Спутники с привязкой сначала лежали
194
- рядом с законами, и проверка была зелёной именно потому, что структура совпадала с тем,
195
- чего проверка сама и ждала.
196
- - **Конфликт мержа в спеке разрешается сохранением обеих сторон, а не выбором одной.** Две
197
- ветки дописывают в конец одних и тех же списков — сценариев, правил, строк привязки, — и
198
- обе стороны верны: конфликт здесь не спор, а две дописи в одно место. Номера сценариев при
199
- разрешении не пересчитываются: идентификатор — ключ связи с тестами, и сдвиг номеров рвёт
200
- сверку у соседей, которых правка не касалась. Порядок сохранённых сторон держится
201
- одинаковым в `spec.md`, `scenarios.md` и `implementation.md`: иначе правило, его сценарий и
202
- его привязка перестают находиться друг по другу. После разрешения гоняется
203
- `npm run check:specs` — конфликт в спеке кода не задевает, и ни сборка, ни линтеры его не
204
- увидят.
@@ -12,6 +12,9 @@ description: Правило под «Закон о фронтовом прило
12
12
  `component-structure`, состояние — `angular-patterns`, окружение браузера —
13
13
  `platform-access`, слой обращения к серверу — `api-layer`. Все пять под одним законом.
14
14
 
15
+ **Холодная часть:** `pitfalls.md` рядом — ловушки, грабли, на которые уже наступали.
16
+ Грузится по требованию, а не вместе с правилом.
17
+
15
18
  ## Как это называется здесь
16
19
 
17
20
  | В законе | Здесь |
@@ -51,28 +54,45 @@ flowchart TD
51
54
  - **Оформление берётся токеном `--rt-*`, а не пишется значением на месте.** Составные
52
55
  значения — `box-shadow`, `text-shadow` — берутся готовым токеном целиком, а не собираются
53
56
  из частей.
57
+ <!-- rt-when: *.scss *.css -->
58
+
54
59
  - **У каждого класса элемента есть своё правило стилей.** Класс без правила выглядит рабочим
55
60
  и молча ничего не делает.
61
+ <!-- rt-when: *.scss *.css -->
62
+
56
63
  - **Класс ставится директивой, а не строкой в атрибуте.** Имя блока `rtElem` получает
57
64
  инъекцией от ближайшего предка с `rtBlock`, и повторить этот разбор по тексту шаблона нечем.
65
+ <!-- rt-when: *.html *.scss -->
66
+
58
67
  - **Раскладка объявлена в общем слое приложения, а не в стилях экрана.** У компонента экрана
59
68
  вне кита файл стилей по умолчанию пустой.
69
+ <!-- rt-when: *.scss *.css -->
70
+
60
71
  - **Шторку и окно открывает служба кита, а не номер слоя.** Числа шкалы сравниваются только
61
72
  между соседями по разметке; служба выносит разметку наружу, к `<body>`, и сравнивать её
62
73
  становится не с чем.
74
+ <!-- rt-when: *.ts *.scss -->
75
+
63
76
  - **Номер слоя берётся из шкалы, а не пишется числом в файле компонента.** Шкала — единственное
64
77
  место, где слои видно рядом: написанное на месте число в неё не попадает, и следующий узел
65
78
  занимает тот же номер, ничего об этом не узнав.
79
+ <!-- rt-when: *.scss *.css -->
80
+
66
81
  - **Размер элемента управления выбирается по признаку указателя, а не по ширине экрана.**
67
82
  Планшет в ландшафте шире порога узкого вьюпорта, а нажимают по нему пальцем: `pointer: coarse`
68
83
  отвечает про способ нажатия, ширина — про место под раскладку. Ступени берутся у кита, а не
69
84
  назначаются пикселями.
85
+ <!-- rt-when: *.scss *.css -->
86
+
70
87
  - **Файл стилей не длиннее 500 строк.** Предел общий с кодом и текстами, но stylelint длину не
71
88
  судит вовсе — держит его проверка дерева. Выросший файл экрана делится по блокам, а общая
72
89
  раскладка уходит в свой слой.
90
+ <!-- rt-when: *.scss *.css -->
91
+
73
92
  - **Предупреждение stylelint роняет прогон наравне с ошибкой.** `!important` объявлен
74
93
  предупреждением, а прогон идёт с `--max-warnings 0`: иначе запрет читается как пожелание —
75
94
  два таких предупреждения лежали в дереве, а `npm run stylelint` возвращал ноль и гейтом не был.
95
+ <!-- rt-when: *.scss *.css -->
76
96
 
77
97
  ## Чего из закона здесь нет
78
98
 
@@ -85,42 +105,3 @@ flowchart TD
85
105
  - `styling-bem-layout` — экран на общем слое раскладки, блоки приложения.
86
106
  - `styling-bem-component` — стили компонента кита, `:host`, модификаторы, язык оформления сайта.
87
107
  - `styling-bem-sheet` — шторка и окно поверх страницы: чем открываются, подложка, замер.
88
-
89
- ## Ловушки
90
-
91
- - **`rtElem` без предка с `rtBlock` роняет отрисовку в рантайме** — сборка и линт молчат.
92
- - **Спроецированный узел блока-предка не имеет.** `rtElem` берёт имя блока инъекцией от
93
- ближайшего предка **по месту объявления шаблона**, а не по месту вставки: элемент, который
94
- экран объявляет у себя и отдаёт в проекцию чужого компонента, ищет `rtBlock` в своём шаблоне
95
- и не находит. Отрисовка падает в рантайме, сборка и линт зелёные. Класс на такой узел
96
- вешается правилом по селектору кита в общем слое раскладки, а не директивой.
97
- - **Элемент с `backdrop-filter` или своим `z-index` замыкает потомков в свой слой.** Липкая
98
- шапка с размытием — самый частый случай: номер слоя у того, что лежит внутри неё,
99
- сравнивается не с соседями по странице, а только с соседями внутри шапки, и нижняя панель
100
- накрывает открытую шторку вместе с её кнопкой. Проверяется это `elementFromPoint` в центре
101
- кнопки: сборка, линт и скриншот показывают тут целую страницу.
102
- - **До узла, вынесенного к `<body>`, стили компонента не достают.** Превью и заглушку переноса
103
- кладёт туда библиотека, а правила компонента заскоуплены атрибутом: файл выглядит рабочим и
104
- не красит ничего. Такие правила объявляются в общем слое приложения. Ни сборка, ни линт, ни
105
- проверка «класс без правила» этого не видят: класса такого в шаблоне нет вовсе, и пролежать
106
- это может несколько задач подряд.
107
- - **Имя токена не сверяется ничем.** Ссылка на несуществующий токен собирается, проходит
108
- stylelint и проверку класса без правила, а свойство молча берёт наследованное значение:
109
- правило выглядит написанным и не красит ничего. Ловится это только замером в браузере, а
110
- имена берутся из объявлений кита, а не по догадке о том, как токен должен был бы называться.
111
- - **`rtBlock` на `<ng-container>` класса не ставит вовсе:** узел это комментарий, и имя блока
112
- он только объявляет потомкам. Класс блока экрана вешает хост через `host: { class: … }`.
113
- - **`justify-content: center` во flex-контейнере с `overflow-x` уводит первые элементы за
114
- нулевой скролл** — доскроллить до них невозможно. В прокручиваемых лентах —
115
- `justify-content: safe center`.
116
- - **`scrollbar-gutter: stable` на корне не заводить:** резерв под полосу прокрутки сужает
117
- содержащий блок для `position: fixed`, и попап, выровненный по правому краю, встаёт на
118
- ширину резерва левее своей кнопки.
119
- - **`& + :host` невалиден:** изнутри компонента до соседнего хоста не дотянуться. Разделитель
120
- между повторяющимися хостами — `:host(:not(:first-of-type))`.
121
- - **`[attr.aria-disabled]` визуального состояния не даёт:** браузер стилизует `:disabled`, но
122
- атрибуты `aria-*` — нет. К каждому `aria-disabled` заводится правило `[aria-disabled='true']`.
123
- - **Гарнитуру с `body` элементы формы не наследуют:** браузер задаёт `button`, `input`,
124
- `select` и `textarea` свой шрифт. Наследование включено глобально — сбрасывать его нельзя.
125
- - **Комментарии-выключатели stylelint не ставятся.** Селекторы объединяются вложенностью.
126
- - **При переносе стилей новых объявлений не появляется** — только перемещение существующих.