@bonesofspring/ai-rules 0.1.36 → 0.1.37

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonesofspring/ai-rules",
3
- "version": "0.1.36",
3
+ "version": "0.1.37",
4
4
  "description": "Presets of Cursor and Claude rules/commands for Revy Ross personal use",
5
5
  "license": "MIT",
6
6
  "author": "Revy Ross",
@@ -36,6 +36,7 @@
36
36
  | `code-review-mr.mdc` | Чеклист ревью MR, в т.ч. HTTP‑клиент и тесты |
37
37
  | `tests-unit.mdc` | Unit‑тесты и behavior‑тесты HTTP‑клиента |
38
38
  | `playwright-agents.mdc`, `tests-e2e-structure.mdc` | E2E |
39
+ | `react-ui.mdc` | React/Next UI: структура компонентов, соседние `ComponentName.data.ts` / `.utils.ts`, стили, пропсы |
39
40
 
40
41
  **Коллизии формулировок:** если в разных `.mdc` расходятся детали **импорта типов**, источник правды — **`types-public-imports.mdc`** (`@/types`, `@/types/enums`); по **импорту из API‑слоя** (store, UI, прочий код вне `app/src/api/**`) — **`api-public-imports.mdc`** (`@/api`), в том же смысле что правило ESLint `no-restricted-imports` в `app/eslint.config.mjs`.
41
42
 
@@ -35,6 +35,12 @@ alwaysApply: true
35
35
  - сначала локально улучшить архитектуру минимальными шагами;
36
36
  - оставить код в консистентном состоянии.
37
37
 
38
+ # ESLint и плагины
39
+
40
+ - Учитывать **все активные правила ESLint** и **подключённые плагины** проекта (конфиг: `app/eslint.config.mjs`, базовые пресеты в т.ч. `@sh/eslint-config-react`, `@sh/eslint-config-boundaries` и локальные overrides).
41
+ - Новый или изменённый код не должен нарушать эти правила. Перед завершением правок по возможности прогонять ESLint на затронутых файлах.
42
+ - Отключение правила (`eslint-disable`) — только **точечно** (строка/небольшой блок) и с **кратким комментарием**, зачем это нужно; отключать «на весь файл» без веской причины не следует.
43
+
38
44
  # Требование к агенту
39
45
 
40
46
  При каждом изменении:
