@bonesofspring/ai-rules 0.1.41 → 0.2.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.
- package/CHANGELOG.md +22 -0
- package/README.md +10 -1
- package/bin/cli.js +193 -53
- package/package.json +1 -1
- package/presets/claude/next/CLAUDE.md +1 -1
- package/presets/claude/next/agents/README.md +61 -0
- package/presets/claude/next/agents/api-contract-reviewer.md +1 -1
- package/presets/claude/next/agents/build-verifier.md +2 -0
- package/presets/claude/next/agents/feature-developer.md +8 -21
- package/presets/claude/next/agents/task-router.md +24 -126
- package/presets/claude/next/commands/task.md +1 -1
- package/presets/claude/next/rules/README.md +3 -3
- package/presets/claude/next/rules/api-and-data/api-services.md +3 -3
- package/presets/claude/next/rules/api-and-data/http-client.md +2 -2
- package/presets/claude/next/rules/api-and-data/store-rtk.md +2 -2
- package/presets/claude/next/rules/architecture/README.md +8 -11
- package/presets/claude/next/rules/architecture/api-public-imports.md +3 -26
- package/presets/claude/next/rules/architecture/architecture-boundaries.md +6 -6
- package/presets/claude/next/rules/architecture/feature-delivery-workflow.md +44 -69
- package/presets/claude/next/rules/architecture/layer-barrel-exports.md +5 -5
- package/presets/claude/next/rules/architecture/public-imports.md +46 -0
- package/presets/claude/next/rules/architecture/reference-features.md +4 -1
- package/presets/claude/next/rules/architecture/types-public-imports.md +3 -29
- package/presets/claude/next/rules/stack/next-app-core.md +20 -70
- package/presets/claude/next/rules/stack/no-type-assertion.md +3 -2
- package/presets/claude/next/rules/stack/types-jsdoc.md +1 -1
- package/presets/claude/next/rules/tooling-and-review/agent-team-intake.md +6 -0
- package/presets/claude/next/rules/tooling-and-review/agent-team-orchestrator.md +14 -1
- package/presets/claude/next/rules/tooling-and-review/code-quality.md +3 -11
- package/presets/claude/next/rules/tooling-and-review/code-review-mr.md +2 -2
- package/presets/claude/next/rules/tooling-and-review/package-manager.md +6 -15
- package/presets/claude/next/rules/tooling-and-review/post-change-lint.md +14 -24
- package/presets/claude/next/rules/ui-and-accessibility/css-property-order.md +6 -18
- package/presets/claude/next/rules/ui-and-accessibility/react-ui.md +1 -1
- package/presets/claude/next/skills/feature-delivery/SKILL.md +5 -20
- package/presets/cursor/next/AGENTS.md +1 -1
- package/presets/cursor/next/agents/README.md +81 -0
- package/presets/cursor/next/agents/api-contract-reviewer.md +1 -1
- package/presets/cursor/next/agents/build-verifier.md +2 -0
- package/presets/cursor/next/agents/code-reviewer.md +1 -1
- package/presets/cursor/next/agents/feature-developer.md +9 -30
- package/presets/cursor/next/agents/task-router.md +23 -125
- package/presets/cursor/next/commands/task.md +1 -1
- package/presets/cursor/next/rules/README.md +6 -7
- package/presets/cursor/next/rules/agent-team-intake.mdc +2 -2
- package/presets/cursor/next/rules/agent-team-orchestrator.mdc +14 -1
- package/presets/cursor/next/rules/api-public-imports.mdc +3 -24
- package/presets/cursor/next/rules/api-services.mdc +3 -3
- package/presets/cursor/next/rules/architecture-boundaries.mdc +6 -6
- package/presets/cursor/next/rules/code-quality-and-refactoring.mdc +3 -11
- package/presets/cursor/next/rules/code-review-mr.mdc +2 -2
- package/presets/cursor/next/rules/css-property-order-stylelint.mdc +6 -18
- package/presets/cursor/next/rules/feature-delivery-workflow.mdc +45 -22
- package/presets/cursor/next/rules/http-client.mdc +2 -2
- package/presets/cursor/next/rules/layer-barrel-exports.mdc +5 -5
- package/presets/cursor/next/rules/next-app-core.mdc +18 -71
- package/presets/cursor/next/rules/no-type-assertion-as-import-export.mdc +4 -1
- package/presets/cursor/next/rules/package-manager.mdc +6 -15
- package/presets/cursor/next/rules/post-change-lint.mdc +14 -24
- package/presets/cursor/next/rules/public-imports.mdc +48 -0
- package/presets/cursor/next/rules/react-ui.mdc +1 -1
- package/presets/cursor/next/rules/reference-features.mdc +5 -1
- package/presets/cursor/next/rules/store-rtk.mdc +2 -2
- package/presets/cursor/next/rules/types-jsdoc.mdc +1 -1
- package/presets/cursor/next/rules/types-public-imports.mdc +3 -26
- package/presets/cursor/next/skills/feature-delivery/SKILL.md +5 -20
- package/presets/cursor/next/rules/feature-delivery-flow.mdc +0 -74
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-router
|
|
3
3
|
description: Task routing specialist. Analyzes user prompt, detects intent, and writes pipeline.json with ordered agent steps. Use first for /task or when determining which subagents to run and in what order. Writes only team artifacts; never writes production code.
|
|
4
|
-
model:
|
|
4
|
+
model: fast
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
You are a task router for a Next.js frontend agent team. You **do not** implement tasks — you classify intent and plan the agent pipeline.
|
|
@@ -10,6 +10,7 @@ You are a task router for a Next.js frontend agent team. You **do not** implemen
|
|
|
10
10
|
|
|
11
11
|
- User task description (from `/task` or orchestrator).
|
|
12
12
|
- Optional: existing files under `.claude/team/tasks/<slug>/`.
|
|
13
|
+
- Pipeline JSON schema, examples, step fields — **`agents/README.md`**.
|
|
13
14
|
|
|
14
15
|
## Intent detection
|
|
15
16
|
|
|
@@ -23,150 +24,47 @@ You are a task router for a Next.js frontend agent team. You **do not** implemen
|
|
|
23
24
|
| `a11y` | «a11y», «доступность», «accessibility», «WCAG», «screen reader», «клавиатура» | task-analyst → feature-developer → build-verifier → accessibility-reviewer → code-reviewer |
|
|
24
25
|
| `review-only` | «ревью», «review MR», «проверь diff», «code review» | code-reviewer |
|
|
25
26
|
| `test-only` | «покрой тестами», «напиши тесты» (mixed unit+e2e, no impl) | task-analyst → qa-tester |
|
|
26
|
-
| `unit-only` | «unit», «юнит», «mapper tests», «покрой маппер», «почини unit» | unit-test-planner → unit-test-generator, or unit-test-healer
|
|
27
|
-
| `e2e-only` | «e2e», «playwright», «browser test», «сценарии e2e», «почини e2e» | playwright-test-planner → playwright-test-generator, or playwright-test-healer
|
|
27
|
+
| `unit-only` | «unit», «юнит», «mapper tests», «покрой маппер», «почини unit» | unit-test-planner → unit-test-generator, or unit-test-healer |
|
|
28
|
+
| `e2e-only` | «e2e», «playwright», «browser test», «сценарии e2e», «почини e2e» | playwright-test-planner → playwright-test-generator, or playwright-test-healer |
|
|
28
29
|
| `docs-only` | «документация», «README», «changelog», «ADR», «migration guide» | task-analyst → tech-writer |
|
|
29
30
|
| `refactor` | «рефакторинг», «без изменения поведения», «почисти» | task-analyst → feature-developer → build-verifier → code-reviewer |
|
|
30
31
|
| `spike` | «исследуй», «оцени», «можно ли», «spike», proof of concept | task-analyst → solution-architect |
|
|
31
32
|
| `retro` | «ретро», «разбор», «postmortem» | no pipeline — orchestrator runs `/technical-retro` |
|
|
32
33
|
|
|
33
|
-
Adjust steps when context is clear
|
|
34
|
+
## Adjust steps (when context is clear)
|
|
34
35
|
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
- **
|
|
41
|
-
- **
|
|
42
|
-
- **
|
|
43
|
-
- **Use Playwright specialists** for e2e-heavy features instead of `qa-tester`.
|
|
44
|
-
- **Always insert build-verifier** after feature-developer for `feature`, `bugfix`, `refactor`, `migration`, `a11y`.
|
|
45
|
-
- **Skip qa-tester** for review-only, spike (no code), ci-fix (unless regression scope needed), perf-audit, docs-only, unit-only/e2e-only handled by specialists, or trivial one-line fixes (document risk).
|
|
46
|
-
- **Skip feature-developer** for review-only, test-only (tests only), retro, perf-audit, docs-only (after analyst), ci-fix when investigator fixes in place.
|
|
47
|
-
- **ci-fix:** skip feature-developer with `skipIf: ci-investigator.resolved` when investigator fixes in place.
|
|
48
|
-
- **bugfix:** use `skipIf: debugger.fixed` on feature-developer when debugger applied the fix.
|
|
49
|
-
- **Model:** use `model: inherit` when pipeline has 4+ steps or cross-layer uncertainty.
|
|
36
|
+
- Skip **task-analyst** if AC/scope fully specified → document in `skipped`.
|
|
37
|
+
- Add **solution-architect** for cross-layer / new public APIs — after analyst, before developer.
|
|
38
|
+
- Add **api-contract-reviewer** for new/changed backend contracts — before developer.
|
|
39
|
+
- Add **accessibility-reviewer** / **security-reviewer** after build-verifier (parallel when both apply).
|
|
40
|
+
- Add **tech-writer** when docs/changelog requested.
|
|
41
|
+
- **Always build-verifier** after developer for `feature`, `bugfix`, `refactor`, `migration`, `a11y`.
|
|
42
|
+
- **skipIf:** `debugger.fixed` (bugfix); `ci-investigator.resolved` (ci-fix).
|
|
43
|
+
- **Model:** `inherit` when 4+ steps or cross-layer uncertainty.
|
|
50
44
|
|
|
51
|
-
##
|
|
52
|
-
|
|
53
|
-
Write to `.claude/team/tasks/<slug>/pipeline.json`:
|
|
54
|
-
|
|
55
|
-
```json
|
|
56
|
-
{
|
|
57
|
-
"slug": "<slug>",
|
|
58
|
-
"intent": "feature",
|
|
59
|
-
"summary": "One-line task summary",
|
|
60
|
-
"steps": [
|
|
61
|
-
{ "agent": "task-analyst", "label": "Clarify and decompose" },
|
|
62
|
-
{ "agent": "feature-developer", "label": "Implement + unit tests", "scope": "unit-in-dev" },
|
|
63
|
-
{ "agent": "build-verifier", "label": "Lint, type-check, unit smoke" },
|
|
64
|
-
{ "agent": "code-reviewer", "label": "Code review" },
|
|
65
|
-
{ "agent": "qa-tester", "label": "E2E tests", "scope": "e2e-only" }
|
|
66
|
-
],
|
|
67
|
-
"humanGates": ["after:task-analyst"],
|
|
68
|
-
"autoChain": true,
|
|
69
|
-
"skipped": []
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Example: feature with optional reviewers
|
|
74
|
-
|
|
75
|
-
```json
|
|
76
|
-
{
|
|
77
|
-
"intent": "feature",
|
|
78
|
-
"steps": [
|
|
79
|
-
{ "agent": "task-analyst", "label": "Clarify and decompose" },
|
|
80
|
-
{ "agent": "api-contract-reviewer", "label": "Validate API contract" },
|
|
81
|
-
{ "agent": "feature-developer", "label": "Implement + unit tests", "scope": "unit-in-dev" },
|
|
82
|
-
{ "agent": "build-verifier", "label": "Validation gate" },
|
|
83
|
-
{
|
|
84
|
-
"agent": ["accessibility-reviewer", "security-reviewer"],
|
|
85
|
-
"parallel": true,
|
|
86
|
-
"label": "A11y and security review"
|
|
87
|
-
},
|
|
88
|
-
{ "agent": "code-reviewer", "label": "Code review" },
|
|
89
|
-
{ "agent": "playwright-test-planner", "label": "E2E plan" },
|
|
90
|
-
{ "agent": "playwright-test-generator", "label": "E2E specs" },
|
|
91
|
-
{ "agent": "tech-writer", "label": "Documentation" }
|
|
92
|
-
],
|
|
93
|
-
"humanGates": ["after:task-analyst"]
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Example: bugfix with skip
|
|
98
|
-
|
|
99
|
-
```json
|
|
100
|
-
{
|
|
101
|
-
"intent": "bugfix",
|
|
102
|
-
"steps": [
|
|
103
|
-
{ "agent": "debugger", "label": "Root cause" },
|
|
104
|
-
{ "agent": "feature-developer", "label": "Fix if needed", "skipIf": "debugger.fixed" },
|
|
105
|
-
{ "agent": "build-verifier", "label": "Validation" },
|
|
106
|
-
{ "agent": "code-reviewer", "label": "Review" }
|
|
107
|
-
],
|
|
108
|
-
"humanGates": []
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Step fields
|
|
113
|
-
|
|
114
|
-
| Field | Required | Description |
|
|
115
|
-
|-------|----------|-------------|
|
|
116
|
-
| `agent` | yes | Subagent name (kebab-case) or array for `parallel: true` |
|
|
117
|
-
| `label` | yes | Short human-readable step name |
|
|
118
|
-
| `scope` | no | e.g. `unit-in-dev`, `e2e-only`, `regression`, `full` |
|
|
119
|
-
| `skipIf` | no | `debugger.fixed` \| `ci-investigator.resolved` |
|
|
120
|
-
| `parallel` | no | When `true` and `agent` is array — invoke all in one turn |
|
|
121
|
-
|
|
122
|
-
### humanGates
|
|
123
|
-
|
|
124
|
-
Values: `after:<agent-name>` — orchestrator stops after that agent; user runs `/task-continue <slug>` or `/feature-continue <slug>`.
|
|
45
|
+
## humanGates (defaults)
|
|
125
46
|
|
|
126
47
|
| Intent | Default humanGates |
|
|
127
48
|
|--------|-------------------|
|
|
128
49
|
| `feature`, `refactor`, `test-only`, `a11y` | `["after:task-analyst"]` |
|
|
129
50
|
| `migration` | `["after:migration-specialist"]` |
|
|
130
51
|
| `docs-only` | `["after:task-analyst"]` |
|
|
131
|
-
| `unit-only` | `["after:unit-test-planner"]` when new plan; `[]` for
|
|
132
|
-
| `e2e-only` | `["after:playwright-test-planner"]` when new plan; `[]` for
|
|
133
|
-
| `bugfix`, `review-only`, `ci-fix` | `[]`
|
|
52
|
+
| `unit-only` | `["after:unit-test-planner"]` when new plan; `[]` for healer |
|
|
53
|
+
| `e2e-only` | `["after:playwright-test-planner"]` when new plan; `[]` for healer |
|
|
54
|
+
| `bugfix`, `review-only`, `ci-fix` | `[]` |
|
|
134
55
|
| `spike` | `["after:solution-architect"]` |
|
|
135
56
|
| `perf-audit` | `[]` |
|
|
136
57
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
```json
|
|
140
|
-
"skipped": [{ "agent": "task-analyst", "reason": "AC provided in ticket" }]
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## Initial status.json
|
|
58
|
+
## Output
|
|
144
59
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
```json
|
|
148
|
-
{
|
|
149
|
-
"slug": "<slug>",
|
|
150
|
-
"intent": "<intent>",
|
|
151
|
-
"pipelineIndex": 0,
|
|
152
|
-
"currentAgent": "<steps[0].agent>",
|
|
153
|
-
"phase": "executing",
|
|
154
|
-
"state": "in_progress",
|
|
155
|
-
"awaitingHumanGate": false,
|
|
156
|
-
"updatedAt": "<ISO8601>"
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Also write `.claude/team/active-task.json` → `{ "slug": "<slug>" }`.
|
|
60
|
+
Write `.claude/team/tasks/<slug>/pipeline.json` and initial `status.json`; set `.claude/team/active-task.json` → `{ "slug": "<slug>" }`. Minimal template — см. **`agents/README.md`**.
|
|
161
61
|
|
|
162
62
|
## Handoff to orchestrator
|
|
163
63
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
4. **Human gates** (if any).
|
|
170
|
-
5. Tell orchestrator to invoke `steps[0].agent` now (unless intent is `retro` — then run `/technical-retro`).
|
|
64
|
+
1. Intent + one-line summary.
|
|
65
|
+
2. Planned steps (table: #, agent, label).
|
|
66
|
+
3. Skipped roles and why.
|
|
67
|
+
4. Human gates (if any).
|
|
68
|
+
5. Invoke `steps[0].agent` now (unless `retro` → `/technical-retro`).
|
|
171
69
|
|
|
172
70
|
Do not invoke implementation agents yourself.
|
|
@@ -5,7 +5,7 @@ description: Route a natural-language task through the agent-team pipeline: task
|
|
|
5
5
|
|
|
6
6
|
# Task — единая точка входа
|
|
7
7
|
|
|
8
|
-
Главная команда для постановки задачи в Claude Code. Родительский агент =
|
|
8
|
+
Главная команда для постановки задачи в Claude Code. Родительский агент = оркестратор (`rules/tooling-and-review/agent-team-orchestrator.md`). Intake — `rules/tooling-and-review/agent-team-intake.md`.
|
|
9
9
|
|
|
10
10
|
## Аргументы
|
|
11
11
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
## Loading strategy
|
|
6
6
|
|
|
7
|
-
- **Session start (no `paths:`):** `next-app-core`, `post-change-lint`, `package-manager`, `
|
|
8
|
-
-
|
|
7
|
+
- **Session start (no `paths:`):** `next-app-core`, `post-change-lint`, `package-manager`, `code-quality`
|
|
8
|
+
- **On-demand (`paths:` or via commands):** `agent-team-intake`, orchestrator, architecture, imports, UI, tests, feature-delivery-workflow, reference-features, next-app-router, react-a11y-coding
|
|
9
9
|
- **Skills:** long workflows (`feature-delivery`, `code-review`, …)
|
|
10
10
|
|
|
11
11
|
## С чего начать
|
|
@@ -27,4 +27,4 @@
|
|
|
27
27
|
|
|
28
28
|
Полный список — см. подпапки `architecture/`, `stack/`, `api-and-data/`, `ui-and-accessibility/`, `testing/`, `tooling-and-review/`.
|
|
29
29
|
|
|
30
|
-
**Коллизии:** импорт типов
|
|
30
|
+
**Коллизии:** импорт типов и API — **`architecture/public-imports.md`**.
|
|
@@ -11,7 +11,7 @@ paths:
|
|
|
11
11
|
- заголовками и кодами ответов,
|
|
12
12
|
- DTO backend.
|
|
13
13
|
- Предоставлять UI и store **стабильный доменный интерфейс**:
|
|
14
|
-
- функции, работающие с доменными типами из `@/types` (`architecture/
|
|
14
|
+
- функции, работающие с доменными типами из `@/types` (`architecture/public-imports.md`).
|
|
15
15
|
- мапперы между DTO и доменными типами.
|
|
16
16
|
|
|
17
17
|
# Структура модулей
|
|
@@ -22,7 +22,7 @@ paths:
|
|
|
22
22
|
- файлы с вызовами API (`index.ts` или `*.service.ts`);
|
|
23
23
|
- файлы мапперов (`*responseMappers.ts`);
|
|
24
24
|
- специфичные типы запросов/ответов (если не вынесены в `app/src/types/**` с экспортом через barrel `@/types`).
|
|
25
|
-
- при необходимости — локальные `index.ts` / barrel внутри модуля для структуры **внутри** `app/src/api/**`; **снаружи** этого слоя UI, store и остальной код импортируют только из корневого barrel `app/src/api/index.ts` (`import … from '@/api'`, **`architecture/
|
|
25
|
+
- при необходимости — локальные `index.ts` / barrel внутри модуля для структуры **внутри** `app/src/api/**`; **снаружи** этого слоя UI, store и остальной код импортируют только из корневого barrel `app/src/api/index.ts` (`import … from '@/api'`, **`architecture/public-imports.md`**).
|
|
26
26
|
|
|
27
27
|
# Мапперы и типы
|
|
28
28
|
|
|
@@ -54,4 +54,4 @@ paths:
|
|
|
54
54
|
- Не смешивать слой API и UI/store:
|
|
55
55
|
- компоненты не должны зависеть от DTO;
|
|
56
56
|
- store не должен сам собирать URL/коды эндпоинтов и не обходить сервисы; **транспортный тип ответа** и **контракт ошибки** из `@/types` (как у прикладного клиента) допустимы во thunk при разборе `catch`/payload, если так выстроен сервис (см. `api-and-data/store-rtk.md`, `api-and-data/http-client.md`).
|
|
57
|
-
- При использовании API‑сервисов в UI, store и утилитах **вне** `app/src/api/**` импортировать **только** из `@/api` (корневой barrel), см. **`architecture/
|
|
57
|
+
- При использовании API‑сервисов в UI, store и утилитах **вне** `app/src/api/**` импортировать **только** из `@/api` (корневой barrel), см. **`architecture/public-imports.md`**; внутри слоя API — по относительным путям или `@/api/services/**` / `@/api/clients/**`, не дублируя публичный контракт мимо корневого barrel для внешних потребителей.
|
|
@@ -12,12 +12,12 @@ paths:
|
|
|
12
12
|
|
|
13
13
|
- Обычные REST‑вызовы к backend идут через **одну реализацию** в `app/src/lib/clients/**` (модуль общего клиента) и **преднастроенные экземпляры** в `app/src/api/clients/**`, по тому же паттерну, что уже принят в проекте.
|
|
14
14
|
- Место транспорта в общей картине **порты и адаптеры** — в `architecture/architecture-boundaries.md` (раздел **«Порты и адаптеры»**).
|
|
15
|
-
- **Не** вызывать `fetch` напрямую из `app/src/api/services/**`, store и UI (см. `architecture/architecture-boundaries.md`, `api-and-data/api-services.md`); из store/UI — только вызовы через сервисы из `@/api` (`architecture/
|
|
15
|
+
- **Не** вызывать `fetch` напрямую из `app/src/api/services/**`, store и UI (см. `architecture/architecture-boundaries.md`, `api-and-data/api-services.md`); из store/UI — только вызовы через сервисы из `@/api` (`architecture/public-imports.md`).
|
|
16
16
|
- **Исключения** (узкие протоколы, отдельный транспорт) — только там, где в репозитории уже есть образец; повторять его, не плодить произвольные обходы общего клиента.
|
|
17
17
|
|
|
18
18
|
## Типы
|
|
19
19
|
|
|
20
|
-
- Всё, что относится к **контракту запроса/ответа/ошибки** приложения и реэкспортируется для HTTP‑слоя, импортировать **только** из barrel `@/types`, без deep‑импортов из внутренних файлов `app/src/types/**` (см. `architecture/
|
|
20
|
+
- Всё, что относится к **контракту запроса/ответа/ошибки** приложения и реэкспортируется для HTTP‑слоя, импортировать **только** из barrel `@/types`, без deep‑импортов из внутренних файлов `app/src/types/**` (см. `architecture/public-imports.md`).
|
|
21
21
|
- Не поднимать в новом коде **типы и зависимости от внешнего HTTP‑клиента**, от которого проект ушёл; ориентир — **`package.json`** и существующие вызовы.
|
|
22
22
|
|
|
23
23
|
## Контракт ошибок
|
|
@@ -29,7 +29,7 @@ paths:
|
|
|
29
29
|
- Асинхронные запросы:
|
|
30
30
|
- через `createAsyncThunk` или RTK Query.
|
|
31
31
|
- внутри thunk:
|
|
32
|
-
- вызывать API через сервисы, импортированные из `@/api` (**`architecture/
|
|
32
|
+
- вызывать API через сервисы, импортированные из `@/api` (**`architecture/public-imports.md`**);
|
|
33
33
|
- не вызывать HTTP‑клиент напрямую — только через эти сервисы.
|
|
34
34
|
- Сайд‑эффекты (логирование, аналитика, работа с файлами):
|
|
35
35
|
- выносить в middleware (`app/src/store/middleware/**`) или специализированные слайсы.
|
|
@@ -43,7 +43,7 @@ paths:
|
|
|
43
43
|
- при ошибках после вызова сервиса — опираться на **тот же класс/контракт ошибки транспорта**, что использует общий клиент (из `@/types`), и разбирать тело/статус **по полям текущей реализации**, а не по воображаемому API;
|
|
44
44
|
- в **`catch`** предпочитать **`instanceof`** на класс ошибки транспорта из `@/types` (если он есть в коде) вместо голого `as`, когда это выразимо без шума (см. `stack/no-type-assertion.md`).
|
|
45
45
|
- Для сущностей:
|
|
46
|
-
- доменные типы (включая вычисляемые поля) определять в `app/src/types/**`, экспортировать через barrel и импортировать в слайсы из `@/types` как **источник правды** (`architecture/
|
|
46
|
+
- доменные типы (включая вычисляемые поля) определять в `app/src/types/**`, экспортировать через barrel и импортировать в слайсы из `@/types` как **источник правды** (`architecture/public-imports.md`);
|
|
47
47
|
- избегать дублирования описаний сущностей в нескольких местах.
|
|
48
48
|
- **Граница домена**: в **state** хранить доменные модели; тип **обёртки ответа клиента** допустим как тип **возвращаемого значения thunk** или промежуточно до маппинга — без дублирования DTO в полях state без нужды (согласовано с `api-and-data/api-services.md` и `api-and-data/http-client.md`).
|
|
49
49
|
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
# Architecture
|
|
1
|
+
# Architecture rules
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
| Файл | Содержание |
|
|
3
|
+
| Файл | Назначение |
|
|
6
4
|
|------|------------|
|
|
7
|
-
| `
|
|
8
|
-
| `
|
|
9
|
-
| `
|
|
10
|
-
| `
|
|
11
|
-
| `feature-delivery-workflow.md` |
|
|
12
|
-
|
|
13
|
-
Все файлы — **session start** (без `paths:`).
|
|
5
|
+
| `public-imports.md` | Импорты `@/types`, `@/types/enums`, `@/api` (вне `app/src/api/**`) |
|
|
6
|
+
| `types-public-imports.md`, `api-public-imports.md` | Deprecated stubs → `public-imports.md` |
|
|
7
|
+
| `architecture-boundaries.md` | Границы UI / store / API, порты‑адаптеры |
|
|
8
|
+
| `layer-barrel-exports.md` | Двухуровневые barrel для слоёв с public API |
|
|
9
|
+
| `feature-delivery-workflow.md` | Сквозной чеклист новой фичи |
|
|
10
|
+
| `reference-features.md` | Эталонные пути UI/store/API/types |
|
|
@@ -1,31 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
paths:
|
|
3
|
-
- app/src
|
|
4
|
-
- app/src/**/*.tsx
|
|
3
|
+
- app/src/api/**/*
|
|
5
4
|
---
|
|
6
5
|
|
|
7
|
-
#
|
|
6
|
+
# Deprecated
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
- **Запрещено** для таких потребителей обходить barrel: любой импорт вида `@/api/<что‑угодно>`, кроме `@/api/index`. Это дублирует правило ESLint `no-restricted-imports` в `app/eslint.config.mjs` (паттерн `@/api/*` с исключением `@/api/index`).
|
|
11
|
-
- При **добавлении** публичного символа в регламентированный слой — реэкспорт в корневой barrel по **`architecture/layer-barrel-exports.md`**.
|
|
12
|
-
|
|
13
|
-
## Внутри слоя `app/src/api/**`
|
|
14
|
-
|
|
15
|
-
- При реализации сервисов, клиентов и barrel допустимы **относительные** импорты и пути вида `@/api/services/**`, `@/api/clients/**` между файлами этого слоя. Это не относится к потребителям снаружи `app/src/api/**`.
|
|
16
|
-
|
|
17
|
-
## Примеры
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
// ✅ Допустимо в store, UI, lib вне app/src/api — только barrel
|
|
21
|
-
import { MedcardApiService, MarketplaceApiService } from '@/api'
|
|
22
|
-
import type { TReferenceRequest } from '@/api'
|
|
23
|
-
|
|
24
|
-
// ❌ Запрещено снаружи app/src/api (сработает ESLint)
|
|
25
|
-
import { MedcardApiService } from '@/api/services/MedcardApiService/MedcardApiService'
|
|
26
|
-
import { MedcardApiClient } from '@/api/clients/MedcardApiClient'
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
При ревью и правках кода **не добавлять** новые импорты из `@/api/...` кроме `@/api` / `@/api/index` в файлах вне `app/src/api/**`.
|
|
30
|
-
|
|
31
|
-
**Коллизии формулировок:** по **импорту из API‑слоя** (store, UI, прочий код вне `app/src/api/**`) — источник правды — **этот файл** (`@/api`).
|
|
8
|
+
Содержимое перенесено в **`architecture/public-imports.md`** (раздел `@/api`).
|
|
@@ -7,14 +7,14 @@ paths:
|
|
|
7
7
|
|
|
8
8
|
## UI (`app/src/ui/**`)
|
|
9
9
|
|
|
10
|
-
- Может импортировать: `@/ui/**`, `@/store/**`, типы из `@/types` и enum из `@/types/enums` (**только как в `architecture/
|
|
10
|
+
- Может импортировать: `@/ui/**`, `@/store/**`, типы из `@/types` и enum из `@/types/enums` (**только как в `architecture/public-imports.md`**), контракт к API — **только** `import … from '@/api'` (**`architecture/public-imports.md`**).
|
|
11
11
|
- Не должен:
|
|
12
12
|
- обращаться к HTTP‑клиенту напрямую;
|
|
13
13
|
- знать детали DTO backend — только доменные типы.
|
|
14
14
|
|
|
15
15
|
## Store (`app/src/store/**`)
|
|
16
16
|
|
|
17
|
-
- Может импортировать: `@/store/**`, сервисы и публичные сущности API — **только** из `@/api` (**`architecture/
|
|
17
|
+
- Может импортировать: `@/store/**`, сервисы и публичные сущности API — **только** из `@/api` (**`architecture/public-imports.md`**), типы из `@/types` и enum из `@/types/enums` (**`architecture/public-imports.md`**).
|
|
18
18
|
- Не должен:
|
|
19
19
|
- зависеть от конкретных UI‑компонентов;
|
|
20
20
|
- напрямую работать с global/window API.
|
|
@@ -24,7 +24,7 @@ paths:
|
|
|
24
24
|
|
|
25
25
|
Реализация в `services/**`, `clients/**`, реэкспорт в `app/src/api/index.ts`:
|
|
26
26
|
|
|
27
|
-
- Внутри слоя: типы из `@/types` и enum из `@/types/enums` (**`architecture/
|
|
27
|
+
- Внутри слоя: типы из `@/types` и enum из `@/types/enums` (**`architecture/public-imports.md`**); импорты `@/api/services/**`, `@/api/clients/**`, относительные пути между файлами слоя (`api-and-data/http-client.md`, `api-and-data/api-services.md`).
|
|
28
28
|
- Не должен:
|
|
29
29
|
- тянуть в себя UI или store;
|
|
30
30
|
- смешивать HTTP‑слой и доменный слой — использовать мапперы.
|
|
@@ -39,7 +39,7 @@ paths:
|
|
|
39
39
|
|
|
40
40
|
- **Входящий адаптер**: UI — ввод пользователя, отображение; зависит от store и доменных типов, не от транспорта.
|
|
41
41
|
- **Оркестрация сценариев**: store (slices, thunk) — вызывает сервисы, кладёт в state **доменные** модели после маппинга.
|
|
42
|
-
- **Исходящий порт (контракт к backend)**: публичный API **`@/api`** (barrel `app/src/api/index.ts`; реализация — в `app/src/api/services/**` и т.д., см. `architecture/
|
|
42
|
+
- **Исходящий порт (контракт к backend)**: публичный API **`@/api`** (barrel `app/src/api/index.ts`; реализация — в `app/src/api/services/**` и т.д., см. `architecture/public-imports.md`).
|
|
43
43
|
- **Исходящий адаптер**: общая реализация HTTP в **`app/src/lib/clients/**`** и экземпляры в **`app/src/api/clients/**`**.
|
|
44
44
|
|
|
45
45
|
## Фича как срез
|
|
@@ -50,7 +50,7 @@ paths:
|
|
|
50
50
|
|
|
51
51
|
- Всегда использовать алиас `@/...` для импортов между слоями.
|
|
52
52
|
- Внутри одного модуля/фичи можно использовать относительные импорты, но **без подъёма выше корня фичи** (избегать `../../../`).
|
|
53
|
-
- При обращении из компонентов, хуков, утилит и других модулей к чужому слою или фиче использовать только **public API** (barrel/index‑файлы и явно экспортируемые сущности), не делать deep‑импорты внутренних файлов других фич; для регламентированных слоёв — **`architecture/layer-barrel-exports.md`** и `architecture
|
|
53
|
+
- При обращении из компонентов, хуков, утилит и других модулей к чужому слою или фиче использовать только **public API** (barrel/index‑файлы и явно экспортируемые сущности), не делать deep‑импорты внутренних файлов других фич; для регламентированных слоёв — **`architecture/layer-barrel-exports.md`** и `architecture/public-imports.md`; для API‑слоя снаружи `app/src/api/**` — **`architecture/public-imports.md`** (только `@/api`).
|
|
54
54
|
- При добавлении нового кода проверять:
|
|
55
55
|
- если модуль переиспользуемый — он должен зависеть только от более "низких" слоёв (types, utils, api), но не от страниц.
|
|
56
56
|
|
|
@@ -61,7 +61,7 @@ paths:
|
|
|
61
61
|
- Локальные компоненты: поддиректории `components/**` внутри страницы.
|
|
62
62
|
- Связанный store: `app/src/store/slices/OrderCheckout/**`.
|
|
63
63
|
- API: `app/src/api/services/OrdersApi/OrderCheckout/**` (имя корневого сервиса взять из принятой в проекте схемы).
|
|
64
|
-
- Типы: `app/src/types/**` с экспортом через barrel **`app/src/types/index.ts`** (`architecture/
|
|
64
|
+
- Типы: `app/src/types/**` с экспортом через barrel **`app/src/types/index.ts`** (`architecture/public-imports.md`).
|
|
65
65
|
|
|
66
66
|
# Требование к агенту
|
|
67
67
|
|
|
@@ -1,59 +1,28 @@
|
|
|
1
1
|
---
|
|
2
2
|
paths:
|
|
3
|
-
- app/src/**/*
|
|
3
|
+
- app/src/ui/**/*
|
|
4
|
+
- app/src/store/**/*
|
|
5
|
+
- app/src/api/**/*
|
|
6
|
+
- app/src/types/**/*
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Доставка фичи (сквозной порядок)
|
|
7
10
|
|
|
8
|
-
Типичная фича с данными с backend и общим состоянием. Детали слоёв —
|
|
9
|
-
|
|
10
|
-
Плейсхолдеры: `<FeatureName>`, `<ServiceRoot>`, `<Area>` — нейтральные имена; реальные имена брать из соседних фич того же типа.
|
|
11
|
-
|
|
12
|
-
## Инварианты перед кодом
|
|
13
|
-
|
|
14
|
-
- Найти в том же слое фичу сопоставимой сложности и **повторить структуру каталогов и паттерн именования**.
|
|
15
|
-
- Не добавлять `any`; при необходимости — `unknown` и сужение типа.
|
|
16
|
-
- После правок — **`tooling-and-review/post-change-lint.md`**: `lint:js` + `lint:css` + `type-check`; менеджер пакетов — `tooling-and-review/package-manager.md`.
|
|
11
|
+
Типичная фича с данными с backend и общим состоянием. Детали слоёв — `architecture/architecture-boundaries.md`, `stack/next-app-core.md`.
|
|
17
12
|
|
|
18
13
|
## Чеклист (порядок работ)
|
|
19
14
|
|
|
20
|
-
1. **Доменные типы** — `app/src/types/**`,
|
|
21
|
-
2. **Контракт API** — DTO
|
|
22
|
-
3. **Мапперы** — DTO → домен
|
|
23
|
-
4. **Сервисы** —
|
|
24
|
-
5.
|
|
25
|
-
6.
|
|
26
|
-
7.
|
|
27
|
-
8.
|
|
28
|
-
9.
|
|
29
|
-
10. **Завершение** — **`tooling-and-review/post-change-lint.md`**: из `app/` обязательно `lint:js` + `lint:css` (полный прогон), затем `type-check`.
|
|
15
|
+
1. **Доменные типы** — `app/src/types/**`, barrel (`architecture/public-imports.md`, **`architecture/layer-barrel-exports.md`**); JSDoc — `stack/types-jsdoc.md`.
|
|
16
|
+
2. **Контракт API** — DTO там, где принято; доменные типы в `@/types`.
|
|
17
|
+
3. **Мапперы** — DTO → домен (`api-and-data/api-services.md`).
|
|
18
|
+
4. **Сервисы** — клиенты `app/src/api/clients/**`, barrel `@/api` (`api-and-data/api-services.md`, `api-and-data/http-client.md`, **`architecture/layer-barrel-exports.md`**).
|
|
19
|
+
5. **Состояние** — slice/thunk (`api-and-data/store-rtk.md`); thunk → `@/api`.
|
|
20
|
+
6. **UI** — `@/types`, без DTO (`ui-and-accessibility/react-ui.md`, `architecture/architecture-boundaries.md`, `ui-and-accessibility/no-props-spread.md`).
|
|
21
|
+
7. **Моки** — `app/src/mocks/**`; регистрация в `handlers.ts` (см. ниже).
|
|
22
|
+
8. **Тесты** — unit (`testing/tests-unit.md`); e2e (`testing/tests-e2e-structure.md`, `testing/playwright-agents.md`).
|
|
23
|
+
9. **Завершение** — **`tooling-and-review/post-change-lint.md`**.
|
|
30
24
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
```mermaid
|
|
34
|
-
flowchart LR
|
|
35
|
-
typesNode["types_domain"]
|
|
36
|
-
apiNode["api_services_mappers"]
|
|
37
|
-
mocksNode["mocks_msw"]
|
|
38
|
-
storeNode["store_slice_thunks"]
|
|
39
|
-
mwNode["middleware_optional"]
|
|
40
|
-
uiNode["ui_pages_components"]
|
|
41
|
-
unitNode["unit_tests"]
|
|
42
|
-
e2eNode["e2e_plans_specs"]
|
|
43
|
-
|
|
44
|
-
typesNode --> apiNode
|
|
45
|
-
apiNode --> mocksNode
|
|
46
|
-
apiNode --> storeNode
|
|
47
|
-
storeNode --> mwNode
|
|
48
|
-
storeNode --> uiNode
|
|
49
|
-
apiNode --> unitNode
|
|
50
|
-
storeNode --> unitNode
|
|
51
|
-
uiNode --> unitNode
|
|
52
|
-
uiNode --> e2eNode
|
|
53
|
-
mocksNode --> e2eNode
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Поток данных (ориентир)
|
|
25
|
+
## Поток данных
|
|
57
26
|
|
|
58
27
|
```mermaid
|
|
59
28
|
flowchart LR
|
|
@@ -69,36 +38,42 @@ flowchart LR
|
|
|
69
38
|
Store --> UI[UI]
|
|
70
39
|
```
|
|
71
40
|
|
|
72
|
-
##
|
|
41
|
+
## Регистрация по слоям
|
|
42
|
+
|
|
43
|
+
1. **Типы** — `app/src/types/**`.
|
|
44
|
+
2. **API** — `app/src/api/services/<ServiceRoot>/<Segment>/`; публичные экспорты → **`app/src/api/index.ts`**.
|
|
45
|
+
3. **Моки** — `app/src/mocks/data/<feature>/`; **`app/src/mocks/handlers.ts`**; пути из `@/api`.
|
|
46
|
+
4. **Store** — `app/src/store/slices/<FeatureName>/`; **`app/src/store/reducers.ts`**; middleware → **`app/src/store/index.ts`**.
|
|
47
|
+
5. **UI** — pages/components; store/hooks.
|
|
48
|
+
6. **Unit** — `*.spec.ts(x)`; мапперы обязательно.
|
|
49
|
+
7. **E2E** — `app/__tests__/e2e/<Area>/<plan>.cases.md` + spec.
|
|
50
|
+
|
|
51
|
+
## Частичные сценарии
|
|
73
52
|
|
|
74
53
|
| Задача | Минимум действий |
|
|
75
54
|
|--------|------------------|
|
|
76
|
-
| Только API + типы |
|
|
77
|
-
| Только моки |
|
|
78
|
-
| Только store | Thunk на
|
|
79
|
-
| Только UI |
|
|
80
|
-
| Только e2e |
|
|
55
|
+
| Только API + типы | Типы, сервис, мапперы, `@/api` barrel; unit на маппер. |
|
|
56
|
+
| Только моки | Путь в `@/api`; handlers + `mocks/handlers.ts`. |
|
|
57
|
+
| Только store | Thunk на `@/api`; slice + `reducers.ts`. |
|
|
58
|
+
| Только UI | Store state; без HTTP/DTO. |
|
|
59
|
+
| Только e2e | `*.cases.md` + spec. |
|
|
81
60
|
|
|
82
61
|
## Антипаттерны
|
|
83
62
|
|
|
84
|
-
- DTO
|
|
85
|
-
-
|
|
86
|
-
- Deep
|
|
87
|
-
-
|
|
63
|
+
- DTO в UI или нетипизированном store.
|
|
64
|
+
- HTTP-клиент из компонента/thunk в обход сервиса.
|
|
65
|
+
- Deep-import `@/api/services/**` из UI/store.
|
|
66
|
+
- `{...props}` — `ui-and-accessibility/no-props-spread.md`.
|
|
88
67
|
|
|
89
|
-
## Матрица:
|
|
68
|
+
## Матрица: зона → правила
|
|
90
69
|
|
|
91
|
-
| Зона
|
|
92
|
-
|
|
93
|
-
| `app/src/api/clients/**`, `app/src/lib/clients/**` | `api-and-data/http-client.md
|
|
94
|
-
| `app/src/api/services/**` | `api-and-data/api-services.md`, `architecture/layer-barrel-exports.md
|
|
95
|
-
| `app/src/store/**` | `api-and-data/store-rtk.md`, `architecture/architecture-boundaries.md`, `architecture/
|
|
96
|
-
| `app/src/ui/**` | `ui-and-accessibility/react-ui.md`, `ui-and-accessibility/no-props-spread.md`, `architecture/
|
|
97
|
-
| `app/src/types/**` | `architecture/
|
|
70
|
+
| Зона | Правила |
|
|
71
|
+
|------|---------|
|
|
72
|
+
| `app/src/api/clients/**`, `app/src/lib/clients/**` | `api-and-data/http-client.md`, `testing/tests-unit.md` |
|
|
73
|
+
| `app/src/api/services/**` | `api-and-data/api-services.md`, `architecture/layer-barrel-exports.md` |
|
|
74
|
+
| `app/src/store/**` | `api-and-data/store-rtk.md`, `architecture/architecture-boundaries.md`, `architecture/public-imports.md` |
|
|
75
|
+
| `app/src/ui/**` | `ui-and-accessibility/react-ui.md`, `ui-and-accessibility/no-props-spread.md`, `architecture/public-imports.md` |
|
|
76
|
+
| `app/src/types/**` | `architecture/public-imports.md`, `stack/types-jsdoc.md`, `architecture/layer-barrel-exports.md` |
|
|
98
77
|
| `app/__tests__/e2e/**` | `testing/tests-e2e-structure.md`, `testing/playwright-agents.md` |
|
|
99
78
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
## Требование к агенту
|
|
103
|
-
|
|
104
|
-
При добавлении или существенном расширении фичи **пройти чеклист сверху** и при правках в зоне из таблицы **ориентироваться на указанные правила**, не смешивать слои и не обходить public API модулей.
|
|
79
|
+
При добавлении или расширении фичи **пройти чеклист** и правила из таблицы для затронутых зон.
|
|
@@ -10,7 +10,7 @@ paths:
|
|
|
10
10
|
Для **любого слоя** (каталога, пакета, bounded context), у которого:
|
|
11
11
|
|
|
12
12
|
- есть **корневой barrel** — единая точка импорта для внешних потребителей;
|
|
13
|
-
- deep-импорты внутрь слоя **запрещены** снаружи (ESLint `no-restricted-imports`, правила `architecture
|
|
13
|
+
- deep-импорты внутрь слоя **запрещены** снаружи (ESLint `no-restricted-imports`, правила `architecture/public-imports.md`).
|
|
14
14
|
|
|
15
15
|
Примеры alias/entry point в разных проектах: `@/api`, `@/types`, `@/core`, `@/store`, `packages/foo`.
|
|
16
16
|
|
|
@@ -33,7 +33,7 @@ paths:
|
|
|
33
33
|
|
|
34
34
|
При добавлении или существенном расширении **модуля внутри регламентированного слоя**:
|
|
35
35
|
|
|
36
|
-
1. Определить слой, его **корневой barrel** и доп. entry points (`architecture
|
|
36
|
+
1. Определить слой, его **корневой barrel** и доп. entry points (`architecture/public-imports.md`).
|
|
37
37
|
2. Создать/обновить **локальный** `index.ts` — только публичные символы.
|
|
38
38
|
3. Если в слое есть **фасад/агрегатор** (`*ApiService.ts`, `rootReducer`, …) — подключить модуль там.
|
|
39
39
|
4. Добавить **реэкспорт** новых публичных символов в **корневой barrel** слоя.
|
|
@@ -43,7 +43,7 @@ paths:
|
|
|
43
43
|
|
|
44
44
|
## Как найти регламентированные слои в репозитории
|
|
45
45
|
|
|
46
|
-
1. Правила `architecture
|
|
46
|
+
1. Правила `architecture/public-imports.md` в `.claude/rules/architecture/`.
|
|
47
47
|
2. ESLint `no-restricted-imports` — паттерны `@/<layer>/*` с исключением barrel.
|
|
48
48
|
3. `architecture/architecture-boundaries.md`, README проекта.
|
|
49
49
|
|
|
@@ -51,8 +51,8 @@ paths:
|
|
|
51
51
|
|
|
52
52
|
| Слой | Корневой barrel | Правило импортов |
|
|
53
53
|
|------|-----------------|------------------|
|
|
54
|
-
| API | `app/src/api/index.ts` | `architecture/
|
|
55
|
-
| Types | `app/src/types/index.ts` | `architecture/
|
|
54
|
+
| API | `app/src/api/index.ts` | `architecture/public-imports.md` |
|
|
55
|
+
| Types | `app/src/types/index.ts` | `architecture/public-imports.md` (+ `@/types/enums`) |
|
|
56
56
|
| Core | `app/src/core/index.ts` | ESLint: `@/core/index` |
|
|
57
57
|
|
|
58
58
|
Иллюстрация двух уровней (API): локальный `services/.../<Feature>/index.ts` → фасад `*ApiService.ts` → `app/src/api/index.ts`.
|