@rt-tools/agent-kit 0.2.0 → 0.4.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 (203) hide show
  1. package/README.md +235 -18
  2. package/assets/agents/business-analyst.md +74 -0
  3. package/assets/agents/project-manager.md +70 -0
  4. package/assets/agents/qa-engineer.md +72 -0
  5. package/assets/agents/skill-curator.md +110 -0
  6. package/assets/agents/spec-critic.md +44 -0
  7. package/assets/agents/spec-writer.md +50 -0
  8. package/assets/checks/board.github.mjs +286 -0
  9. package/assets/checks/check-board.github.mjs +188 -0
  10. package/assets/checks/check-doc-paths.mjs +163 -0
  11. package/assets/checks/check-dupes.mjs +277 -0
  12. package/assets/checks/check-lib-layers.mjs +573 -0
  13. package/assets/checks/check-reuse.mjs +208 -0
  14. package/assets/checks/check-schema-drift.mjs +186 -0
  15. package/assets/checks/check-specs.mjs +1007 -0
  16. package/assets/checks/check-styles.mjs +109 -0
  17. package/assets/checks/rt-kit-checks.config.mjs +134 -0
  18. package/assets/checks/task-new.github.mjs +198 -0
  19. package/assets/commands/skill-curator.md +70 -0
  20. package/assets/defaults/gate-map.sh +100 -0
  21. package/assets/defaults/project.sh +179 -0
  22. package/assets/hooks/browser-device-id.sh +20 -0
  23. package/assets/hooks/browser-guard-device-id.sh +28 -0
  24. package/assets/hooks/browser-guard-no-asking.sh +27 -0
  25. package/assets/hooks/browser-guard-no-listing.sh +18 -0
  26. package/assets/hooks/browser-guard-no-other-drivers.sh +79 -0
  27. package/assets/hooks/browser-guard-require-select.sh +54 -0
  28. package/assets/hooks/commit-msg.sh +26 -0
  29. package/assets/hooks/constitution-index.sh +43 -0
  30. package/assets/hooks/dev-server-guard.sh +115 -0
  31. package/assets/hooks/docs-guard.sh +282 -0
  32. package/assets/hooks/git-guard-delivery.sh +167 -0
  33. package/assets/hooks/git-guard-main.sh +73 -0
  34. package/assets/hooks/git-guard-push-tests.sh +94 -0
  35. package/assets/hooks/glossary-load.sh +23 -0
  36. package/assets/hooks/lint-after-edit.sh +219 -0
  37. package/assets/hooks/qa-dataid-guard.sh +121 -0
  38. package/assets/hooks/reuse-first-guard.sh +154 -0
  39. package/assets/hooks/skill-gate-rearm.sh +23 -0
  40. package/assets/hooks/skill-gate.sh +128 -0
  41. package/assets/hooks/skill-loaded.sh +21 -0
  42. package/assets/hooks/sql-guard.sh +679 -0
  43. package/assets/hooks/task-context-load.sh +100 -0
  44. package/assets/hooks/task-flow-guard.sh +107 -0
  45. package/assets/laws/{access.md → application/access.md} +1 -4
  46. package/assets/laws/{locales.md → application/locales.md} +1 -3
  47. package/assets/laws/application/money.md +41 -0
  48. package/assets/laws/application/ownership.md +32 -0
  49. package/assets/laws/{search-visibility.md → application/search-visibility.md} +1 -1
  50. package/assets/laws/code-structure.md +7 -6
  51. package/assets/laws/delivery.md +53 -3
  52. package/assets/laws/entity-editing.md +49 -55
  53. package/assets/laws/entity-models.md +4 -14
  54. package/assets/laws/frontend-application.md +5 -5
  55. package/assets/laws/lib-imports.md +14 -1
  56. package/assets/laws/lists.md +33 -0
  57. package/assets/laws/navigation.md +40 -0
  58. package/assets/laws/project-documentation.md +17 -8
  59. package/assets/laws/reuse-first.md +26 -21
  60. package/assets/laws/shared-code.md +13 -1
  61. package/assets/laws/verifiability.md +17 -1
  62. package/assets/laws/work-conduct.md +48 -0
  63. package/assets/patterns/admin-lists-screen.md +131 -0
  64. package/assets/patterns/admin-nav-item.md +71 -0
  65. package/assets/patterns/angular-patterns-state.md +101 -0
  66. package/assets/patterns/api-layer-pair.md +88 -0
  67. package/assets/patterns/browser-verification-measure.md +86 -0
  68. package/assets/patterns/browser-verification-stand.md +143 -0
  69. package/assets/patterns/component-structure-new.md +99 -0
  70. package/assets/patterns/dependencies-upgrade.md +65 -0
  71. package/assets/patterns/doc-style-sweep.md +137 -0
  72. package/assets/patterns/doc-style-write.md +109 -0
  73. package/assets/patterns/entity-aside.md +136 -0
  74. package/assets/patterns/entity-models-new.md +124 -0
  75. package/assets/patterns/entity-store.md +91 -0
  76. package/assets/patterns/git-workflow-commit.azure.md +259 -0
  77. package/assets/patterns/git-workflow-commit.github.md +333 -0
  78. package/assets/patterns/git-workflow-commit.gitlab.md +283 -0
  79. package/assets/patterns/git-workflow-merge.md +99 -0
  80. package/assets/patterns/git-workflow-migration.md +88 -0
  81. package/assets/patterns/git-workflow-restart.md +49 -0
  82. package/assets/patterns/lib-layers-move.md +95 -0
  83. package/assets/patterns/lib-layers-new.md +82 -0
  84. package/assets/patterns/ownership-scope-resolve.md +69 -0
  85. package/assets/patterns/permissions-procedure.md +71 -0
  86. package/assets/patterns/platform-access-di.md +84 -0
  87. package/assets/patterns/pricing-quote.md +71 -0
  88. package/assets/patterns/reuse-first-extend.md +73 -0
  89. package/assets/patterns/seo-page.md +104 -0
  90. package/assets/patterns/seo-verify.md +83 -0
  91. package/assets/patterns/shared-code-new.md +86 -0
  92. package/assets/patterns/spec-driven-domain.md +107 -0
  93. package/assets/patterns/spec-driven-rule.md +127 -0
  94. package/assets/patterns/styling-bem-component.md +88 -0
  95. package/assets/patterns/styling-bem-layout.md +73 -0
  96. package/assets/patterns/task-flow-close.md +90 -0
  97. package/assets/patterns/task-flow-resume.md +94 -0
  98. package/assets/patterns/task-flow-start.md +117 -0
  99. package/assets/patterns/testing-e2e.md +92 -0
  100. package/assets/patterns/testing-unit.md +117 -0
  101. package/assets/patterns/translations-key.md +64 -0
  102. package/assets/patterns/ts-procedure.md +65 -0
  103. package/assets/rules/angular-patterns.md +71 -0
  104. package/assets/rules/api-layer.md +71 -0
  105. package/assets/rules/browser-verification.md +87 -0
  106. package/assets/rules/component-structure.md +64 -0
  107. package/assets/rules/dependencies.md +66 -0
  108. package/assets/rules/doc-style.md +103 -0
  109. package/assets/rules/entity-conventions.md +78 -0
  110. package/assets/rules/entity-models.md +70 -0
  111. package/assets/rules/git-workflow.azure.md +116 -0
  112. package/assets/rules/git-workflow.github.md +123 -0
  113. package/assets/rules/git-workflow.gitlab.md +113 -0
  114. package/assets/rules/lib-layers.md +80 -0
  115. package/assets/rules/lists.md +73 -0
  116. package/assets/rules/navigation.md +78 -0
  117. package/assets/rules/ownership-scope.md +63 -0
  118. package/assets/rules/permissions.md +70 -0
  119. package/assets/rules/platform-access.md +77 -0
  120. package/assets/rules/pricing.md +64 -0
  121. package/assets/rules/reuse-first.md +83 -0
  122. package/assets/rules/seo.md +71 -0
  123. package/assets/rules/shared-code.md +70 -0
  124. package/assets/rules/spec-driven.md +135 -0
  125. package/assets/rules/styling-bem.md +74 -0
  126. package/assets/rules/task-flow.md +110 -0
  127. package/assets/rules/testing.md +100 -0
  128. package/assets/rules/translations.md +69 -0
  129. package/assets/rules/typescript-conventions.md +76 -0
  130. package/assets/skills/agent-kit.md +81 -0
  131. package/assets/skills/write-a-skill.md +108 -0
  132. package/assets/templates/gate-map.sh +45 -0
  133. package/assets/templates/implementation.md +44 -0
  134. package/assets/templates/pattern.md +5 -1
  135. package/assets/templates/project.sh +54 -0
  136. package/assets/templates/rule.md +12 -23
  137. package/assets/variants.json +20 -0
  138. package/assets/workflows/feature.js +134 -0
  139. package/assets/workflows/plan.js +150 -0
  140. package/bin/agent-kit.d.ts.map +1 -1
  141. package/bin/agent-kit.js +78 -5
  142. package/bin/agent-kit.js.map +1 -1
  143. package/bin/prompt.d.ts +5 -0
  144. package/bin/prompt.d.ts.map +1 -1
  145. package/bin/prompt.js +19 -7
  146. package/bin/prompt.js.map +1 -1
  147. package/index.d.ts +1 -0
  148. package/index.d.ts.map +1 -1
  149. package/index.js +1 -0
  150. package/index.js.map +1 -1
  151. package/lib/assets.d.ts +14 -1
  152. package/lib/assets.d.ts.map +1 -1
  153. package/lib/assets.js +23 -2
  154. package/lib/assets.js.map +1 -1
  155. package/lib/catalog.d.ts +52 -5
  156. package/lib/catalog.d.ts.map +1 -1
  157. package/lib/catalog.js +104 -16
  158. package/lib/catalog.js.map +1 -1
  159. package/lib/commands.d.ts +22 -1
  160. package/lib/commands.d.ts.map +1 -1
  161. package/lib/commands.js +218 -11
  162. package/lib/commands.js.map +1 -1
  163. package/lib/companion.d.ts +57 -0
  164. package/lib/companion.d.ts.map +1 -0
  165. package/lib/companion.js +60 -0
  166. package/lib/companion.js.map +1 -0
  167. package/lib/config.d.ts +42 -2
  168. package/lib/config.d.ts.map +1 -1
  169. package/lib/config.js +60 -2
  170. package/lib/config.js.map +1 -1
  171. package/lib/freshness.d.ts +14 -0
  172. package/lib/freshness.d.ts.map +1 -0
  173. package/lib/freshness.js +116 -0
  174. package/lib/freshness.js.map +1 -0
  175. package/lib/hooks-map.d.ts +24 -0
  176. package/lib/hooks-map.d.ts.map +1 -0
  177. package/lib/hooks-map.js +72 -0
  178. package/lib/hooks-map.js.map +1 -0
  179. package/lib/integrity.d.ts +36 -0
  180. package/lib/integrity.d.ts.map +1 -0
  181. package/lib/integrity.js +44 -0
  182. package/lib/integrity.js.map +1 -0
  183. package/lib/picker.d.ts +11 -1
  184. package/lib/picker.d.ts.map +1 -1
  185. package/lib/picker.js +44 -6
  186. package/lib/picker.js.map +1 -1
  187. package/lib/stamp.d.ts +2 -5
  188. package/lib/stamp.d.ts.map +1 -1
  189. package/lib/stamp.js +25 -10
  190. package/lib/stamp.js.map +1 -1
  191. package/lib/sync.d.ts +29 -0
  192. package/lib/sync.d.ts.map +1 -1
  193. package/lib/sync.js +78 -4
  194. package/lib/sync.js.map +1 -1
  195. package/lib/variants.d.ts +44 -0
  196. package/lib/variants.d.ts.map +1 -0
  197. package/lib/variants.js +82 -0
  198. package/lib/variants.js.map +1 -0
  199. package/package.json +1 -1
  200. package/rt-tools-agent-kit-0.4.0.tgz +0 -0
  201. package/assets/laws/admin-lists.md +0 -35
  202. package/assets/laws/admin-navigation.md +0 -38
  203. package/rt-tools-agent-kit-0.2.0.tgz +0 -0
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: shared-code-new
3
+ kind: pattern
4
+ rule: shared-code
5
+ description: Паттерн правила shared-code. Брать, когда заводится новое число-настройка, общая функция или общий тип, который должны одинаково понимать сайт, админка и бэкенд — куда класть, как объявить, как сверить строку с набором и как убедиться, что копия не осталась на старом месте.
6
+ ---
7
+
8
+ # Новое общее заводится так
9
+
10
+ Паттерн правила `shared-code`. Что при этом должно быть верно — закон
11
+ `docs/constitution/shared-code.md`.
12
+
13
+ ## Когда брать
14
+
15
+ - Появилось число-настройка: предел, размер, длительность.
16
+ - Появилась функция без фреймворка, нужная обеим сторонам.
17
+ - Значение приходит строкой и должно быть сверено с конечным набором.
18
+
19
+ ## Куда класть
20
+
21
+ | Что | Куда |
22
+ | ------------------------------------- | ----------------------------------------------- |
23
+ | число или функция без фреймворка | `libs/common/util`, файл по предмету |
24
+ | готовый тип или набор значений | берётся из `@rt-tools/utils`, не переписывается |
25
+ | токен DI, общий двум фронтовым семьям | `libs/common/platform` |
26
+
27
+ Файл выбирается по предмету: `const/list.const.ts`, `functions/list-selection.util.ts`.
28
+ Дальше — строка в барель `libs/common/util/src/index.ts`.
29
+
30
+ ## Число объявляется один раз и без довода
31
+
32
+ ```typescript
33
+ export const DEFAULT_PAGE_SIZE: number = 20;
34
+ ```
35
+
36
+ ```typescript
37
+ ✗ export function listPageOf(query: ListQuery | undefined, defaultPageSize: number): IListPage
38
+ ✓ export function listPageOf(query: ListQuery | undefined): IListPage
39
+ ```
40
+
41
+ Пока умолчание передаётся доводом, домен вправе назвать своё число — так у промокодов
42
+ появилось `25` против `20` у остальных списков.
43
+
44
+ ## Строка сверяется с набором, а не приводится к типу
45
+
46
+ Приведение принимает любую строку. Сверку делает общая пара функций, а что делать с промахом,
47
+ решает вызывающий.
48
+
49
+ ```typescript
50
+ const operator: FilterOperatorType | null = listFilterOperatorOf(filter.operatorType);
51
+ if (!operator) {
52
+ throw new ConnectError(`filter operator is required: ${filter.propertyName}`, Code.InvalidArgument);
53
+ }
54
+ ```
55
+
56
+ ```typescript
57
+ const direction: ListSortOrderType = listSortOrderOf(rawDirection) ?? LIST_SORT_ORDER_ENUM.ASC;
58
+ ```
59
+
60
+ Сервер отбивает запрос, экран берёт умолчание. Общий маппер здесь не годится: он подал бы
61
+ промах умолчанием, и клиент получил бы отбор, которого не просил.
62
+
63
+ `typeCast.getAsType` для этого тоже не годится — значение вне набора он пишет в консоль и
64
+ возвращает строкой `'unknown'`.
65
+
66
+ ## Проверить, что копия не осталась
67
+
68
+ ```bash
69
+ npm run check:dupes
70
+ ```
71
+
72
+ Проверка падает на четырёх признаках: одно имя из двух либ, два перечисления с одинаковым
73
+ набором членов, число-настройка под одним именем в двух либах, перечисление, повторяющее набор
74
+ из `@rt-tools/utils`.
75
+
76
+ Накопленное лежит в `tools/dupes-allowlist.json` под ключом `debt` и отказом не считается.
77
+ Список только сокращается: новая строка в нём означает, что повтор завели уже после проверки.
78
+
79
+ ## Частые промахи
80
+
81
+ - Своё перечисление с теми же членами, что уже есть в `@rt-tools/utils`, — копия, даже если
82
+ имена разошлись.
83
+ - Умолчание, переданное доводом, — домен назовёт своё число, и разъезд будет молчаливым.
84
+ - Ту же логику, написанную заново под другим именем, проверка не ловит и ловить не будет —
85
+ такой повтор находит только тот, кто читает правку.
86
+ - Строковая настройка и таблица соответствий не учитываются вовсе — долг `Q-S-2`.
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: spec-driven-domain
3
+ kind: pattern
4
+ rule: spec-driven
5
+ description: Паттерн правила spec-driven. Брать при заведении или правке спека домена в docs/specs — обязательные разделы, форма сценария, привязка правила к коду, порядок работы от спека к коду. Не брать для заведения закона, правила или паттерна — это паттерн spec-driven-rule.
6
+ ---
7
+
8
+ # Спек домена
9
+
10
+ Паттерн правила `spec-driven`. Что при этом должно быть верно — закон
11
+ `docs/constitution/project-documentation.md`.
12
+
13
+ ## Когда брать
14
+
15
+ - Заводится новый домен или фича в `proposed/`.
16
+ - Правится `.proto` — спеки задетых доменов едут той же веткой.
17
+ - Замечено расхождение спека с кодом.
18
+
19
+ ## Раскладка
20
+
21
+ ```
22
+ docs/specs/<домен>/
23
+ spec.md — как домен работает
24
+ implementation.md — таблица «правило → файл:символ»
25
+ scenarios.md — сценарии SC-<ПРЕФИКС>-<НОМЕР>
26
+ proposed/<фича>/ — только то, чего ещё нет
27
+ ```
28
+
29
+ Шаблон — `docs/specs/_template/spec.md`, указатель с префиксами — `docs/specs/README.md`.
30
+
31
+ ## Обязательные разделы
32
+
33
+ `## Зачем` · `## Терминология` с подразделом `### Как это называется в интерфейсе` ·
34
+ `## Правила` · `## Что не входит` · `## Контракт` с подразделом `### Коды отказов` ·
35
+ `## Данные` · `## Экраны и состояния` · `## Сквозные требования` с четырьмя подразделами
36
+ `### Локали`, `### SEO`, `### Мобильная раскладка`, `### Мультиобъектность` · `## Решения` ·
37
+ `## Открытые вопросы` · `## История изменений`.
38
+
39
+ Текст заголовка сверяется дословно. «Не применимо» — законный ответ, отсутствие раздела — нет.
40
+
41
+ Шапка несёт статус, дату ревизии, префикс сценариев, зависимости от других доменов, строку
42
+ `**Законы:**` — законы, которые домен применяет, — и строку `**Процедуры:**` — корни либ, чьи
43
+ процедуры домен обслуживает.
44
+
45
+ ```markdown
46
+ **Зависимости:** `pricing` (сумма заявки), `availability` (занятость дат)
47
+ **Законы:** `access`, `locales`, `money`, `ownership`
48
+ **Процедуры:** `libs/api/<домен>`
49
+ ```
50
+
51
+ Закон, названный где-нибудь в тексте спека, обязан стоять в этой строке: связь сверяется в
52
+ обе стороны.
53
+
54
+ ## Правило и его привязка
55
+
56
+ Правило формулируется так, чтобы его можно было нарушить, и начинается с жирной фразы:
57
+
58
+ ```markdown
59
+ - **Применяется одна максимальная скидка.** Сложение скидок даёт цену ниже себестоимости.
60
+ ```
61
+
62
+ Привязка живёт в `implementation.md` рядом, ключ связи — сам текст правила:
63
+
64
+ ```markdown
65
+ | Правило | Где исполняется |
66
+ | ------------------------------------- | ------------------------------------------------------------------ |
67
+ | Применяется одна максимальная скидка. | `libs/api/<домен>/util/src/lib/quote.calculator.ts:calculateQuote` |
68
+ ```
69
+
70
+ Правило, которому места в коде не нашлось, — намерение: ему место в «Открытых вопросах» как
71
+ `Q-N`, а не формальный якорь.
72
+
73
+ ## Сценарий
74
+
75
+ ```markdown
76
+ ### SC-BK-19 — подтверждение на занятые даты отбивается
77
+
78
+ Дано у объекта есть подтверждённая бронь на пересекающиеся даты
79
+ Когда владелец подтверждает заявку
80
+ Тогда отказ подаётся владельцу как занятые даты, а не как ошибка базы
81
+ ```
82
+
83
+ Идентификатор ставится в начало заголовка теста, через тире. Сценарий без теста помечается
84
+ `Не покрыто: <причина>`, сценарий с неполным тестом — `Покрытие: частичное — <чего не
85
+ хватает>`.
86
+
87
+ ## Порядок работы
88
+
89
+ 1. Задача заводится сценариями: что станет верно, когда работа закончится.
90
+ 2. Спек домена (или `proposed/<фича>/`) правится **до** кода.
91
+ 3. Код пишется под сценарии, тесты называются их идентификаторами.
92
+ 4. `npm run check:specs` — до пуша.
93
+ 5. Приёмка идёт по сценариям, а не по пересказу правки.
94
+
95
+ ## Частые промахи
96
+
97
+ - `tasks.md` в спеке: шаги — артефакт сессии, им место в ветке или в описании PR.
98
+ - Скопированная из контракта таблица полей: источник — `libs/common/proto/proto/<область>/v1/`,
99
+ и компилируется из двух только одна.
100
+ - Колонки и индексы в спеке: они в `prisma/schema.prisma`, а в спеке остаётся правило, которое
101
+ ограничение выражает.
102
+ - Место, где правило исполняется, внутри текста правила: оно меняется при первом рефакторинге,
103
+ и для него заведён `implementation.md`.
104
+ - Пометка «Не покрыто» при существующем тесте — отказ: долг закрыли, а отметку не сняли.
105
+ - Закон, названный в тексте, но забытый в строке `**Законы:**`: по закону тогда не узнать,
106
+ какие домены на нём стоят.
107
+ - Правка `.proto` без спеков задетых доменов: `docs-guard` отбивает такой коммит.
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: spec-driven-rule
3
+ kind: pattern
4
+ rule: spec-driven
5
+ description: Паттерн правила spec-driven. Брать при заведении или правке закона в docs/constitution, правила или паттерна в .claude/skills — готовые шапки, набор разделов каждого слоя, таблица привязки, признак того, что правило пора делить. Не брать для спека домена — это паттерн spec-driven-domain.
6
+ ---
7
+
8
+ # Закон, правило и паттерн
9
+
10
+ Паттерн правила `spec-driven`. Что при этом должно быть верно — закон
11
+ `docs/constitution/project-documentation.md`.
12
+
13
+ ## Когда брать
14
+
15
+ - Правило приходится повторять ещё в двух местах — пора заводить закон.
16
+ - Заводится правило под уже существующий закон.
17
+ - Готовый код в правиле разросся — пора выносить паттерн.
18
+
19
+ ## Закон
20
+
21
+ `docs/constitution/<закон>.md`. О проекте не знает ничего: ни путей, ни имён файлов, ни
22
+ привязок. Признак закона: попытка положить правило в спек домена заставляет повторить то же
23
+ самое ещё в двух.
24
+
25
+ Слой выбирается по одному вопросу: останется ли статья верной в приложении, где нет ни денег,
26
+ ни локалей перевода, ни второй владеющей сущности. Останется — закон живёт в корне; не
27
+ останется — это закон приложения, и он кладётся в `docs/constitution/application/<закон>.md`. Имя закона одно на
28
+ оба слоя: ни `law:` в шапке правила, ни `**Законы:**` в шапке спека слоя не называют, а два
29
+ закона с одним именем развели бы правило и его закон между собой.
30
+
31
+ Разделы: `## Зачем` (без заголовка, вводным абзацем) · `## Статьи` · `## Открытые вопросы`.
32
+ Обязательны только «Статьи» — их и сверяет проверка. «Открытые вопросы» заводятся, когда
33
+ вопрос есть, и стираются вместе с последним закрытым: закрытый вопрос из закона убирается, а
34
+ не превращается в пустой раздел.
35
+
36
+ Ни истории правок, ни доводов о том, почему когда-то выбрали так, в законе нет. Историю
37
+ держит система контроля версий, а довод с отвергнутой альтернативой — свойство работы, а не
38
+ продукта: ему место в «Ловушках» правила под этим законом, где и путям к файлам можно.
39
+ Утверждение, которое нельзя написать как «верно всегда», статьёй не становится вовсе.
40
+
41
+ ```markdown
42
+ # Закон о поставке
43
+
44
+ Как правка доезжает до работающего приложения. …
45
+
46
+ **Ревизия:** 2026-08-05
47
+
48
+ ## Статьи
49
+
50
+ - **Выкатывается образ того коммита, который выкатывают.** Умолчание «последний» отстаёт от
51
+ главной ветки, и приложение молча возвращается к прежней версии, продолжая отвечать.
52
+ ```
53
+
54
+ Раздел `## Открытые вопросы` заводится, когда вопрос есть, и стирается вместе с последним
55
+ закрытым. Вопрос называется `Q-<буква закона>-<номер>`, говорит, что решение изменит, и несёт
56
+ дату заведения; номер после закрытия не переиспользуется.
57
+
58
+ Поведение кода законом не является: «стор отвечает булевым», «метод называется `save`» — этого
59
+ не видит ни гость, ни владелец. Граница простая: закон описывает то, что видно снаружи
60
+ приложения. Исключение — статья об устройстве кода, которую сверяет машина: якоря читаются
61
+ только под `docs/specs/` и `docs/constitution/`.
62
+
63
+ ## Правило
64
+
65
+ `.claude/skills/<правило>/SKILL.md`. Привязывает закон к этому проекту; на один закон их
66
+ бывает несколько.
67
+
68
+ ```markdown
69
+ ---
70
+ name: git-workflow
71
+ kind: rule
72
+ law: delivery
73
+ description: Правило под «Закон о поставке». Брать на … Готовый код — в паттернах …
74
+ ---
75
+ ```
76
+
77
+ Разделы: `## Как это называется здесь` · `## Где это лежит` · `## Как закон применяется
78
+ здесь` · `## Чего из закона здесь нет` · `## Паттерны` · `## Ловушки`.
79
+
80
+ Сверяется только `## Как закон применяется здесь`: каждый его пункт начинается жирной фразой,
81
+ и у каждой жирной фразы есть строка в `implementation.md` рядом.
82
+
83
+ ```markdown
84
+ | Статья | Где исполняется |
85
+ | -------------------------------------------------------------- | ----------------------------------- |
86
+ | Образы выкатываются по sha коммита, а не по метке «последний». | `docker-compose.prod.yml:IMAGE_TAG` |
87
+ ```
88
+
89
+ Утверждение, которому места в коде не нашлось, в этот раздел не ставится: оно уходит прозой в
90
+ «Ловушки» или вопросом `Q-N` в закон.
91
+
92
+ ## Паттерн
93
+
94
+ `.claude/skills/<правило>-<что>/SKILL.md`. Минимум один на правило.
95
+
96
+ ```markdown
97
+ ---
98
+ name: git-workflow-commit
99
+ kind: pattern
100
+ rule: git-workflow
101
+ description: Паттерн правила git-workflow. Брать … Не брать для … — это паттерн …
102
+ ---
103
+ ```
104
+
105
+ Разделы: `## Когда брать` · готовый код · `## Частые промахи`. Привязки у паттерна нет:
106
+ проверка его не сверяет, потому что сверять готовый код с ним самим нечем.
107
+
108
+ ## Порядок
109
+
110
+ 1. Статья пишется в закон — без путей и имён файлов.
111
+ 2. Правило объявляет закон в шапке и называет то же самое в терминах этого дерева.
112
+ 3. Каждое утверждение правила получает строку в `implementation.md`; якорь проверяется
113
+ открытием файла, а не памятью.
114
+ 4. Готовый код уезжает в паттерн, а правило на него ссылается.
115
+ 5. `npm run check:specs` — до пуша.
116
+
117
+ ## Частые промахи
118
+
119
+ - Закон назвал файл проекта — проверка отбивает. Путям место в правиле.
120
+ - Спутник с привязкой лежит рядом с законом: он привязывает закон к этому проекту, а зелёная
121
+ проверка это утвердит, потому что структура совпадёт с тем, чего проверка сама и ждёт.
122
+ - Якорь ведёт в мёртвый символ: объявлен и больше нигде не встречается. Так пять правил про
123
+ правку сущности оказались привязаны к механике, которую не зовёт ни один экран.
124
+ - Утверждение переформулировали, а строку в привязке не тронули: связь идёт по тексту, и
125
+ проверка перестанет её находить.
126
+ - В `description` не сказано, когда паттерн **не** брать, — соседний паттерн того же правила
127
+ становится неотличимым.
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: styling-bem-component
3
+ kind: pattern
4
+ rule: styling-bem
5
+ description: Паттерн правила styling-bem. Брать при правке стилей компонента кита — готовый :host, модификаторы, токены оформления, язык оформления публичного сайта, обход умолчаний кита. Не брать для раскладки экрана — это паттерн styling-bem-layout.
6
+ ---
7
+
8
+ # Стили компонента
9
+
10
+ Паттерн правила `styling-bem`. Что при этом должно быть верно — закон
11
+ `docs/constitution/frontend-application.md`.
12
+
13
+ ## Когда брать
14
+
15
+ - Правится компонент кита — он живёт в пакете `@rt-tools/ui-kit-v2`, а не в этом дереве.
16
+ - Правится оформление публичного сайта.
17
+ - Нужно перебить умолчание кита в своём компоненте.
18
+
19
+ ## `:host` — сам блок
20
+
21
+ Хост несёт класс блока, раскладка на `:host`, элементы вложены внутрь:
22
+
23
+ ```scss
24
+ :host {
25
+ display: inline-flex;
26
+
27
+ .<префикс > -tag {
28
+ display: inline-flex;
29
+ gap: var(--<префикс>-space-1);
30
+ align-items: center;
31
+
32
+ &--shape--pill {
33
+ border-radius: var(--<префикс>-radius-full);
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ Отступ — четыре пробела. Модификатор — `&--<имя>` или привязка класса на хосте
40
+ (`[class.<префикс>-component-name--active]="isActive()"`).
41
+
42
+ У экрана вне кита такого раздела нет: `display: flex` с `gap` и `padding` на `:host` — это
43
+ раскладка, и она в общем слое приложения.
44
+
45
+ ## Значения — только токенами
46
+
47
+ ```scss
48
+ ✗ color: #fff;
49
+ ✗ box-shadow: 0 1px 2px rgb(0 0 0 / 12%);
50
+ ✓ color: var(--<префикс>-color-surface);
51
+ ✓ box-shadow: var(--<префикс>-shadow-sm);
52
+ ```
53
+
54
+ Составное значение берётся готовым токеном целиком, а не собирается из частей. SCSS-переменные
55
+ (`$primaryColor`) для значений оформления не используются вовсе.
56
+
57
+ ## Язык оформления публичного сайта
58
+
59
+ Тропический премиум, фото-first:
60
+
61
+ - светлая тёплая палитра — песок, терракота, пальмовая зелень, только через `--<префикс>-color-*`;
62
+ - акцентная антиква в заголовках (`--<префикс>-font-serif`), гуманистический гротеск в тексте
63
+ (`--<префикс>-font-sans`);
64
+ - большие полноэкранные фото, щедрые отступы, сдержанные анимации;
65
+ - тёмные оверлеи поверх фото — переменными с прозрачностью.
66
+
67
+ ## Перебить умолчание кита
68
+
69
+ Стили компонента с `ViewEncapsulation.None` весят столько же, сколько умолчания кита: у
70
+ `.<префикс>-block__item` и у `.<префикс>-kit-item` по одному классу, и исход решает порядок подключения.
71
+ Переопределение пишется потомком блока:
72
+
73
+ ```scss
74
+ & &__item {
75
+ color: var(--<префикс>-color-text-muted);
76
+ }
77
+ ```
78
+
79
+ ## Частые промахи
80
+
81
+ - Комментарий-выключатель stylelint: селекторы объединяются вложенностью, а не отключением
82
+ правила.
83
+ - `!important`: запрещён, и инлайновый `width: 100%` на боксе панели перебить им нельзя.
84
+ - Новые объявления при переносе стилей: переносится существующее, новое появляется только
85
+ тогда, когда задача — фича.
86
+ - Замечание линтера, лежавшее в файле раньше, оставлено: правятся все, и новые, и старые.
87
+ - Свой `font-family: inherit` в компоненте: наследование включено глобально в `styles.scss`
88
+ обоих приложений.
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: styling-bem-layout
3
+ kind: pattern
4
+ rule: styling-bem
5
+ description: Паттерн правила styling-bem. Брать при сборке экрана раздела, формы, панели или окна — готовые блоки общего слоя, разметка через rtBlock и rtElem, свой элемент в чужом поддереве, признак того, что правка идёт не туда. Не брать для стилей компонента кита — это паттерн styling-bem-component.
6
+ ---
7
+
8
+ # Экран на общем слое раскладки
9
+
10
+ Паттерн правила `styling-bem`. Что при этом должно быть верно — закон
11
+ `docs/constitution/frontend-application.md`.
12
+
13
+ ## Когда брать
14
+
15
+ - Собирается экран раздела, форма, содержимое панели или модального окна.
16
+ - В файле стилей экрана появляется раскладка.
17
+
18
+ ## Файл стилей экрана по умолчанию пустой
19
+
20
+ Раскладка объявлена один раз в общем слое приложения (`apps/<app>/src/styles/`), а экран её
21
+ только применяет. Блоков в админке четыре, у сайта один:
22
+
23
+ | Блок | Что раскладывает |
24
+ | --------------------- | --------------------------------------------------------------- |
25
+ | `<префикс>-page` | экран раздела: заголовок, тулбар, прокрутка, таблица, пагинация |
26
+ | `<префикс>-form` | форма с разделами-карточками и строками полей |
27
+ | `<префикс>-panel` | содержимое панели правки |
28
+ | `<префикс>-window` | содержимое модального окна |
29
+ | `<префикс>-site-page` | колонка содержимого сайта: заголовок раздела и вводный абзац |
30
+
31
+ Блок вешается на хост, элементы получают классы от `rtBlock` в корне шаблона:
32
+
33
+ ```typescript
34
+ host: { class: '<префикс>-page' },
35
+ ```
36
+
37
+ ```html
38
+ <ng-container rtBlock="<префикс>-page">
39
+ <header rtElem="header">
40
+ <div rtElem="header-main">
41
+ <h1 rtElem="title">{{ 'bookingsTitle' | transloco }}</h1>
42
+ <p rtElem="hint">{{ 'bookingsHint' | transloco }}</p>
43
+ </div>
44
+ </header>
45
+ </ng-container>
46
+ ```
47
+
48
+ `rtBlock` на `<ng-container>` класса не ставит — узел это комментарий. Второго носителя класса
49
+ блока не нужно, и своей обёртки `<section>` тоже.
50
+
51
+ ## Свой элемент в чужом поддереве
52
+
53
+ Пара директив на одном элементе; класс блока при этом не ставится, только класс элемента:
54
+
55
+ ```html
56
+ <div rtBlock="<префикс>-bookings-page" rtElem="confirm"></div>
57
+ ```
58
+
59
+ Класс получается `<префикс>-bookings-page__confirm`, а потомки внутри считаются от того же блока.
60
+
61
+ ## Своё в файле экрана
62
+
63
+ Остаётся только то, что принадлежит одному этому экрану и в общий слой не просится — сетка
64
+ календаря, карта на странице объекта, лента переписки. Рядом пишется, почему это не общее.
65
+
66
+ ## Частые промахи
67
+
68
+ - `display: flex` с `gap` и `padding` на `:host` в файле экрана — это раскладка. Одинаковые с
69
+ виду экраны от неё расходятся: заголовок страницы объявлялся в одиннадцати компонентах тремя
70
+ разными кеглями.
71
+ - `rtElem` без предка с `rtBlock`: отрисовка падает в рантайме, сборка и линт молчат.
72
+ - Класс, у которого правило сняли, а `rtElem` в шаблоне остался: ловит `npm run check:styles`.
73
+ - Элемент чужого блока в чужом поддереве: имя блока приходит инъекцией, и подмешать его нечем.
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: task-flow-close
3
+ kind: pattern
4
+ rule: task-flow
5
+ description: Паттерн правила task-flow. Брать при закрытии работы — вливание договорённости в спек домена последним коммитом отчёта, разбор папки задачи, переезд в архив, сверка очереди работ. Не брать для хода работы — это паттерн task-flow-resume.
6
+ ---
7
+
8
+ # Закрытие работы
9
+
10
+ Паттерн правила `task-flow`. Что при этом должно быть верно — закон
11
+ `docs/constitution/work-conduct.md`.
12
+
13
+ ## Когда брать
14
+
15
+ - Этапы замысла закрыты, проверки зелёные, отчёт готовится к публикации.
16
+ - `npm run check:specs` перечислил договорённость в разделе «Пора вливать».
17
+
18
+ ## 1. Договорённость вливается в спек домена
19
+
20
+ Последним коммитом отчёта, до слияния. Код к этому моменту написан, поэтому привязки
21
+ `файл:символ` известны — правило въезжает в спек домена сразу проверяемым.
22
+
23
+ ```bash
24
+ npm run check:specs # раздел «Пора вливать» называет готовые директории
25
+ ```
26
+
27
+ Порядок переезда:
28
+
29
+ - правила из `proposed/<фича>/spec.md` дописываются в `spec.md` домена, в его разделы;
30
+ - сценарии переезжают в `scenarios.md` домена **с прежними номерами**: на них ссылаются
31
+ заголовки тестов, и пересчёт рвёт сверку;
32
+ - привязки из `proposed/<фича>/implementation.md` дописываются в `implementation.md` домена
33
+ и проставляются на код, который теперь есть;
34
+ - законы, объявленные фичей в шапке, дописываются в шапку спека домена;
35
+ - директория `proposed/<фича>/` удаляется, строка о фиче снимается из раздела «Что
36
+ предложено, но ещё не выкачено» в `docs/specs/README.md`;
37
+ - домена ещё не было — `proposed/` заменяется полноценным спеком, и домен получает строку в
38
+ таблице `docs/specs/README.md`.
39
+
40
+ Работа шла несколькими задачами — вливание идёт в последней из них. Какая последняя, видно в
41
+ `docs/plans/<линия>.md`; закрытая линия уезжает в `docs/archive/` или удаляется.
42
+
43
+ ```bash
44
+ npm run check:specs # после вливания: привязки на месте, сценарии не потерялись
45
+ ```
46
+
47
+ ## 2. Папка задачи разбирается
48
+
49
+ Целиком в архив не переносится: `docs/archive/` — место для записей о состоявшемся, которые
50
+ кто-то читает, а не свалка ходов работы.
51
+
52
+ | Файл | Куда |
53
+ | ------------- | ------------------------------------------------------------------------------------------------------------------ |
54
+ | `grill.md` | в `docs/archive/` — ответы владельца невосстановимы, и это единственная запись о том, почему задача поставлена так |
55
+ | `progress.md` | в `docs/archive/`, если в нём есть решения по ходу с причинами; иначе удаляется |
56
+ | `plan.md` | удаляется — после выкатки на его вопрос отвечает код, а на «как работает» отвечает спек домена |
57
+
58
+ Уезжающее складывается одним файлом с говорящим именем, а не папкой из трёх:
59
+
60
+ ```bash
61
+ cat docs/tasks/<КЛЮЧ>-<номер>-<slug>/grill.md > docs/archive/<ЧТО_РЕШАЛИ>.md
62
+ rm -r docs/tasks/<КЛЮЧ>-<номер>-<slug>
63
+ ```
64
+
65
+ Разбор идёт в том же отчёте, что и работа: папка, оставленная до мержа, попадает в главную
66
+ ветку и читается там как текущая.
67
+
68
+ ## 3. Сверка
69
+
70
+ ```bash
71
+ npm run check:board # папка закрытой задачи среди текущих, брошенные черновики
72
+ npm run check:specs # договорённость влита, привязки на месте
73
+ npm run check:docs # пути, названные в текстах, существуют
74
+ ```
75
+
76
+ ## Ловушки
77
+
78
+ - **Папку разбирают до мержа — после него о ней уже никто не вспомнит.** Сверка очереди
79
+ считает задачу закрытой по мержу: до него папка среди текущих законна, а после за неё никто
80
+ не отвечает — работа ушла в следующую задачу, и находка приходит в чужой заход. Дважды
81
+ подряд папка закрытой задачи так и уехала в главную ветку. Разбирают её тем же PR, что и
82
+ работу, а не отдельным заходом «потом».
83
+ - **Вливание после мержа не делается.** В главной ветке тогда лежит раздел «предложено, но не
84
+ выкачено» с тем, что работает месяц, — беззвучная ложь, тем убедительнее, чем старше.
85
+ - **Номера сценариев при вливании не пересчитываются.** Идентификатор — ключ связи с тестами;
86
+ сдвиг рвёт сверку у соседей, которых правка не касалась.
87
+ - **Правило без привязки в спек домена не въезжает.** Кода, который его исполняет, нет —
88
+ значит это намерение, и место ему в открытых вопросах домена, а не в правилах.
89
+ - **Архив не обновляется после выкатки.** Уехавшее туда описывает день переезда, и правится
90
+ оно только вместе с признанием, что описывало неверно.