@@ -0,0 +1,25 @@
1
+ ---
2
+ description: Порядок CSS-свойств по Stylelint (idiomatic-order) — для любых стилей в проекте
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Порядок CSS-свойств (как в Stylelint)
7
+
8
+ Действует для **любого** CSS в репозитории: `.css`, стилевые блоки в `styles.ts` / `styles.tsx`, `styled` / Linaria и другой CSS-in-JS в `.ts` / `.tsx`, если этот код попадает под `yarn lint:css`.
9
+
10
+ Источник: `app/.stylelintrc` → `@sh/stylelint-config-react` → пакет **`stylelint-config-idiomatic-order`** (правило `order/properties-order`). Свойства, не попавшие в список, идут **в конце блока в алфавитном порядке** (`unspecified: bottomAlphabetical`).
11
+
12
+ Пиши объявления в **одном** блоке в такой последовательности групп:
13
+
14
+ 1. **`composes`** — только для CSS Modules (если есть).
15
+ 2. **`all`**
16
+ 3. **Позиционирование:** `position`, `z-index`, затем `top`, `right`, `bottom`, `left`.
17
+ 4. **Отображение и раскладка:** `display`, `overflow`.
18
+ 5. **Размеры:** `width`, `min-width`, `max-width`, `height`, `min-height`, `max-height`, `box-sizing`.
19
+ 6. **Flex:** `flex`, `flex-basis`, `flex-direction`, `flex-flow`, `flex-grow`, `flex-shrink`, `flex-wrap`, `align-content`, `align-items`, `align-self`, `justify-content`, `order`.
20
+ 7. **Внутренние отступы:** `padding-top`, `padding-right`, `padding-bottom`, `padding-left`.
21
+ 8. **Рамка:** общие `border`, `border-width`, `border-style`, `border-color`, `border-radius`; затем для сторон **сверху по часовой** — `border-top` и его `-width`, `-style`, `-color`, `-radius`, то же для `right`, `bottom`, `left`.
22
+ 9. **Внешние отступы:** `margin-top`, `margin-right`, `margin-bottom`, `margin-left`.
23
+ 10. **Остальные свойства** — после перечисленных, **по алфавиту** (типографика, фон, анимации, `cursor`, и т.д.).
24
+
25
+ Автоисправление из каталога `app`: `yarn lint:css --fix` (проверяет `**/*.{css,ts}`).
@@ -0,0 +1,55 @@
1
+ ---
2
+ description: Стили компонентов — колокация, импорты, корневой styled как Root
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Стили только рядом с компонентом
7
+
8
+ ## Имя корневого styled-элемента: `Root`
9
+
10
+ - В `styles.ts` (или аналоге) **корневой** styled-элемент — тот, что оборачивает весь JSX компонента — экспортируется как **`Root`**.
11
+ - В разметке: `<s.Root>...</s.Root>` при `import * as s from './styles'`.
12
+ - Вложенные и соседние примитивы именуются по смыслу: `Title`, `List`, `Item`, `Header` и т.д.
13
+ - Если нет одной styled-обёртки на весь компонент (только фрагмент или один нативный тег без своего styled), экспорта `Root` может не быть. Когда вводится **одна** внешняя styled-обёртка всего JSX — она называется **`Root`**, а не `Container`, `Wrapper`, `Block` и т.п.
14
+
15
+ ```tsx
16
+ // ✅ Хорошо
17
+ export const Root = styled.div` ... `
18
+ // в компоненте: <s.Root>...</s.Root>
19
+
20
+ // ❌ Плохо для единственной обёртки всего компонента
21
+ export const Service = styled.div` ... `
22
+ ```
23
+
24
+ ## Правило
25
+
26
+ **Запрещено** импортировать модули стилей, которые лежат в каталоге **другого** UI-компонента или блока (не в том же каталоге, что и текущий файл).
27
+
28
+ Под «модулями стилей» имеются в виду в первую очередь:
29
+
30
+ - `styles.ts` / `styles.tsx` рядом с компонентом;
31
+ - `*.module.css`, `*.module.scss` и аналоги, принадлежащие конкретному компоненту;
32
+ - любые файлы, которые **экспортируют только styled-примитивы** для одного компонента.
33
+
34
+ ## Разрешено
35
+
36
+ - `import * as s from './styles'` — стили **в той же папке**, что и компонент.
37
+ - Импорты **общих** примитивов дизайн-системы, токенов, общих UI из `@/ui/components/...` или пакетов, если это **не** приватный `styles` чужой фичи.
38
+ - Повторное использование визуала через **сам компонент** (композиция), а не через его `styles`.
39
+
40
+ ## Примеры
41
+
42
+ ```tsx
43
+ // ✅ Хорошо — локальный styles
44
+ import * as s from './styles'
45
+
46
+ // ❌ Плохо — стили родителя/соседа
47
+ import * as s from '../../styles'
48
+ import * as s from '../RequestForAnalysisServices/styles'
49
+ ```
50
+
51
+ ## Почему
52
+
53
+ - Единое имя **`Root`** ускоряет чтение: сразу видно входную точку разметки компонента.
54
+ - Стили и разметка компонента должны меняться вместе, без скрытой связи через чужие файлы.
55
+ - Упрощается рефакторинг и поиск владельца стилей.
@@ -1,11 +1,14 @@
1
1
  ---
2
2
  description: Избегать спред-а пропов при передаче в компоненты
3
3
  alwaysApply: true
4
+ globs: app/src/**/*.tsx
4
5
  ---
