@bonesofspring/ai-rules 0.1.36 → 0.1.39
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/README.md +7 -3
- package/bin/cli.js +55 -31
- package/package.json +1 -1
- package/presets/claude/next/CLAUDE.md +24 -5
- package/presets/claude/next/agents/code-reviewer.md +56 -0
- package/presets/claude/next/agents/debugger.md +58 -0
- package/presets/claude/next/agents/feature-developer.md +45 -0
- package/presets/claude/next/agents/qa-tester.md +54 -0
- package/presets/claude/next/agents/solution-architect.md +70 -0
- package/presets/claude/next/agents/task-analyst.md +105 -0
- package/presets/claude/next/agents/task-router.md +105 -0
- package/presets/claude/next/commands/README.md +5 -1
- package/presets/claude/next/commands/feature-continue.md +46 -0
- package/presets/claude/next/commands/feature-start.md +25 -0
- package/presets/claude/next/commands/task-continue.md +43 -0
- package/presets/claude/next/commands/task.md +40 -0
- package/presets/claude/next/commands/technical-retro.md +53 -0
- package/presets/claude/next/rules/README.md +47 -11
- package/presets/claude/next/rules/api-and-data/README.md +7 -1
- package/presets/claude/next/rules/api-and-data/api-services.md +57 -0
- package/presets/claude/next/rules/api-and-data/http-client.md +40 -0
- package/presets/claude/next/rules/api-and-data/store-rtk.md +65 -0
- package/presets/claude/next/rules/architecture/README.md +11 -1
- package/presets/claude/next/rules/architecture/api-public-imports.md +25 -0
- package/presets/claude/next/rules/architecture/architecture-boundaries.md +67 -0
- package/presets/claude/next/rules/architecture/feature-delivery-workflow.md +99 -0
- package/presets/claude/next/rules/architecture/layer-barrel-exports.md +53 -0
- package/presets/claude/next/rules/architecture/types-public-imports.md +28 -0
- package/presets/claude/next/rules/stack/README.md +9 -1
- package/presets/claude/next/rules/stack/arrow-functions.md +40 -0
- package/presets/claude/next/rules/stack/navigation-router.md +56 -0
- package/presets/claude/next/rules/stack/next-app-core.md +83 -0
- package/presets/claude/next/rules/stack/no-type-assertion.md +52 -0
- package/presets/claude/next/rules/stack/types-jsdoc.md +37 -0
- package/presets/claude/next/rules/testing/README.md +9 -1
- package/presets/claude/next/rules/testing/playwright-agents.md +69 -0
- package/presets/claude/next/rules/testing/tests-e2e-structure.md +52 -0
- package/presets/claude/next/rules/testing/tests-unit.md +66 -0
- package/presets/claude/next/rules/tooling-and-review/README.md +12 -1
- package/presets/claude/next/rules/tooling-and-review/agent-team-intake.md +9 -0
- package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +97 -0
- package/presets/claude/next/rules/tooling-and-review/code-quality.md +50 -0
- package/presets/claude/next/rules/tooling-and-review/code-review-mr.md +67 -0
- package/presets/claude/next/rules/tooling-and-review/package-manager.md +20 -0
- package/presets/claude/next/rules/tooling-and-review/post-change-lint.md +43 -0
- package/presets/claude/next/rules/ui-and-accessibility/README.md +8 -1
- package/presets/claude/next/rules/ui-and-accessibility/component-styles.md +50 -0
- package/presets/claude/next/rules/ui-and-accessibility/css-property-order.md +20 -0
- package/presets/claude/next/rules/ui-and-accessibility/no-props-spread.md +52 -0
- package/presets/claude/next/rules/ui-and-accessibility/react-ui.md +90 -0
- package/presets/claude/next/team/README.md +64 -0
- package/presets/claude/next/team/tasks/.gitkeep +1 -0
- package/presets/cursor/next/agents/README.md +25 -0
- package/presets/cursor/next/agents/code-reviewer.md +57 -0
- package/presets/cursor/next/agents/debugger.md +59 -0
- package/presets/cursor/next/agents/feature-developer.md +46 -0
- package/presets/cursor/next/agents/qa-tester.md +55 -0
- package/presets/cursor/next/agents/solution-architect.md +71 -0
- package/presets/cursor/next/agents/task-analyst.md +111 -0
- package/presets/cursor/next/agents/task-router.md +106 -0
- package/presets/cursor/next/commands/README.md +33 -1
- package/presets/cursor/next/commands/feature-continue.md +14 -0
- package/presets/cursor/next/commands/feature-start.md +28 -0
- package/presets/cursor/next/commands/task-continue.md +43 -0
- package/presets/cursor/next/commands/task.md +40 -0
- package/presets/cursor/next/commands/technical-retro.md +76 -0
- package/presets/cursor/next/hooks/chain-team-phases.sh +216 -0
- package/presets/cursor/next/hooks.json +11 -0
- package/presets/cursor/next/rules/README.md +11 -3
- package/presets/cursor/next/rules/agent-team-intake.mdc +14 -0
- package/presets/cursor/next/rules/agent-team-orchestrator.mdc +102 -0
- package/presets/cursor/next/rules/api-public-imports.mdc +1 -0
- package/presets/cursor/next/rules/api-services.mdc +1 -0
- package/presets/cursor/next/rules/architecture-boundaries.mdc +1 -1
- package/presets/cursor/next/rules/code-quality-and-refactoring.mdc +9 -0
- package/presets/cursor/next/rules/code-review-mr.mdc +6 -7
- package/presets/cursor/next/rules/css-property-order-stylelint.mdc +25 -0
- package/presets/cursor/next/rules/feature-delivery-workflow.mdc +5 -5
- package/presets/cursor/next/rules/layer-barrel-exports.mdc +58 -0
- package/presets/cursor/next/rules/next-app-core.mdc +1 -1
- package/presets/cursor/next/rules/no-cross-component-styles-import.mdc +55 -0
- package/presets/cursor/next/rules/no-props-spread.mdc +26 -3
- package/presets/cursor/next/rules/package-manager.mdc +25 -0
- package/presets/cursor/next/rules/post-change-lint.mdc +48 -0
- package/presets/cursor/next/rules/react-ui.mdc +31 -2
- package/presets/cursor/next/rules/technical-retro.mdc +5 -51
- package/presets/cursor/next/rules/tests-unit.mdc +1 -0
- package/presets/cursor/next/rules/types-public-imports.mdc +1 -0
- package/presets/cursor/next/team/README.md +106 -0
- package/presets/cursor/next/team/tasks/.gitkeep +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Orchestrates the agent team via task-router and pipeline.json. Use for /task, /task-continue, /feature-start, task decomposition, or when the user describes a feature, bug, or review request.
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Agent team orchestrator
|
|
7
|
+
|
|
8
|
+
Parent agent = **manager**. Router plans; specialists execute. Artifacts: `.cursor/team/tasks/<slug>/`.
|
|
9
|
+
|
|
10
|
+
## Entry points
|
|
11
|
+
|
|
12
|
+
| Command | When |
|
|
13
|
+
|---------|------|
|
|
14
|
+
| **`/task <desc>`** | **Preferred** — router → dynamic pipeline → first agent |
|
|
15
|
+
| `/task-continue <slug>` | After human gate or pause |
|
|
16
|
+
| `/feature-start <desc>` | Legacy: analyst-only start (no router) |
|
|
17
|
+
| `/feature-continue <slug>` | Alias of task-continue |
|
|
18
|
+
| `/technical-retro [slug]` | Retro with agent team block |
|
|
19
|
+
|
|
20
|
+
## Roles
|
|
21
|
+
|
|
22
|
+
| Agent | readonly | Typical intent |
|
|
23
|
+
|-------|----------|----------------|
|
|
24
|
+
| `task-router` | yes | Every `/task` — writes `pipeline.json` |
|
|
25
|
+
| `task-analyst` | yes | feature, refactor, test-only |
|
|
26
|
+
| `solution-architect` | yes | spike, complex cross-layer feature |
|
|
27
|
+
| `debugger` | no | bugfix |
|
|
28
|
+
| `feature-developer` | no | feature, bugfix, refactor |
|
|
29
|
+
| `code-reviewer` | yes | most pipelines, review-only |
|
|
30
|
+
| `qa-tester` | no | feature, bugfix, test-only |
|
|
31
|
+
|
|
32
|
+
Full prompts: `.cursor/agents/*.md`. Artifact conventions: `.cursor/team/README.md`.
|
|
33
|
+
|
|
34
|
+
## Dynamic pipeline
|
|
35
|
+
|
|
36
|
+
```mermaid
|
|
37
|
+
flowchart TD
|
|
38
|
+
task["/task prompt"]
|
|
39
|
+
router["task-router"]
|
|
40
|
+
pipeline["pipeline.json"]
|
|
41
|
+
step0["steps 0..N"]
|
|
42
|
+
gate{"humanGates?"}
|
|
43
|
+
hook["subagentStop hook"]
|
|
44
|
+
retro["/technical-retro"]
|
|
45
|
+
|
|
46
|
+
task --> router
|
|
47
|
+
router --> pipeline
|
|
48
|
+
pipeline --> step0
|
|
49
|
+
step0 --> gate
|
|
50
|
+
gate -->|"/task-continue"| step0
|
|
51
|
+
step0 --> hook
|
|
52
|
+
hook --> step0
|
|
53
|
+
step0 --> retro
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Source of truth for order:** `pipeline.json` → `steps[]`. Never hardcode analyst → dev → review → QA when `pipeline.json` exists.
|
|
57
|
+
|
|
58
|
+
## status.json (pipeline mode)
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"slug": "...",
|
|
63
|
+
"intent": "feature",
|
|
64
|
+
"pipelineIndex": 0,
|
|
65
|
+
"currentAgent": "task-analyst",
|
|
66
|
+
"phase": "executing",
|
|
67
|
+
"state": "in_progress",
|
|
68
|
+
"awaitingHumanGate": false
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
| state | Meaning |
|
|
73
|
+
|-------|---------|
|
|
74
|
+
| `in_progress` | Current step running |
|
|
75
|
+
| `completed` | Current step done; hook advances |
|
|
76
|
+
| `awaiting_approval` | Human gate; wait for `/task-continue` |
|
|
77
|
+
| `changes_requested` | Reviewer blocked; re-run developer |
|
|
78
|
+
|
|
79
|
+
## Rules (strict)
|
|
80
|
+
|
|
81
|
+
1. **`/task` always starts with task-router** (except user says "skip router" with documented pipeline).
|
|
82
|
+
2. Read `pipeline.json` before every subagent invocation.
|
|
83
|
+
3. One role per Task/subagent call.
|
|
84
|
+
4. **Never** skip `humanGates` without `/task-continue` or explicit user approval.
|
|
85
|
+
5. Persist handoffs to disk (`brief.md`, `decomposition.md`, `debug-report.md`, `architecture.md`).
|
|
86
|
+
6. On `changes_requested`: re-invoke `feature-developer`, then `code-reviewer` — do not advance `pipelineIndex` until review passes.
|
|
87
|
+
7. When all steps complete, suggest `/technical-retro <slug>`.
|
|
88
|
+
8. If `autoChain: false` in pipeline, do not rely on hook — manual step only.
|
|
89
|
+
|
|
90
|
+
## Invoking agents
|
|
91
|
+
|
|
92
|
+
Use Task tool or `/agent-name`. Pass: slug, artifact paths, step `scope` if set.
|
|
93
|
+
|
|
94
|
+
After each agent completes, ensure `status.json` has `state: completed` (or `awaiting_approval` if gate applies).
|
|
95
|
+
|
|
96
|
+
## Legacy mode
|
|
97
|
+
|
|
98
|
+
If `pipeline.json` is missing (old `/feature-start` tasks), fall back to fixed phases: analysis → development → review → testing. Hook supports both.
|
|
99
|
+
|
|
100
|
+
## Auto-detection (optional)
|
|
101
|
+
|
|
102
|
+
When user describes a **task** (not a question "how does X work"), suggest `/task <their message>` or run router proactively if they agree.
|
|
@@ -7,6 +7,7 @@ alwaysApply: true
|
|
|
7
7
|
|
|
8
8
|
- **Публичный API слоя API** — barrel `app/src/api/index.ts`. Для файлов **вне** `app/src/api/**` импортировать сервисы, клиенты, эндпоинты и публичные типы API **только** как `import … from '@/api'` (или `from '@/api/index'` при необходимости явного пути).
|
|
9
9
|
- **Запрещено** для таких потребителей обходить barrel: любой импорт вида `@/api/<что‑угодно>`, кроме `@/api/index`. Это дублирует правило ESLint `no-restricted-imports` в `app/eslint.config.mjs` (паттерн `@/api/*` с исключением `@/api/index`).
|
|
10
|
+
- При **добавлении** публичного символа в регламентированный слой — реэкспорт в корневой barrel по **`layer-barrel-exports.mdc`**.
|
|
10
11
|
|
|
11
12
|
## Внутри слоя `app/src/api/**`
|
|
12
13
|
|
|
@@ -50,6 +50,7 @@ alwaysApply: false
|
|
|
50
50
|
|
|
51
51
|
При добавлении/изменении API‑метода:
|
|
52
52
|
- Следовать существующим сервисам и мапперам как эталону.
|
|
53
|
+
- Пройти чеклист barrel-экспортов (**`layer-barrel-exports.mdc`**): локальный `index.ts` → фасад слоя → корневой barrel.
|
|
53
54
|
- Не смешивать слой API и UI/store:
|
|
54
55
|
- компоненты не должны зависеть от DTO;
|
|
55
56
|
- store не должен сам собирать URL/коды эндпоинтов и не обходить сервисы; **транспортный тип ответа** и **контракт ошибки** из `@/types` (как у прикладного клиента) допустимы во thunk при разборе `catch`/payload, если так выстроен сервис (см. `store-rtk.mdc`, `http-client.mdc`).
|
|
@@ -43,7 +43,7 @@ alwaysApply: true
|
|
|
43
43
|
|
|
44
44
|
- Всегда использовать алиас `@/...` для импортов между слоями.
|
|
45
45
|
- Внутри одного модуля/фичи можно использовать относительные импорты, но **без подъёма выше корня фичи** (избегать `../../../`).
|
|
46
|
-
- При обращении из компонентов, хуков, утилит и других модулей к чужому слою или фиче использовать только **public API** (barrel/index‑файлы и явно экспортируемые сущности), не делать deep‑импорты внутренних файлов других фич; для API‑слоя снаружи `app/src/api/**` — **`api-public-imports.mdc`** (только `@/api`).
|
|
46
|
+
- При обращении из компонентов, хуков, утилит и других модулей к чужому слою или фиче использовать только **public API** (barrel/index‑файлы и явно экспортируемые сущности), не делать deep‑импорты внутренних файлов других фич; для регламентированных слоёв — **`layer-barrel-exports.mdc`** и `*-public-imports.mdc`; для API‑слоя снаружи `app/src/api/**` — **`api-public-imports.mdc`** (только `@/api`).
|
|
47
47
|
- При добавлении нового кода проверять:
|
|
48
48
|
- если модуль переиспользуемый — он должен зависеть только от более "низких" слоёв (types, utils, api), но не от страниц.
|
|
49
49
|
|
|
@@ -35,10 +35,19 @@ alwaysApply: true
|
|
|
35
35
|
- сначала локально улучшить архитектуру минимальными шагами;
|
|
36
36
|
- оставить код в консистентном состоянии.
|
|
37
37
|
|
|
38
|
+
# ESLint, Stylelint и плагины
|
|
39
|
+
|
|
40
|
+
- Учитывать **все активные правила ESLint** и **подключённые плагины** проекта (конфиг: `app/eslint.config.mjs`, базовые пресеты в т.ч. `@sh/eslint-config-react`, `@sh/eslint-config-boundaries` и локальные overrides).
|
|
41
|
+
- Учитывать **Stylelint** для CSS и CSS-in-JS (конфиг: `app/.stylelintrc`; порядок свойств — `css-property-order-stylelint.mdc`).
|
|
42
|
+
- Новый или изменённый код не должен нарушать эти правила.
|
|
43
|
+
- После **каждого** изменения кода агент **обязан** выполнить **`post-change-lint.mdc`**: полный прогон **`lint:js`** и **`lint:css`**, анализ вывода, исправление срабатываний в зоне задачи.
|
|
44
|
+
- Отключение правила (`eslint-disable`) — только **точечно** (строка/небольшой блок) и с **кратким комментарием**, зачем это нужно; отключать «на весь файл» без веской причины не следует.
|
|
45
|
+
|
|
38
46
|
# Требование к агенту
|
|
39
47
|
|
|
40
48
|
При каждом изменении:
|
|
41
49
|
- Поддерживать принцип **“boy scout rule”**:
|
|
42
50
|
- оставлять модуль в немного лучшем состоянии, чем до изменения (простые, безопасные улучшения).
|
|
43
51
|
- Не жертвовать архитектурой и слоями ради краткости реализации.
|
|
52
|
+
- **Не завершать задачу**, пока не пройдены обязательные линтеры (`post-change-lint.mdc`).
|
|
44
53
|
|
|
@@ -18,6 +18,7 @@ alwaysApply: true
|
|
|
18
18
|
- **Импорты и организация кода**:
|
|
19
19
|
- Использование алиаса `@/...` вместо относительных импортов выше по дереву.
|
|
20
20
|
- Отсутствие deep‑импортов во внешние фичи; использование только public API; в файлах вне `app/src/api/**` импорты из API — только `from '@/api'` (`api-public-imports.mdc`, дублирует ESLint).
|
|
21
|
+
- При новых/изменённых модулях в регламентированных слоях — реэкспорт публичных символов в корневой barrel по **`layer-barrel-exports.mdc`**.
|
|
21
22
|
- Размещение новых файлов в корректных слоях и директориях фич.
|
|
22
23
|
- **Типы и TS‑строгость**:
|
|
23
24
|
- Не допускать новых `any`; предпочитать доменные типы из `@/types` (barrel, см. `types-public-imports.mdc`).
|
|
@@ -32,13 +33,11 @@ alwaysApply: true
|
|
|
32
33
|
- либо e2e‑сценарии/спеки отражают новую логику (`playwright-agents.mdc`, `tests-e2e-structure.mdc`).
|
|
33
34
|
- При правках **общего HTTP‑клиента** — наличие/актуальность **behavior‑тестов клиента** (`http-client.mdc`, `tests-unit.mdc`).
|
|
34
35
|
- Указывать, какие именно тесты стоит добавить или поправить.
|
|
35
|
-
- **Линтеры (обязательно)
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
- При **имплементации правок** по итогам ревью или любой работе «как к MR»: после изменений снова выполнить `bun run lint:js` (и при необходимости `bun run lint:css`); не считать задачу завершённой, пока в изменённых файлах остаются исправимые предупреждения ESLint, которые относятся к этой задаче (исключение — явно устаревший легаси вне скоупа, с пометкой в ответе).
|
|
41
|
-
- При желании полной валидации, как в CI: `bun run lint` (ESLint + Stylelint + `type-check`) — уместно перед итогом крупного MR.
|
|
36
|
+
- **Линтеры (обязательно)** — **`post-change-lint.mdc`**:
|
|
37
|
+
- Перед финализацией отчёта по ревью и после любых правок по итогам ревью: полный прогон **`lint:js`** и **`lint:css`** из `app/`.
|
|
38
|
+
- В отчёт включить **все сообщения ESLint и Stylelint (errors и warnings)** по файлам из диффа MR/ветки; запуск — по всему проекту, фильтрация вывода — к путям из `git diff`.
|
|
39
|
+
- Не считать ревью/правки завершёнными, пока линтеры не проходят или не зафиксирован блокер в ответе.
|
|
40
|
+
- Полная валидация как в CI: **`lint`** (= `lint:js` + `lint:css` + `type-check`) — уместна перед итогом крупного MR.
|
|
42
41
|
|
|
43
42
|
- **Глубина и формат ревью**
|
|
44
43
|
- Фокус на **изменениях MR** (дифф относительно целевой ветки), а не на всём проекте.
|
|
@@ -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}`).
|
|
@@ -9,15 +9,15 @@ alwaysApply: true
|
|
|
9
9
|
|
|
10
10
|
## Чеклист (порядок работ)
|
|
11
11
|
|
|
12
|
-
1. **Доменные типы** — `app/src/types/**`, экспорт через barrel `app/src/types/index.ts` (`types-public-imports.mdc
|
|
12
|
+
1. **Доменные типы** — `app/src/types/**`, экспорт через barrel `app/src/types/index.ts` (`types-public-imports.mdc`, **`layer-barrel-exports.mdc`**); JSDoc полей — `types-jsdoc.mdc`.
|
|
13
13
|
2. **Контракт API** — DTO ответов/запросов там, где принято в репо; целевые доменные типы в `@/types`.
|
|
14
14
|
3. **Мапперы** — DTO → домен в `*responseMappers.ts` или аналоге; чистые функции (`api-services.mdc`).
|
|
15
|
-
4. **Сервисы** — вызовы только через прикладные клиенты `app/src/api/clients/**`, public API модуля (`api-services.mdc`, `http-client.mdc
|
|
15
|
+
4. **Сервисы** — вызовы только через прикладные клиенты `app/src/api/clients/**`, public API модуля (`api-services.mdc`, `http-client.mdc`, **`layer-barrel-exports.mdc`**). Без `fetch` из UI/store.
|
|
16
16
|
5. **Состояние** — `createSlice` / `createAsyncThunk`, доменные модели в state (`store-rtk.mdc`); thunk вызывает сервисы, импортированные из `@/api` (`api-public-imports.mdc`).
|
|
17
17
|
6. **UI** — тонкие компоненты, типы из `@/types`, без DTO (`react-ui.mdc`, `architecture-boundaries.mdc`, `no-props-spread.mdc`).
|
|
18
18
|
7. **Моки** — по схеме репозитория, точка входа регистрации моков (например `app/src/mocks/index.js`).
|
|
19
19
|
8. **Тесты** — unit для мапперов и критичной логики (`tests-unit.mdc`); при смене HTTP‑клиента — behavior‑тесты клиента (`http-client.mdc`); e2e по `*.cases.md` (`tests-e2e-structure.mdc`, `playwright-agents.mdc`).
|
|
20
|
-
9. **Завершение** — из каталога `app
|
|
20
|
+
9. **Завершение** — **`post-change-lint.mdc`**: из каталога `app/` обязательно `lint:js` + `lint:css` (полный прогон, исправить срабатывания), затем `type-check`; менеджер пакетов — `package-manager.mdc`.
|
|
21
21
|
|
|
22
22
|
## Поток данных (ориентир)
|
|
23
23
|
|
|
@@ -40,10 +40,10 @@ flowchart LR
|
|
|
40
40
|
| Зона в репозитории | Правила Cursor (`.cursor/rules/`) |
|
|
41
41
|
|--------------------|-----------------------------------|
|
|
42
42
|
| `app/src/api/clients/**`, `app/src/lib/clients/**` | `http-client.mdc`; при изменении клиента — `tests-unit.mdc` (behavior‑тесты) |
|
|
43
|
-
| `app/src/api/services/**` | `api-services.mdc`; при необходимости `http-client.mdc` |
|
|
43
|
+
| `app/src/api/services/**` | `api-services.mdc`, `layer-barrel-exports.mdc`; при необходимости `http-client.mdc` |
|
|
44
44
|
| `app/src/store/**` | `store-rtk.mdc`, `architecture-boundaries.mdc`, `api-public-imports.mdc` |
|
|
45
45
|
| `app/src/ui/**` | `react-ui.mdc`, `no-props-spread.mdc`, `types-public-imports.mdc`, `api-public-imports.mdc` |
|
|
46
|
-
| `app/src/types/**` | `types-public-imports.mdc`, `types-jsdoc.mdc` |
|
|
46
|
+
| `app/src/types/**` | `types-public-imports.mdc`, `types-jsdoc.mdc`, `layer-barrel-exports.mdc` |
|
|
47
47
|
| `app/__tests__/e2e/**` | `tests-e2e-structure.mdc`, `playwright-agents.mdc` |
|
|
48
48
|
|
|
49
49
|
Специализированные `.mdc` с `globs` подмешиваются при работе с соответствующими файлами; эта матрица нужна, когда открыт другой файл или идёт общий чат.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Двухуровневые barrel-экспорты для слоёв с регламентированным public API
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Barrel-экспорты слоёв с public API
|
|
7
|
+
|
|
8
|
+
## Когда применять
|
|
9
|
+
|
|
10
|
+
Для **любого слоя** (каталога, пакета, bounded context), у которого:
|
|
11
|
+
|
|
12
|
+
- есть **корневой barrel** — единая точка импорта для внешних потребителей;
|
|
13
|
+
- deep-импорты внутрь слоя **запрещены** снаружи (ESLint `no-restricted-imports`, правила `*-public-imports.mdc`).
|
|
14
|
+
|
|
15
|
+
Примеры alias/entry point в разных проектах: `@/api`, `@/types`, `@/core`, `@/store`, `packages/foo`.
|
|
16
|
+
|
|
17
|
+
## Два уровня barrel
|
|
18
|
+
|
|
19
|
+
1. **Локальный** — `index.ts` модуля/фичи внутри слоя.
|
|
20
|
+
2. **Корневой public API** — barrel слоя (например `src/<layer>/index.ts`).
|
|
21
|
+
|
|
22
|
+
**Внутри** слоя — относительные импорты и пути между подмодулями. **Снаружи** — только корневой barrel и **явно разрешённые** вторичные entry points (если зафиксированы в правилах проекта, напр. `@/types/enums`).
|
|
23
|
+
|
|
24
|
+
## Что реэкспортировать наружу
|
|
25
|
+
|
|
26
|
+
Только символы, которые **должны быть доступны** потребителям слоя: публичные функции/сервисы/фасады, типы контракта, константы и helpers, нужные другим слоям или тестам.
|
|
27
|
+
|
|
28
|
+
**Не реэкспортировать:** внутренние адаптеры, мапперы, детали транспорта, промежуточные объекты для сборки фасада внутри слоя.
|
|
29
|
+
|
|
30
|
+
Группировка в корневом barrel — **по конвенции репозитория** (ориентир — соседние модули того же слоя).
|
|
31
|
+
|
|
32
|
+
## Чеклист агента (обязателен)
|
|
33
|
+
|
|
34
|
+
При добавлении или существенном расширении **модуля внутри регламентированного слоя**:
|
|
35
|
+
|
|
36
|
+
1. Определить слой, его **корневой barrel** и доп. entry points (`*-public-imports.mdc`).
|
|
37
|
+
2. Создать/обновить **локальный** `index.ts` — только публичные символы.
|
|
38
|
+
3. Если в слое есть **фасад/агрегатор** (`*ApiService.ts`, `rootReducer`, …) — подключить модуль там.
|
|
39
|
+
4. Добавить **реэкспорт** новых публичных символов в **корневой barrel** слоя.
|
|
40
|
+
5. **Проверка:** grep по имени символа или пути `./<Module>` в корневом barrel; снаружи слоя нет deep-импортов.
|
|
41
|
+
|
|
42
|
+
Модуль **не готов**, пока чеклист не пройден.
|
|
43
|
+
|
|
44
|
+
## Как найти регламентированные слои в репозитории
|
|
45
|
+
|
|
46
|
+
1. Правила `*-public-imports.mdc` в `.cursor/rules/`.
|
|
47
|
+
2. ESLint `no-restricted-imports` — паттерны `@/<layer>/*` с исключением barrel.
|
|
48
|
+
3. `architecture-boundaries.mdc`, README проекта.
|
|
49
|
+
|
|
50
|
+
## В этом репозитории
|
|
51
|
+
|
|
52
|
+
| Слой | Корневой barrel | Правило импортов |
|
|
53
|
+
|------|-------------------|------------------|
|
|
54
|
+
| API | `app/src/api/index.ts` | `api-public-imports.mdc` |
|
|
55
|
+
| Types | `app/src/types/index.ts` | `types-public-imports.mdc` (+ `@/types/enums`) |
|
|
56
|
+
| Core | `app/src/core/index.ts` | ESLint: `@/core/index` |
|
|
57
|
+
|
|
58
|
+
Иллюстрация двух уровней (API): локальный `services/.../<Feature>/index.ts` → фасад `*ApiService.ts` → `app/src/api/index.ts`.
|
|
@@ -83,5 +83,5 @@ alwaysApply: true
|
|
|
83
83
|
- Найти в соответствующей директории похожие примеры и **копировать архитектурный паттерн** (структура файлов, типы, именование).
|
|
84
84
|
- Не упрощать архитектуру в ущерб существующим слоям (не тянуть DTO и HTTP в UI; вызовы сервисов из UI — только в рамках `architecture-boundaries.mdc`).
|
|
85
85
|
- Избегать использования `any` при типизации кода; при необходимости использовать `unknown` с последующим безопасным сужением типов.
|
|
86
|
-
- После
|
|
86
|
+
- После **любых** изменений кода — **`post-change-lint.mdc`**: из каталога `app/` обязательно запустить **`lint:js`** и **`lint:css`** (полный прогон), проанализировать вывод, исправить errors/warnings в зоне задачи; задача не завершена, пока оба линтера не проходят. Дополнительно — **`type-check`** при правках TypeScript. Менеджер пакетов — **`package-manager.mdc`**.
|
|
87
87
|
|
|
@@ -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
|
-
- Передача
|
|
39
|
-
- Делегирование пропов в обёртку (wrapper) допустимо, если это явно документировано и
|
|
61
|
+
- Передача пропов в **нативный** DOM-элемент (`<div {...rest} />`) допустима, если `rest` содержит только валидные HTML-атрибуты.
|
|
62
|
+
- Делегирование пропов в обёртку (wrapper) допустимо, если это явно документировано и обосновано; при необходимости пометьте файл или строку через ESLint-disable, как выше.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Перед командами в терминале определять менеджер пакетов репозитория и использовать только его
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Менеджер пакетов (терминал)
|
|
7
|
+
|
|
8
|
+
Перед **`npm install` / `yarn` / `pnpm` / `bun`** и любыми **`… run …`** (lint, test, dev, build) **сначала определи**, какой менеджер закреплён в этом репозитории, и **используй только его** — не подставляй npm или другой инструмент «по привычке».
|
|
9
|
+
|
|
10
|
+
## Как определить (по убыванию надёжности)
|
|
11
|
+
|
|
12
|
+
1. Поле **`packageManager`** в `package.json` у корня монорепо или в каталоге приложения (например `app/package.json`) — строка вида `yarn@…`, `pnpm@…`, `npm@…`, `bun@…` (Corepack).
|
|
13
|
+
2. **Lockfile** рядом с тем `package.json`, откуда ставятся зависимости:
|
|
14
|
+
- `yarn.lock` → **yarn**
|
|
15
|
+
- `pnpm-lock.yaml` → **pnpm**
|
|
16
|
+
- `package-lock.json` → **npm**
|
|
17
|
+
- `bun.lock` / `bun.lockb` → **bun**
|
|
18
|
+
3. Если структура неоднозначна — критерий: где лежат **`node_modules`** и какой lockfile обновляют в CI / документации репо.
|
|
19
|
+
|
|
20
|
+
## Как запускать
|
|
21
|
+
|
|
22
|
+
- Рабочий каталог — тот, где **`package.json`** с нужными **scripts** (в этом репозитории зависимости и скрипты в **`app/`**).
|
|
23
|
+
- Примеры: `yarn lint`, `pnpm run test` — **в соответствии с обнаруженным менеджером**, без смешения разных CLI в одной задаче.
|
|
24
|
+
|
|
25
|
+
Если менеджер неочевиден — **посмотри файлы** (`package.json`, lockfile) инструментами чтения/списка каталога, **не угадывай**.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Обязательный прогон ESLint и Stylelint после любых изменений кода
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Линтеры после изменений кода
|
|
7
|
+
|
|
8
|
+
## Когда применять
|
|
9
|
+
|
|
10
|
+
После **любого** изменения исходников в репозитории: правка, создание или удаление файлов в `app/**` (TS/TSX/JS/MJS, CSS, styled/Linaria в `.ts`/`.tsx`, markdown с ESLint и т.д.).
|
|
11
|
+
|
|
12
|
+
Исключения без прогона линтеров: только правки **документации вне `app/`**, конфигов CI, `.cursor/rules/**`, если **не** менялся исполняемый код приложения.
|
|
13
|
+
|
|
14
|
+
## Обязательные команды
|
|
15
|
+
|
|
16
|
+
Рабочий каталог — **`app/`** (там `package.json` со скриптами). Менеджер пакетов — **`package-manager.mdc`**.
|
|
17
|
+
|
|
18
|
+
1. **`lint:js`** — полный ESLint по проекту (`eslint .` с расширениями из скрипта).
|
|
19
|
+
2. **`lint:css`** — полный Stylelint (`**/*.{css,ts}`).
|
|
20
|
+
|
|
21
|
+
**Всегда запускать обе команды**, даже если задача не касалась стилей: Stylelint проверяет и CSS-in-JS в `.ts`.
|
|
22
|
+
|
|
23
|
+
Точечный ESLint/Stylelint только на один файл **не заменяет** полный прогон перед завершением задачи.
|
|
24
|
+
|
|
25
|
+
## Алгоритм для агента
|
|
26
|
+
|
|
27
|
+
1. Завершить правки кода.
|
|
28
|
+
2. Запустить **`lint:js`** и **`lint:css`** из `app/` (через терминал, не «на глаз»).
|
|
29
|
+
3. **Проанализировать весь вывод**: errors и warnings.
|
|
30
|
+
4. **Исправить** все срабатывания в **изменённых файлах** и связанных с задачей; для Stylelint сначала пробовать **`lint:css --fix`**, если правило автоисправимо.
|
|
31
|
+
5. При ненулевом exit code — повторить шаги 2–4 до успешного прогона или явного блокера.
|
|
32
|
+
6. **Не считать задачу выполненной**, пока оба линтера не завершились с кодом 0 **или** в ответе пользователю не зафиксирован блокер (например, легаси вне скоупа) с перечислением оставшихся замечаний.
|
|
33
|
+
|
|
34
|
+
## Что исправлять
|
|
35
|
+
|
|
36
|
+
- **Errors** — обязательно.
|
|
37
|
+
- **Warnings** — обязательно в файлах из текущей задачи; вне скоупа — не чинить «заодно», но **упомянуть** в ответе, если мешают нулевому exit code.
|
|
38
|
+
- **`eslint-disable`** — только точечно, с кратким комментарием «зачем» (`code-quality-and-refactoring.mdc`).
|
|
39
|
+
|
|
40
|
+
## Связанные проверки
|
|
41
|
+
|
|
42
|
+
- **`type-check`** — обязателен при изменениях TypeScript (`next-app-core.mdc`); не подменяет ESLint/Stylelint.
|
|
43
|
+
- Полная валидация как в CI: **`lint`** (= `lint:js` + `lint:css` + `type-check`) — уместна перед крупным MR.
|
|
44
|
+
|
|
45
|
+
## Конфиги
|
|
46
|
+
|
|
47
|
+
- ESLint: `app/eslint.config.mjs`
|
|
48
|
+
- Stylelint: `app/.stylelintrc` (порядок свойств — `css-property-order-stylelint.mdc`)
|
|
@@ -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
|
|
|
@@ -22,14 +22,42 @@ alwaysApply: false
|
|
|
22
22
|
- `styles.ts` или соседний модуль стилей — по конвенции репозитория (CSS Modules, CSS-in-JS, и т.д.).
|
|
23
23
|
- `index.ts` — реэкспорт (если нужно наружу).
|
|
24
24
|
|
|
25
|
+
## Дочерние компоненты (`./components`)
|
|
26
|
+
|
|
27
|
+
- Локальные подкомпоненты, используемые только этим блоком, выносятся в **`./components/<ComponentName>/`** относительно папки родительского компонента (не оставлять крупные куски JSX и «внутренние» компоненты в том же файле, что и родитель).
|
|
28
|
+
- У каждого такого подкомпонента — **своя** папка с тем же именем, что и публичное имя компонента:
|
|
29
|
+
- `ComponentName.tsx` — разметка и композиция;
|
|
30
|
+
- `styles.ts` — только стили этого подкомпонента (см. `no-cross-component-styles-import.mdc`: не тянуть `styles` соседних компонентов);
|
|
31
|
+
- при необходимости — `ComponentName.data.ts`, `ComponentName.utils.ts`, `ComponentName.hooks.ts` по тем же правилам префикса, что и у родителя;
|
|
32
|
+
- опционально `index.ts` с реэкспортом.
|
|
33
|
+
- Родитель импортирует подкомпонент из `./components/...`, а не держит его реализацию inline.
|
|
34
|
+
|
|
25
35
|
Для переиспользуемого компонента:
|
|
26
36
|
- Папка с именем компонента:
|
|
27
37
|
- `ComponentName.tsx`
|
|
28
38
|
- файлы стилей по принятой схеме;
|
|
29
|
-
- опционально: `types.ts`, `hooks.ts
|
|
39
|
+
- опционально: `types.ts`, `ComponentName.hooks.ts` (см. ниже про префикс).
|
|
40
|
+
|
|
41
|
+
## Вспомогательные модули рядом с компонентом (именование)
|
|
42
|
+
|
|
43
|
+
**Префикс имени файла = публичное имя компонента** (как у `ComponentName.tsx` в этой папке), в **PascalCase**. Не вводить отдельные «говорящие» имена файлов по смыслу содержимого (`analysisPreparationIconMap.ts`, `buildAnalysisIdToNameMap.ts` и т.п.) — так теряется связь с компонентом и плодятся одноразовые названия.
|
|
44
|
+
|
|
45
|
+
**Суффикс по роли:**
|
|
46
|
+
|
|
47
|
+
| Суффикс | Назначение | Примеры содержимого |
|
|
48
|
+
|--------|------------|---------------------|
|
|
49
|
+
| `ComponentName.data.ts` | Статические данные и конфигурация для UI | мапы `id → иконка/лейбл`, константы списков, таблицы соответствий для отображения |
|
|
50
|
+
| `ComponentName.utils.ts` | Чистые функции без React | форматирование, предобработка пропсов/данных для рендера, `build…`/`map…`‑хелперы |
|
|
51
|
+
| `ComponentName.hooks.ts` | Хуки, используемые только этим блоком | локальные `use…` (если не вынесены в `src/ui/hooks/**`) |
|
|
52
|
+
|
|
53
|
+
- Несколько констант/мапов или несколько функций — **по-прежнему один** `.data.ts` и один `.utils.ts`, не дробить по «темам» отдельными файлами без веской причины (размер, разные зоны ответственности на уровне подкомпонентов).
|
|
54
|
+
- Если логика принадлежит **подкомпоненту** в подпапке (`components/Child/Child.tsx`), те же правила применяются к **`Child.data.ts`**, **`Child.utils.ts`** относительно этого подкомпонента.
|
|
55
|
+
- Тесты для утилит и данных — рядом в `__tests__/` или с суффиксом `.test.ts`, согласно `tests-unit.mdc`, с тем же префиксом (`RequestForAnalysisRecommendations.utils.test.ts` и т.д.).
|
|
30
56
|
|
|
31
57
|
# Стили и дизайн‑токены
|
|
32
58
|
|
|
59
|
+
- **Корневой** styled-элемент компонента в соседнем `styles` — **`Root`** (`<s.Root>`). Подробнее: `no-cross-component-styles-import.mdc`.
|
|
60
|
+
- Порядок объявлений в CSS / `styled` — как требует Stylelint: см. `css-property-order-stylelint.mdc`.
|
|
33
61
|
- Для визуала использовать **тот стек стилей и токенов, который уже в проекте** (переменные, тема, общие классы, дизайн‑пакет).
|
|
34
62
|
- Избегать:
|
|
35
63
|
- inline‑стилей, кроме простых случаев;
|
|
@@ -39,6 +67,7 @@ alwaysApply: false
|
|
|
39
67
|
|
|
40
68
|
# Пропсы и типизация
|
|
41
69
|
|
|
70
|
+
- **Не передавать пропы в компоненты через spread** (`<Foo {...x} />`). Только явные атрибуты; подробности и исключения — `no-props-spread.mdc` (в `app/src/ui` это дополнительно ловит ESLint).
|
|
42
71
|
- Описывать пропсы через `type Props = { ... }` или `interface Props { ... }`.
|
|
43
72
|
- Не использовать `any`; при необходимости:
|
|
44
73
|
- обобщения (`<T>`), `unknown`, тип‑предикаты и user‑defined type guards.
|