5
6
 
6
7
  # Не использовать спред пропов при передаче в компоненты
7
8
 
8
- При вызове React-компонентов **передавать пропы явно**, а не через spread (`{...props}`).
9
+ При вызове **пользовательских** React-компонентов (имя с заглавной буквы: `IconBox`, `TextField`, ваши `FooBar`) **передавать пропы явно**, а не через spread (`{...props}`, `{...obj}`).
10
+
11
+ **Агентам и при ревью:** не «упрощать» JSX через объект с последующим spread — это нарушение. Если ветвление по пропам длинное, используйте два явных JSX-блока (`condition ? <A … /> : <B … />`) или отдельные маленькие компоненты, а не `{...mergedProps}`.
9
12
 
10
13
  ## Почему
11
14
 
@@ -13,6 +16,11 @@ alwaysApply: true
13
16
  - Упрощает рефакторинг и поиск использований.
14
17
  - Снижает риск случайно пробросить лишние или устаревшие пропы.
15
18
 
19
+ ## Проверка в репозитории
20
+
21
+ - Для файлов `app/src/ui/**/*.tsx` включено ESLint-правило `react/jsx-props-no-spreading` (`app/eslint.config.mjs`): несоблюдение увидит линтер и CI.
22
+ - Легитимное исключение в конкретном месте — **однострочный** `eslint-disable-next-line react/jsx-props-no-spreading` с кратким комментарием «почему»; для редких обёрток допустим disable на файл (как в `PromocodeInput`).
23
+
16
24
  ## Примеры
17
25
 
18
26
  ```tsx
@@ -23,6 +31,10 @@ return <Child {...commonProps} />
23
31
  // ❌ Плохо
24
32
  return <Child {...props} />
25
33
 
34
+ // ❌ Плохо (spread из соседнего модуля стилей тоже не оправдание)
35
+ const iconProps = cond ? { name, size: 'm' } : { name, size: 'm', ...styles.IconBoxAccent }
36
+ return <IconBox {...iconProps} />
37
+
26
38
  // ✅ Хорошо
27
39
  return (
28
40
  <Child
@@ -31,9 +43,20 @@ return (
31
43
  c={c}
32
44
  />
33
45
  )
46
+
47
+ // ✅ Хорошо — явные пропсы по веткам
48
+ return cond ? (
49
+ <IconBox name={name} size="m" variant="warning" />
50
+ ) : (
51
+ <IconBox
52
+ customColors={styles.IconBoxAccent.customColors}
53
+ name={name}
54
+ size="m"
55
+ />
56
+ )
34
57
  ```
35
58
 
36
59
  ## Исключения
37
60
 
38
- - Передача всех пропов в нативный DOM-элемент (`<div {...rest} />`) допустима, если `rest` содержит только валидные HTML-атрибуты.
39
- - Делегирование пропов в обёртку (wrapper) допустимо, если это явно документировано и обосновано.
61
+ - Передача пропов в **нативный** DOM-элемент (`<div {...rest} />`) допустима, если `rest` содержит только валидные HTML-атрибуты.
62
+ - Делегирование пропов в обёртку (wrapper) допустимо, если это явно документировано и обосновано; при необходимости пометьте файл или строку через ESLint-disable, как выше.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Паттерны React/Next UI и стилей (preset)
3
- globs: app/src/ui/**/*.tsx
3
+ globs: app/src/ui/**/*.tsx,app/src/ui/**/*.ts
4
4
  alwaysApply: false
5
5
  ---
6
6
 
@@ -26,10 +26,28 @@ alwaysApply: false
26
26
  - Папка с именем компонента:
27
27
  - `ComponentName.tsx`
28
28
  - файлы стилей по принятой схеме;
29
- - опционально: `types.ts`, `hooks.ts`.
29
+ - опционально: `types.ts`, `ComponentName.hooks.ts` (см. ниже про префикс).
30
+
31
+ ## Вспомогательные модули рядом с компонентом (именование)
32
+
33
+ **Префикс имени файла = публичное имя компонента** (как у `ComponentName.tsx` в этой папке), в **PascalCase**. Не вводить отдельные «говорящие» имена файлов по смыслу содержимого (`analysisPreparationIconMap.ts`, `buildAnalysisIdToNameMap.ts` и т.п.) — так теряется связь с компонентом и плодятся одноразовые названия.
34
+
35
+ **Суффикс по роли:**
36
+
37
+ | Суффикс | Назначение | Примеры содержимого |
38
+ |--------|------------|---------------------|
39
+ | `ComponentName.data.ts` | Статические данные и конфигурация для UI | мапы `id → иконка/лейбл`, константы списков, таблицы соответствий для отображения |
40
+ | `ComponentName.utils.ts` | Чистые функции без React | форматирование, предобработка пропсов/данных для рендера, `build…`/`map…`‑хелперы |
41
+ | `ComponentName.hooks.ts` | Хуки, используемые только этим блоком | локальные `use…` (если не вынесены в `src/ui/hooks/**`) |
42
+
43
+ - Несколько констант/мапов или несколько функций — **по-прежнему один** `.data.ts` и один `.utils.ts`, не дробить по «темам» отдельными файлами без веской причины (размер, разные зоны ответственности на уровне подкомпонентов).
44
+ - Если логика принадлежит **подкомпоненту** в подпапке (`components/Child/Child.tsx`), те же правила применяются к **`Child.data.ts`**, **`Child.utils.ts`** относительно этого подкомпонента.
45
+ - Тесты для утилит и данных — рядом в `__tests__/` или с суффиксом `.test.ts`, согласно `tests-unit.mdc`, с тем же префиксом (`RequestForAnalysisRecommendations.utils.test.ts` и т.д.).
30
46
 
31
47
  # Стили и дизайн‑токены
32
48
 
49
+ - **Корневой** styled-элемент компонента в соседнем `styles` — **`Root`** (`<s.Root>`). Подробнее: `no-cross-component-styles-import.mdc`.
50
+ - Порядок объявлений в CSS / `styled` — как требует Stylelint: см. `css-property-order-stylelint.mdc`.
33
51
  - Для визуала использовать **тот стек стилей и токенов, который уже в проекте** (переменные, тема, общие классы, дизайн‑пакет).
34
52
  - Избегать:
35
53
  - inline‑стилей, кроме простых случаев;
@@ -39,6 +57,7 @@ alwaysApply: false
39
57
 
40
58
  # Пропсы и типизация
41
59
 
60
+ - **Не передавать пропы в компоненты через spread** (`<Foo {...x} />`). Только явные атрибуты; подробности и исключения — `no-props-spread.mdc` (в `app/src/ui` это дополнительно ловит ESLint).
42
61
  - Описывать пропсы через `type Props = { ... }` или `interface Props { ... }`.
43
62
  - Не использовать `any`; при необходимости:
44
63
  - обобщения (`<T>`), `unknown`, тип‑предикаты и user‑defined type guards.
@@ -15,6 +15,7 @@ alwaysApply: false
15
15
  - **Именование unit‑тестов** (строки в `describe` / `it` / `test`):
16
16
  - формулировки **только на русском языке** — понятные бизнес‑фразы (что проверяется и какой ожидается результат);
17
17
  - **каждое предложение** в названии **начинается с заглавной буквы** (в том числе после `.`, `!`, `?` и при нескольких предложениях в одной строке); первая буква всей строки — тоже заглавная.
18
+ - **Проверка в CI:** ESLint (`jest/valid-title` в `app/eslint.config.mjs`) требует, чтобы строка начиналась с русской заглавной (А–Я, Ё), и запрещает пробел после точки, за которым сразу идёт строчная буква (типичный случай нарушения «с заглавной после точки»).
18
19
 
19
20
  ```typescript
20
21
  // ✅ Хорошо