@bonesofspring/ai-rules 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/bin/cli.js +148 -14
  2. package/package.json +1 -1
  3. package/presets/claude/next/CLAUDE.md +11 -0
  4. package/presets/claude/next/README.md +14 -0
  5. package/presets/claude/next/agents/README.md +5 -0
  6. package/presets/claude/next/agents/playwright-test-generator.md +75 -0
  7. package/presets/claude/next/agents/playwright-test-healer.md +61 -0
  8. package/presets/claude/next/agents/playwright-test-planner.md +67 -0
  9. package/presets/claude/next/commands/README.md +4 -2
  10. package/presets/claude/next/hooks/README.md +5 -0
  11. package/presets/claude/next/rules/README.md +15 -2
  12. package/presets/claude/next/rules/api-and-data/README.md +3 -0
  13. package/presets/claude/next/rules/architecture/README.md +3 -0
  14. package/presets/claude/next/rules/stack/README.md +3 -0
  15. package/presets/claude/next/rules/testing/README.md +3 -0
  16. package/presets/claude/next/rules/tooling-and-review/README.md +3 -0
  17. package/presets/claude/next/rules/ui-and-accessibility/README.md +3 -0
  18. package/presets/claude/next/skills/README.md +5 -0
  19. package/presets/cursor/next/rules/README.md +12 -0
  20. package/presets/cursor/next/rules/api-services.mdc +56 -0
  21. package/presets/cursor/next/rules/architecture-boundaries.mdc +47 -0
  22. package/presets/cursor/next/rules/code-quality-and-refactoring.mdc +44 -0
  23. package/presets/cursor/next/rules/code-review-mr.mdc +47 -0
  24. package/presets/cursor/next/rules/emedcard-core.mdc +77 -0
  25. package/presets/cursor/next/rules/no-props-spread.mdc +39 -0
  26. package/presets/cursor/next/rules/playwright-agents.mdc +72 -0
  27. package/presets/cursor/next/rules/react-ui.mdc +67 -0
  28. package/presets/cursor/next/rules/store-rtk.mdc +59 -0
  29. package/presets/cursor/next/rules/tests-e2e-structure.mdc +51 -0
  30. package/presets/cursor/next/rules/tests-unit.mdc +46 -0
  31. package/presets/cursor/next/rules/next-stack.mdc +0 -9
package/bin/cli.js CHANGED
@@ -7,6 +7,9 @@ const path = require('path');
7
7
 
8
8
  const packageRoot = path.join(__dirname, '..');
9
9
 
10
+ /** Single path segment: letters, digits, dot, underscore, hyphen; no separators or "..". */
11
+ const PRESET_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
12
+
10
13
  const PRESETS = {
11
14
  cursor: {
12
15
  rulesDir: '.cursor/rules',
@@ -17,6 +20,10 @@ const PRESETS = {
17
20
  rulesDir: '.claude/rules',
18
21
  commandsDir: '.claude/commands',
19
22
  relBase: ['presets', 'claude'],
23
+ /** Optional dirs under preset root → under `.claude/` (recursive copy). */
24
+ optionalClaudeDirs: ['skills', 'agents', 'hooks'],
25
+ /** Copied from preset root to `.claude/CLAUDE.md` when present. */
26
+ claudeMdSrc: 'CLAUDE.md',
20
27
  },
21
28
  };
22
29
 
@@ -27,6 +34,10 @@ Usage:
27
34
  ai-rules init <cursor|claude> --preset <name> Copy preset rules and commands into the current directory
28
35
  ai-rules clean <cursor|claude> Remove preset target rules and commands directories
29
36
 
37
+ Notes:
38
+ init merges into existing target folders; same-named files are overwritten.
39
+ Flags may appear before or after the subcommand (e.g. --preset next init cursor).
40
+
30
41
  Examples:
31
42
  npx @bonesofspring/ai-rules init cursor --preset next
32
43
  npx @bonesofspring/ai-rules clean claude
@@ -38,11 +49,23 @@ function parseArgs(argv) {
38
49
  for (let i = 0; i < argv.length; i++) {
39
50
  const a = argv[i];
40
51
  if (a === '--preset') {
41
- args.preset = argv[++i];
52
+ const value = argv[i + 1];
53
+ if (value === undefined || value.startsWith('-')) {
54
+ args.presetError =
55
+ 'Missing value for --preset (use --preset <name> or --preset=<name>)';
56
+ continue;
57
+ }
58
+ args.preset = value;
59
+ i++;
42
60
  continue;
43
61
  }
44
62
  if (a.startsWith('--preset=')) {
45
- args.preset = a.slice('--preset='.length);
63
+ const value = a.slice('--preset='.length);
64
+ if (value === '') {
65
+ args.presetError = 'Missing value after --preset=';
66
+ continue;
67
+ }
68
+ args.preset = value;
46
69
  continue;
47
70
  }
48
71
  args._.push(a);
@@ -50,6 +73,35 @@ function parseArgs(argv) {
50
73
  return args;
51
74
  }
52
75
 
76
+ /**
77
+ * @returns {string | null} Error message or null if valid.
78
+ */
79
+ function validatePresetName(preset) {
80
+ if (preset === undefined || preset === '') {
81
+ return 'Missing --preset <name>';
82
+ }
83
+ if (!PRESET_NAME_RE.test(preset) || preset.includes('..')) {
84
+ return (
85
+ 'Invalid preset name: use one path segment (letters, digits, ., _, -), ' +
86
+ 'no slashes or ".." (example: next)'
87
+ );
88
+ }
89
+ return null;
90
+ }
91
+
92
+ /**
93
+ * Ensures resolved preset dir stays under the tool presets root (defense in depth).
94
+ */
95
+ function assertPresetDirInsideRoot(presetsRoot, presetBase) {
96
+ const root = path.resolve(presetsRoot);
97
+ const resolved = path.resolve(presetBase);
98
+ const rel = path.relative(root, resolved);
99
+ if (rel.startsWith('..') || path.isAbsolute(rel)) {
100
+ console.error('Invalid preset path (escapes package presets directory).');
101
+ process.exit(1);
102
+ }
103
+ }
104
+
53
105
  function copyDir(src, dest) {
54
106
  if (!fs.existsSync(src)) {
55
107
  throw new Error(`Source not found: ${src}`);
@@ -73,33 +125,88 @@ function removeDirIfExists(dir) {
73
125
  }
74
126
  }
75
127
 
128
+ function removeFileIfExists(filePath) {
129
+ if (fs.existsSync(filePath)) {
130
+ fs.unlinkSync(filePath);
131
+ }
132
+ }
133
+
134
+ function presetHasAnySource(base, cfg) {
135
+ const rulesSrc = path.join(base, 'rules');
136
+ const commandsSrc = path.join(base, 'commands');
137
+ if (fs.existsSync(rulesSrc) || fs.existsSync(commandsSrc)) {
138
+ return true;
139
+ }
140
+ if (cfg.optionalClaudeDirs) {
141
+ for (const name of cfg.optionalClaudeDirs) {
142
+ if (fs.existsSync(path.join(base, name))) {
143
+ return true;
144
+ }
145
+ }
146
+ }
147
+ if (cfg.claudeMdSrc && fs.existsSync(path.join(base, cfg.claudeMdSrc))) {
148
+ return true;
149
+ }
150
+ return false;
151
+ }
152
+
76
153
  function cmdInit(tool, preset) {
77
154
  const cfg = PRESETS[tool];
78
155
  if (!cfg) {
79
156
  console.error(`Unknown tool: ${tool}. Use cursor or claude.`);
80
157
  process.exit(1);
81
158
  }
82
- if (!preset) {
83
- console.error('Missing --preset <name>');
159
+ const nameErr = validatePresetName(preset);
160
+ if (nameErr) {
161
+ console.error(nameErr);
84
162
  process.exit(1);
85
163
  }
86
- const base = path.join(packageRoot, ...cfg.relBase, preset);
164
+ const presetsRoot = path.join(packageRoot, ...cfg.relBase);
165
+ const base = path.join(presetsRoot, preset);
166
+ assertPresetDirInsideRoot(presetsRoot, base);
167
+
87
168
  const rulesSrc = path.join(base, 'rules');
88
169
  const commandsSrc = path.join(base, 'commands');
89
170
  const cwd = process.cwd();
90
171
 
91
- if (!fs.existsSync(rulesSrc) && !fs.existsSync(commandsSrc)) {
172
+ if (!presetHasAnySource(base, cfg)) {
92
173
  console.error(`Preset "${preset}" for ${tool} not found under ${base}`);
93
174
  process.exit(1);
94
175
  }
95
176
 
96
- if (fs.existsSync(rulesSrc)) {
97
- copyDir(rulesSrc, path.join(cwd, cfg.rulesDir));
98
- console.log(`Copied rules → ${cfg.rulesDir}`);
99
- }
100
- if (fs.existsSync(commandsSrc)) {
101
- copyDir(commandsSrc, path.join(cwd, cfg.commandsDir));
102
- console.log(`Copied commands → ${cfg.commandsDir}`);
177
+ try {
178
+ if (tool === 'claude' && cfg.claudeMdSrc) {
179
+ const mdFrom = path.join(base, cfg.claudeMdSrc);
180
+ if (fs.existsSync(mdFrom)) {
181
+ const claudeRoot = path.join(cwd, '.claude');
182
+ fs.mkdirSync(claudeRoot, { recursive: true });
183
+ fs.copyFileSync(mdFrom, path.join(claudeRoot, 'CLAUDE.md'));
184
+ console.log('Copied CLAUDE.md → .claude/CLAUDE.md');
185
+ }
186
+ }
187
+
188
+ if (fs.existsSync(rulesSrc)) {
189
+ copyDir(rulesSrc, path.join(cwd, cfg.rulesDir));
190
+ console.log(`Copied rules → ${cfg.rulesDir}`);
191
+ }
192
+ if (fs.existsSync(commandsSrc)) {
193
+ copyDir(commandsSrc, path.join(cwd, cfg.commandsDir));
194
+ console.log(`Copied commands → ${cfg.commandsDir}`);
195
+ }
196
+
197
+ if (tool === 'claude' && cfg.optionalClaudeDirs) {
198
+ for (const name of cfg.optionalClaudeDirs) {
199
+ const src = path.join(base, name);
200
+ if (fs.existsSync(src)) {
201
+ copyDir(src, path.join(cwd, '.claude', name));
202
+ console.log(`Copied ${name}/ → .claude/${name}/`);
203
+ }
204
+ }
205
+ }
206
+ } catch (err) {
207
+ const msg = err instanceof Error ? err.message : String(err);
208
+ console.error(`init failed: ${msg}`);
209
+ process.exit(1);
103
210
  }
104
211
  }
105
212
 
@@ -112,7 +219,19 @@ function cmdClean(tool) {
112
219
  const cwd = process.cwd();
113
220
  removeDirIfExists(path.join(cwd, cfg.rulesDir));
114
221
  removeDirIfExists(path.join(cwd, cfg.commandsDir));
115
- console.log(`Removed ${cfg.rulesDir} and ${cfg.commandsDir} (if present)`);
222
+ if (tool === 'claude' && cfg.optionalClaudeDirs) {
223
+ for (const name of cfg.optionalClaudeDirs) {
224
+ removeDirIfExists(path.join(cwd, '.claude', name));
225
+ }
226
+ removeFileIfExists(path.join(cwd, '.claude', 'CLAUDE.md'));
227
+ }
228
+ console.log(
229
+ `Removed ${cfg.rulesDir} and ${cfg.commandsDir}` +
230
+ (tool === 'claude' && cfg.optionalClaudeDirs
231
+ ? `, optional .claude/{${cfg.optionalClaudeDirs.join(',')}}, and .claude/CLAUDE.md`
232
+ : '') +
233
+ ' (if present)',
234
+ );
116
235
  }
117
236
 
118
237
  function main() {
@@ -125,15 +244,30 @@ function main() {
125
244
  const parsed = parseArgs(argv);
126
245
  const [command, tool] = parsed._;
127
246
 
247
+ if (parsed.presetError) {
248
+ console.error(parsed.presetError);
249
+ process.exit(1);
250
+ }
251
+
128
252
  if (command === 'init') {
253
+ if (!tool) {
254
+ console.error('Missing <cursor|claude> after init.');
255
+ process.exit(1);
256
+ }
129
257
  cmdInit(tool, parsed.preset);
130
258
  return;
131
259
  }
132
260
  if (command === 'clean') {
261
+ if (!tool) {
262
+ console.error('Missing <cursor|claude> after clean.');
263
+ process.exit(1);
264
+ }
133
265
  cmdClean(tool);
134
266
  return;
135
267
  }
136
268
 
269
+ const got = command === undefined ? 'none' : command;
270
+ console.error(`Unknown command: ${got}. Use init or clean.`);
137
271
  printHelp();
138
272
  process.exit(1);
139
273
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonesofspring/ai-rules",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Presets of Cursor and Claude rules/commands for Revy Ross personal use",
5
5
  "license": "MIT",
6
6
  "author": "Revy Ross",
@@ -0,0 +1,11 @@
1
+ # Next.js stack — project instructions
2
+
3
+ Краткая точка входа для Claude Code. Подробные правила лежат в модульных файлах под `rules/` (подпапки по темам).
4
+
5
+ See @rules/README.md for how this preset splits instructions.
6
+
7
+ ## Conventions
8
+
9
+ - Держите **одну тему на файл**; для больших областей — подпапки в `rules/<topic>/`.
10
+ - Скоуп по путям проекта — через frontmatter `paths:` в отдельных `.md` (см. официальные docs по path-specific rules).
11
+ - Slash-команды — в `commands/`; переиспользуемые сценарии — в `skills/`.
@@ -0,0 +1,14 @@
1
+ # Preset `next` (Claude Code)
2
+
3
+ Структура отличается от пресета Cursor: здесь повторяется типичный **layout проекта Claude Code** под `.claude/`, а не плоский список `.mdc` в `rules/`.
4
+
5
+ | В пресете | Куда копирует `ai-rules init claude --preset next` |
6
+ |-----------|-----------------------------------------------------|
7
+ | `CLAUDE.md` | `.claude/CLAUDE.md` (точка входа, грузится в начале сессии) |
8
+ | `rules/**` | `.claude/rules/**` (рекурсивно: подпапки по темам, см. [документацию](https://code.claude.com/docs/en/memory#organize-rules-with-clauderules)) |
9
+ | `commands/**` | `.claude/commands/**` |
10
+ | `skills/**` | `.claude/skills/**` (если папка есть) |
11
+ | `agents/**` | `.claude/agents/**` (если папка есть) |
12
+ | `hooks/**` | `.claude/hooks/**` (если папка есть) |
13
+
14
+ Файлы правил — обычный Markdown с опциональным YAML frontmatter (`paths:` для скоупа по путям), не формат `.mdc` Cursor.
@@ -0,0 +1,5 @@
1
+ # `.claude/agents` (preset next)
2
+
3
+ Специализированные подагенты (personas) — по [документации Claude Code](https://code.claude.com/docs), если используете их в проекте.
4
+
5
+ Папка копируется в `.claude/agents/` при `ai-rules init claude --preset next`, если существует.
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: playwright-test-generator
3
+ description: 'Use this agent when you need to create automated browser tests using Playwright Examples: <example>Context: User wants to generate a test for the test plan item. <test-suite><!-- Verbatim name of the test spec group w/o ordinal like "Multiplication tests" --></test-suite> <test-name><!-- Name of the test case without the ordinal like "should add two numbers" --></test-name> <test-file><!-- Name of the file to save the test into, like tests/multiplication/should-add-two-numbers.spec.ts --></test-file> <seed-file><!-- Seed file path from test plan --></seed-file> <body><!-- Test case content including steps and expectations --></body></example>'
4
+ tools: Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_verify_element_visible, mcp__playwright-test__browser_verify_list_visible, mcp__playwright-test__browser_verify_text_visible, mcp__playwright-test__browser_verify_value, mcp__playwright-test__browser_wait_for, mcp__playwright-test__generator_read_log, mcp__playwright-test__generator_setup_page, mcp__playwright-test__generator_write_test
5
+ model: sonnet
6
+ color: blue
7
+ ---
8
+
9
+ You are a Playwright Test Generator, an expert in browser automation and end-to-end testing.
10
+ Your specialty is creating robust, reliable Playwright tests that accurately simulate user interactions and validate
11
+ application behavior.
12
+
13
+ ## Project-specific test structure (emedcard-web)
14
+
15
+ In this project you MUST respect the existing e2e layout:
16
+
17
+ - Test root: `app/__tests__/e2e`
18
+ - Test plans/specs: `*.cases.md` files under `app/__tests__/e2e/**`
19
+ - Executable tests: `*.spec.ts` files under `app/__tests__/e2e/**`
20
+ - Seed test: `app/__tests__/e2e/seed.spec.ts`
21
+
22
+ When you generate tests:
23
+
24
+ - Use the corresponding `*.cases.md` file under `app/__tests__/e2e/**` as the source plan (for example,
25
+ `app/__tests__/e2e/MedcardRecords/medcard-records.cases.md`).
26
+ - Write or update Playwright test files only under `app/__tests__/e2e/**` (for example,
27
+ `app/__tests__/e2e/MedcardRecords/medcard-records.spec.ts`) instead of creating files in a separate `tests/` folder.
28
+
29
+ # For each test you generate
30
+ - Obtain the test plan with all the steps and verification specification
31
+ - Run the `generator_setup_page` tool to set up page for the scenario
32
+ - For each step and verification in the scenario, do the following:
33
+ - Use Playwright tool to manually execute it in real-time.
34
+ - Use the step description as the intent for each Playwright tool call.
35
+ - Retrieve generator log via `generator_read_log`
36
+ - Immediately after reading the test log, invoke `generator_write_test` with the generated source code
37
+ - File should contain single test
38
+ - File name must be fs-friendly scenario name
39
+ - Test must be placed in a describe matching the top-level test plan item
40
+ - Test title must match the scenario name
41
+ - Includes a comment with the step text before each step execution. Do not duplicate comments if step requires
42
+ multiple actions.
43
+ - Always use best practices from the log when generating tests.
44
+
45
+ <example-generation>
46
+ For following plan:
47
+
48
+ ```markdown file=specs/plan.md
49
+ ### 1. Adding New Todos
50
+ **Seed:** `tests/seed.spec.ts`
51
+
52
+ #### 1.1 Add Valid Todo
53
+ **Steps:**
54
+ 1. Click in the "What needs to be done?" input field
55
+
56
+ #### 1.2 Add Multiple Todos
57
+ ...
58
+ ```
59
+
60
+ Following file is generated:
61
+
62
+ ```ts file=add-valid-todo.spec.ts
63
+ // spec: specs/plan.md
64
+ // seed: tests/seed.spec.ts
65
+
66
+ test.describe('Adding New Todos', () => {
67
+ test('Add Valid Todo', async { page } => {
68
+ // 1. Click in the "What needs to be done?" input field
69
+ await page.click(...);
70
+
71
+ ...
72
+ });
73
+ });
74
+ ```
75
+ </example-generation>
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: playwright-test-healer
3
+ description: Use this agent when you need to debug and fix failing Playwright tests
4
+ tools: Glob, Grep, Read, LS, Edit, MultiEdit, Write, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_generate_locator, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_snapshot, mcp__playwright-test__test_debug, mcp__playwright-test__test_list, mcp__playwright-test__test_run
5
+ model: sonnet
6
+ color: red
7
+ ---
8
+
9
+ You are the Playwright Test Healer, an expert test automation engineer specializing in debugging and
10
+ resolving Playwright test failures. Your mission is to systematically identify, diagnose, and fix
11
+ broken Playwright tests using a methodical approach.
12
+
13
+ ## Project-specific test structure (emedcard-web)
14
+
15
+ In this project you MUST respect the existing e2e layout:
16
+
17
+ - Test root: `app/__tests__/e2e`
18
+ - Test plans/specs: `*.cases.md` files under `app/__tests__/e2e/**`
19
+ - Executable tests: `*.spec.ts` files under `app/__tests__/e2e/**`
20
+ - Seed test: `app/__tests__/e2e/seed.spec.ts`
21
+
22
+ When healing tests:
23
+
24
+ - Only read and modify `*.spec.ts` files under `app/__tests__/e2e/**`.
25
+ - Use the `*.cases.md` file in the same folder as the failing test as the source of truth for intended behavior
26
+ (for example, `app/__tests__/e2e/MedcardRecords/medcard-records.cases.md` for
27
+ `app/__tests__/e2e/MedcardRecords/medcard-records.spec.ts`).
28
+
29
+ Your workflow:
30
+ 1. **Initial Execution**: Run all tests using `test_run` tool to identify failing tests
31
+ 2. **Debug failed tests**: For each failing test run `test_debug`.
32
+ 3. **Error Investigation**: When the test pauses on errors, use available Playwright MCP tools to:
33
+ - Examine the error details
34
+ - Capture page snapshot to understand the context
35
+ - Analyze selectors, timing issues, or assertion failures
36
+ 4. **Root Cause Analysis**: Determine the underlying cause of the failure by examining:
37
+ - Element selectors that may have changed
38
+ - Timing and synchronization issues
39
+ - Data dependencies or test environment problems
40
+ - Application changes that broke test assumptions
41
+ 5. **Code Remediation**: Edit the test code to address identified issues, focusing on:
42
+ - Updating selectors to match current application state
43
+ - Fixing assertions and expected values
44
+ - Improving test reliability and maintainability
45
+ - For inherently dynamic data, utilize regular expressions to produce resilient locators
46
+ 6. **Verification**: Restart the test after each fix to validate the changes
47
+ 7. **Iteration**: Repeat the investigation and fixing process until the test passes cleanly
48
+
49
+ Key principles:
50
+ - Be systematic and thorough in your debugging approach
51
+ - Document your findings and reasoning for each fix
52
+ - Prefer robust, maintainable solutions over quick hacks
53
+ - Use Playwright best practices for reliable test automation
54
+ - If multiple errors exist, fix them one at a time and retest
55
+ - Provide clear explanations of what was broken and how you fixed it
56
+ - You will continue this process until the test runs successfully without any failures or errors.
57
+ - If the error persists and you have high level of confidence that the test is correct, mark this test as test.fixme()
58
+ so that it is skipped during the execution. Add a comment before the failing step explaining what is happening instead
59
+ of the expected behavior.
60
+ - Do not ask user questions, you are not interactive tool, do the most reasonable thing possible to pass the test.
61
+ - Never wait for networkidle or use other discouraged or deprecated apis
@@ -0,0 +1,67 @@
1
+ ---
2
+ name: playwright-test-planner
3
+ description: Use this agent when you need to create comprehensive test plan for a web application or website
4
+ tools: Glob, Grep, Read, LS, mcp__playwright-test__browser_click, mcp__playwright-test__browser_close, mcp__playwright-test__browser_console_messages, mcp__playwright-test__browser_drag, mcp__playwright-test__browser_evaluate, mcp__playwright-test__browser_file_upload, mcp__playwright-test__browser_handle_dialog, mcp__playwright-test__browser_hover, mcp__playwright-test__browser_navigate, mcp__playwright-test__browser_navigate_back, mcp__playwright-test__browser_network_requests, mcp__playwright-test__browser_press_key, mcp__playwright-test__browser_run_code, mcp__playwright-test__browser_select_option, mcp__playwright-test__browser_snapshot, mcp__playwright-test__browser_take_screenshot, mcp__playwright-test__browser_type, mcp__playwright-test__browser_wait_for, mcp__playwright-test__planner_setup_page, mcp__playwright-test__planner_save_plan
5
+ model: sonnet
6
+ color: green
7
+ ---
8
+
9
+ You are an expert web test planner with extensive experience in quality assurance, user experience testing, and test
10
+ scenario design. Your expertise includes functional testing, edge case identification, and comprehensive test coverage
11
+ planning.
12
+
13
+ ## Project-specific test structure (emedcard-web)
14
+
15
+ In this project you MUST respect the existing e2e layout:
16
+
17
+ - Test root: `app/__tests__/e2e`
18
+ - Test plans/specs: `*.cases.md` files under `app/__tests__/e2e/**`
19
+ - Executable tests: `*.spec.ts` files under `app/__tests__/e2e/**`
20
+ - Seed test: `app/__tests__/e2e/seed.spec.ts`
21
+
22
+ When you create or update a test plan:
23
+
24
+ - Use the appropriate `*.cases.md` file under `app/__tests__/e2e/**` (for example,
25
+ `app/__tests__/e2e/MedcardRecords/medcard-records.cases.md`) instead of creating files in a separate `specs/` folder.
26
+ - Treat these `*.cases.md` files as the canonical, human-readable test plans for the Generator and Healer agents.
27
+
28
+ You will:
29
+
30
+ 1. **Navigate and Explore**
31
+ - Invoke the `planner_setup_page` tool once to set up page before using any other tools
32
+ - Explore the browser snapshot
33
+ - Do not take screenshots unless absolutely necessary
34
+ - Use `browser_*` tools to navigate and discover interface
35
+ - Thoroughly explore the interface, identifying all interactive elements, forms, navigation paths, and functionality
36
+
37
+ 2. **Analyze User Flows**
38
+ - Map out the primary user journeys and identify critical paths through the application
39
+ - Consider different user types and their typical behaviors
40
+
41
+ 3. **Design Comprehensive Scenarios**
42
+
43
+ Create detailed test scenarios that cover:
44
+ - Happy path scenarios (normal user behavior)
45
+ - Edge cases and boundary conditions
46
+ - Error handling and validation
47
+
48
+ 4. **Structure Test Plans**
49
+
50
+ Each scenario must include:
51
+ - Clear, descriptive title
52
+ - Detailed step-by-step instructions
53
+ - Expected outcomes where appropriate
54
+ - Assumptions about starting state (always assume blank/fresh state)
55
+ - Success criteria and failure conditions
56
+
57
+ 5. **Create Documentation**
58
+
59
+ Submit your test plan using `planner_save_plan` tool.
60
+
61
+ **Quality Standards**:
62
+ - Write steps that are specific enough for any tester to follow
63
+ - Include negative testing scenarios
64
+ - Ensure scenarios are independent and can be run in any order
65
+
66
+ **Output Format**: Always save the complete test plan as a markdown file with clear headings, numbered steps, and
67
+ professional formatting suitable for sharing with development and QA teams.
@@ -1,3 +1,5 @@
1
- # Claude commands (next preset)
1
+ # `.claude/commands` (preset next)
2
2
 
3
- Add slash command definitions for this preset. They are copied to `.claude/commands` when you run `ai-rules init claude --preset next`.
3
+ Определения slash-команд для проекта. Копируются в `.claude/commands/` при `ai-rules init claude --preset next`.
4
+
5
+ См. также корневой `README.md` пресета — у Claude Code помимо `rules/` и `commands/` часто используются `skills/`, `agents/`, `hooks/`.
@@ -0,0 +1,5 @@
1
+ # `.claude/hooks` (preset next)
2
+
3
+ Событийные хуки автоматизации Claude Code — по документации продукта, если включены в репозитории.
4
+
5
+ Папка копируется в `.claude/hooks/` при `ai-rules init claude --preset next`, если существует.
@@ -1,3 +1,16 @@
1
- # Claude rules (next preset)
1
+ # `.claude/rules` (preset next)
2
2
 
3
- Add markdown instruction files for this preset. They are copied to `.claude/rules` when you run `ai-rules init claude --preset next`.
3
+ В Claude Code все `.md` под `rules/` **обнаруживаются рекурсивно** подпапки по темам уместнее, чем один длинный файл.
4
+
5
+ Соответствие темам из пресета Cursor (для переноса смысла из `.mdc`):
6
+
7
+ | Папка | О чём |
8
+ |-------|--------|
9
+ | `stack/` | Next.js, React, TypeScript |
10
+ | `architecture/` | границы слоёв, модули |
11
+ | `api-and-data/` | сервисы, API, данные |
12
+ | `testing/` | unit, e2e, Playwright |
13
+ | `ui-and-accessibility/` | UI, a11y, без spread props там, где это правило команды |
14
+ | `tooling-and-review/` | качество кода, ревью MR |
15
+
16
+ Добавляйте сюда `.md` файлы с осмысленными именами (`testing.md`, `api-design.md`, …).
@@ -0,0 +1,3 @@
1
+ # API and data
2
+
3
+ Конвенции сервисов, API-слоя и работы с данными.
@@ -0,0 +1,3 @@
1
+ # Architecture
2
+
3
+ Границы модулей, слоёв и зависимостей (аналог темы architecture / boundaries в Cursor-пресете).
@@ -0,0 +1,3 @@
1
+ # Stack (Next.js, React, TypeScript)
2
+
3
+ Правила уровня фреймворка и языка для пресета `next`.
@@ -0,0 +1,3 @@
1
+ # Testing
2
+
3
+ Unit-тесты, e2e, структура Playwright-агентов — по отдельным `.md` при необходимости.
@@ -0,0 +1,3 @@
1
+ # Tooling and review
2
+
3
+ Рефакторинг, качество кода, процесс ревью MR.
@@ -0,0 +1,3 @@
1
+ # UI and accessibility
2
+
3
+ Компоненты, стили, доступность, паттерны React UI.
@@ -0,0 +1,5 @@
1
+ # `.claude/skills` (preset next)
2
+
3
+ [Skills](https://code.claude.com/docs/en/skills) в Claude Code — сценарии, которые подгружаются по необходимости, а не в каждой сессии целиком. Добавьте сюда `SKILL.md` или структуру skills по документации инструмента.
4
+
5
+ Папка копируется в `.claude/skills/` при `ai-rules init claude --preset next`, если существует.
@@ -0,0 +1,12 @@
1
+ ### Разница .mdc и .md в .cursor/rules
2
+
3
+ #### .md
4
+ Обычный markdown‑файл. Cursor видит его как документацию/контент, но не как правило, которое нужно автоматически применять.
5
+
6
+ #### .mdc
7
+ Специальный формат Cursor Rule:
8
+ - сверху обязателен YAML‑frontmatter с полями вроде description, globs, alwaysApply;
9
+ - файл лежит в .cursor/rules/;
10
+ - Cursor интерпретирует его как конфигурацию поведения ассистента для этого репо (автоматически подмешивает содержимое в контекст, когда правило подходит).
11
+
12
+ - То есть .mdc = “markdown + config для Cursor”, .md = просто текст без управляющего смысла для ассистента.
@@ -0,0 +1,56 @@
1
+ ---
2
+ description: Конвенции API сервисов и мапперов Medcard
3
+ globs: src/api/services/**/*.ts
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Роль API слоя
8
+
9
+ - Инкапсулировать всё, что связано с:
10
+ - HTTP/axios запросами,
11
+ - URL/путями,
12
+ - заголовками и кодами ответов,
13
+ - DTO backend.
14
+ - Предоставлять UI и store **стабильный доменный интерфейс**:
15
+ - функции, работающие с доменными типами из `@/types/**`.
16
+ - мапперы между DTO и доменными типами.
17
+
18
+ # Структура модулей
19
+
20
+ - Для каждой доменной области (Medcard, OfflineConsultation, RequestForAnalysis и т.п.):
21
+ - отдельный каталог в `src/api/services/MedcardApiService/**`.
22
+ - Внутри модуля:
23
+ - файлы с вызовами API (`index.ts` или `*.service.ts`);
24
+ - файлы мапперов (`*responseMappers.ts`);
25
+ - специфичные типы запросов/ответов (если не вынесены в `@/types/**`).
26
+ - один или несколько **public API** файлов (`index.ts` или barrel‑файлы), через которые к модулю обращаются UI, store и другие слои.
27
+
28
+ # Мапперы и типы
29
+
30
+ - Для каждого запроса/эндпоинта:
31
+ - описывать **response‑тип (DTO)**, точно соответствующий контракту backend;
32
+ - определять **целевой доменный тип** в `src/types/**`, с которым будет работать приложение (включая вычисляемые/агрегированные поля).
33
+ - Мапперы (например, `*responseMappers.ts`):
34
+ - чистые функции, без сайд‑эффектов;
35
+ - выполняют все необходимые вычисления и преобразования данных (булевы флаги, склейка строк, агрегаты и т.п.) при переводе из DTO в доменные модели;
36
+ - при необходимости обеспечивают обратное преобразование (доменные модели -> транспортные типы).
37
+ - UI и store работают только с доменными типами (из `@/types/**` или экспортируемыми из API слоя), а не с "сырыми" DTO.
38
+
39
+ # Обработка ошибок
40
+
41
+ - API‑слой:
42
+ - не должен "глотать" ошибки без следа;
43
+ - либо бросает доменные/унифицированные ошибки;
44
+ - либо возвращает результат в `Result<T, E>`‑подобной форме (если такой паттерн принят в проекте).
45
+ - Интеграция с Sentry / OpenTelemetry:
46
+ - если используется — делать её централизованно (например, в HTTP‑клиенте или обёртках), а не в каждом методе.
47
+
48
+ # Требование к агенту
49
+
50
+ При добавлении/изменении API‑метода:
51
+ - Следовать существующим сервисам и мапперам как эталону.
52
+ - Не смешивать слой API и UI/store:
53
+ - компоненты не должны зависеть от DTO;
54
+ - store не должен знать о HTTP‑деталях (URL, коды).
55
+ - При использовании API‑сервисов в UI, store и утилитах импортировать только из public API файлов модуля (например, `@/api/services/MedcardApiService/.../index`), а не из внутренних файлов‑реализаций.
56
+
@@ -0,0 +1,47 @@
1
+ ---
2
+ description: Архитектурные границы и правила импортов
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Границы между слоями
7
+
8
+ - **UI (src/ui/**)**:
9
+ - Может импортировать: `@/ui/**`, `@/store/**`, `@/types/**`, `@/api/services/**` (через публичные интерфейсы).
10
+ - Не должен:
11
+ - обращаться к HTTP/axios напрямую;
12
+ - знать детали DTO backend — только доменные типы.
13
+ - **Store (src/store/**)**:
14
+ - Может импортировать: `@/store/**`, `@/api/services/**`, `@/types/**`.
15
+ - Не должен:
16
+ - зависеть от конкретных UI‑компонентов;
17
+ - напрямую работать с global/window API.
18
+ - **API (src/api/services/**)**:
19
+ - Может импортировать: `@/types/**`, общие утилиты.
20
+ - Не должен:
21
+ - тянуть в себя UI или store;
22
+ - смешивать HTTP‑слой и доменный слой — использовать мапперы.
23
+
24
+ # Правила импортов
25
+
26
+ - Всегда использовать алиас `@/...` для импортов между слоями.
27
+ - Внутри одного модуля/фичи можно использовать относительные импорты, но **без подъёма выше корня фичи** (избегать `../../../`).
28
+ - При обращении из компонентов, хуков, утилит и других модулей к чужому слою или фиче использовать только **public API** (barrel/index‑файлы и явно экспортируемые сущности), не делать deep‑импорты внутренних файлов других фич.
29
+ - При добавлении нового кода проверять:
30
+ - если модуль переиспользуемый — он должен зависеть только от более "низких" слоёв (types, utils, api), но не от страниц.
31
+
32
+ # Организация фич
33
+
34
+ - Для сложных фич (например, OfflineConsultation):
35
+ - Страница: `src/ui/pages/OfflineConsultationPage/**`.
36
+ - Локальные компоненты: поддиректории `components/**` внутри страницы.
37
+ - Связанный store: `src/store/slices/OfflineConsultation/**`.
38
+ - API: `src/api/services/MedcardApiService/OfflineConsultation/**`.
39
+ - Типы: `src/types/OfflineConsultation.types.ts` или аналогичный файл.
40
+
41
+ # Требование к агенту
42
+
43
+ При добавлении новой функциональности:
44
+ - Разместить файлы в **соответствующих слоях**.
45
+ - Проверить существующие фичи с аналогичной структурой и **повторить их организацию**.
46
+ - Не "коротить" слои (например, не вызывать API прямо из компонента только ради упрощения).
47
+
@@ -0,0 +1,44 @@
1
+ ---
2
+ description: Поддержка и улучшение качества кода и архитектуры
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Поддержка существующего стиля
7
+
8
+ - Новые изменения должны:
9
+ - следовать существующим паттернам (имена, структура, типизация);
10
+ - минимизировать "стилистический шум" (лишние правки форматирования, rename без нужды).
11
+ - Перед добавлением нового решения:
12
+ - искать аналогичное в коде и **повторять подход**, а не изобретать новый.
13
+ - проверять, нет ли уже подходящего компонента или паттерна в `@sds/*` или существующем UI‑коде, прежде чем добавлять новый кастомный контрол.
14
+ - использовать при обращении к чужим модулям только их **public API** (index/barrel‑файлы и явно экспортируемые сущности), а deep‑импорты внутренних файлов рассматривать как повод для рефакторинга.
15
+
16
+ # Рефакторинг при изменениях
17
+
18
+ - Разрешён лёгкий refactor, если он:
19
+ - уменьшает дублирование;
20
+ - повышает читаемость;
21
+ - не ломает публичные контракты модулей.
22
+ - Примеры допустимых улучшений:
23
+ - вынести дублирующуюся логику в общий хук/утилиту;
24
+ - типизировать `any` и `unknown`, если это безболезненно;
25
+ - разделить слишком крупный компонент на несколько более простых;
26
+ - заменить локальные «магические» CSS‑значения (цвета, отступы, размеры) на токены из `@sds/tokens-*`, `@sds/brand-colors`, `@sds/tokens-typography` или централизованные UI‑примитивы;
27
+ - заменить deep‑импорты внутренних файлов других модулей на обращения к их public API.
28
+
29
+ # Ограничения
30
+
31
+ - Не выполнять "большой" рефакторинг, если задача точечная и не про архитектуру:
32
+ - не менять структуру директорий;
33
+ - не менять названия публичных типов/функций без явного запроса.
34
+ - При необходимости крупного изменения:
35
+ - сначала локально улучшить архитектуру минимальными шагами;
36
+ - оставить код в консистентном состоянии.
37
+
38
+ # Требование к агенту
39
+
40
+ При каждом изменении:
41
+ - Поддерживать принцип **“boy scout rule”**:
42
+ - оставлять модуль в немного лучшем состоянии, чем до изменения (простые, безопасные улучшения).
43
+ - Не жертвовать архитектурой и слоями ради краткости реализации.
44
+
@@ -0,0 +1,47 @@
1
+ ---
2
+ description: Требования к code review агентами Cursor для GitLab merge requests в emedcard-web
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Code review merge requests
7
+
8
+ - **Когда применять**
9
+ - Если пользователь просит: "проведи ревью", "оценить MR/ветку/дифф", "посмотри изменения".
10
+ - Опираться на локальный репозиторий: текущую ветку, `git diff` и открытые файлы, а не на данные GitLab API.
11
+
12
+ - **Что обязан проверить агент**
13
+ - **Архитектура и слои**:
14
+ - Соблюдение правил из `architecture-boundaries.mdc` и `emedcard-core.mdc`:
15
+ - UI (`src/ui/**`) не ходит напрямую в HTTP/axios и не знает DTO.
16
+ - Store (`src/store/**`) не зависит от UI и не работает с "сырыми" HTTP.
17
+ - API (`src/api/services/**`) не тянет UI/store, использует мапперы.
18
+ - **Импорты и организация кода**:
19
+ - Использование алиаса `@/...` вместо относительных импортов выше по дереву.
20
+ - Отсутствие deep‑импортов во внешние фичи; использование только public API.
21
+ - Размещение новых файлов в корректных слоях и директориях фич.
22
+ - **Типы и TS‑строгость**:
23
+ - Не допускать новых `any`; предпочитать доменные типы из `src/types/**`.
24
+ - Проверять корректность пропсов/возвращаемых типов, особенно в UI и API‑слое.
25
+ - **UI, стили и SDS**:
26
+ - Для компонентов и стилей сверяться с `react-ui.mdc` и `emedcard-core.mdc`:
27
+ - Использовать Linaria и компоненты/токены `@sds/*`, а не "магические" значения.
28
+ - Сохранять консистентность с существующими компонентами и паттернами.
29
+ - **Тесты**:
30
+ - Проверять, что для нетривиальных изменений:
31
+ - либо обновлены/добавлены unit‑тесты (`tests-unit.mdc`),
32
+ - либо e2e‑сценарии/спеки отражают новую логику (`playwright-agents.mdc`, `tests-e2e-structure.mdc`).
33
+ - Указывать, какие именно тесты стоит добавить или поправить.
34
+
35
+ - **Глубина и формат ревью**
36
+ - Фокус на **изменениях MR** (дифф относительно целевой ветки), а не на всём проекте.
37
+ - Сначала дать **высокоуровневый обзор** (что делает MR, риски, архитектурные замечания), затем список конкретных комментариев.
38
+ - Каждый комментарий делать:
39
+ - **конкретным** (указать файл/участок и проблему),
40
+ - **практичным** (предложить вариант исправления, опираясь на существующие паттерны),
41
+ - без "больших рефакторингов" в духе `code-quality-and-refactoring.mdc`, если задача локальная.
42
+
43
+ - **Ограничения для агента**
44
+ - Не придумывать несуществующие GitLab сущности (лейблы, авторов, статусы пайплайнов).
45
+ - Не менять общую архитектуру фичи без прямого запроса пользователя.
46
+ - Следовать принципу "boy scout rule": предлагать улучшения, которые реально можно внести в рамках MR.
47
+
@@ -0,0 +1,77 @@
1
+ ---
2
+ description: Базовые принципы, стек и архитектура emedcard-web
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Стек и окружение
7
+
8
+ - Проект: **Next.js 16**, **React 19**, **TypeScript 5 (strict)**.
9
+ - Сборка: Webpack/Rspack, Node >= 24.
10
+ - Тесты: Jest + Testing Library, e2e — Playwright.
11
+ - Моки: **MSW** (`msw`, `public/mockServiceWorker.js`).
12
+ - Стили и UI:
13
+ - CSS-in-JS: **Linaria** (`@linaria/core`, `@linaria/react`).
14
+ - Дизайн‑система: **SDS** (`@sds/*`) и набор дизайн‑токенов (`@sds/tokens-*`, `@sds/brand-colors`, `@sds/tokens-typography`).
15
+ - Трассировка и мониторинг: Sentry, OpenTelemetry.
16
+
17
+ # Структура проекта (верхний уровень)
18
+
19
+ - `app/` — корень Next.js приложения.
20
+ - `app/src/**` — исходный код приложения.
21
+ - `app/__tests__/e2e/**` — e2e‑тесты и планы.
22
+ - `app/tsconfig.json`:
23
+ - `baseUrl: "."`
24
+ - `paths: { "@/*": ["./src/*"] }`
25
+
26
+ **Требование:** во всех новых изменениях использовать алиас `@/*` вместо относительных импортов выше по дереву.
27
+
28
+ # Архитектурные слои
29
+
30
+ - **UI слой** (`src/ui/**`):
31
+ - `src/ui/pages/**` — страницы и контейнеры.
32
+ - `src/ui/components/**` — переиспользуемые компоненты.
33
+ - **Store слой** (`src/store/**`):
34
+ - `src/store/slices/**` — Redux Toolkit слайсы.
35
+ - `src/store/middleware/**` — middleware для сайд‑эффектов (например, файлы, аналитика).
36
+ - **API слой** (`src/api/services/**`):
37
+ - Сервисы и мапперы, инкапсулирующие HTTP‑логику.
38
+ - **Типы** (`src/types/**`):
39
+ - Общие доменные типы (OfflineConsultation, Medcard, Conclusion и т.д.).
40
+ - **Моки и тестовые данные** (`src/mocks/**`):
41
+ - Моковые данные и обработчики для MSW.
42
+
43
+ # Общие архитектурные принципы
44
+
45
+ - **Чёткое разделение слоёв**:
46
+ - UI знает только о доменных типах и публичных интерфейсах store/API.
47
+ - Store знает о доменных типах и API‑сервисах.
48
+ - API знает о транспортном слое (HTTP, axios и пр.) и DTO.
49
+ - **Никаких "проникновений" слоёв**:
50
+ - UI не обращается к API напрямую — только через store или абстракции сервисов.
51
+ - Store не работает напрямую с "сырыми" HTTP‑ответами — только через мапперы.
52
+ - **Типы — источник правды**:
53
+ - Новые сущности описывать в `src/types/**`, переиспользовать, а не дублировать типы по слоям.
54
+ - Не использовать `any`; при необходимости — `unknown` + безопасное сужение типа.
55
+
56
+ # Кодстайл и качества кода
57
+
58
+ - Следовать конфигам `eslint.config.mjs`, `.prettierrc`, `.stylelintrc`.
59
+ - Поддерживать:
60
+ - KISS, DRY, SOLID (в разумных пределах для фронта).
61
+ - Модульность и переиспользование через компоненты, хуки, слайсы, сервисы.
62
+ - Консистентный визуальный стиль за счёт использования готовых компонентов `@sds/*` и дизайн‑токенов @sds вместо локальных "магических" значений.
63
+ - При добавлении нового кода **искать и копировать существующие паттерны**:
64
+ - Для страниц — аналогичные файлы в `src/ui/pages/**`.
65
+ - Для блоков — компоненты в `src/ui/components/**`.
66
+ - Для API — сервисы в `src/api/services/**`.
67
+ - Для состояния — слайсы в `src/store/slices/**`.
68
+
69
+ # Работа агента
70
+
71
+ При генерации кода:
72
+ - Определить целевой слой (UI/store/API/типизация/тесты).
73
+ - Найти в соответствующей директории похожие примеры и **копировать архитектурный паттерн** (структура файлов, типы, именование).
74
+ - Не упрощать архитектуру в ущерб существующим слоям (не тянуть API в UI, не описывать "DTO" прямо в компонентах).
75
+ - Избегать использования `any` при типизации кода; при необходимости использовать `unknown` с последующим безопасным сужением типов.
76
+ - После создания или редактирования любых файлов **обязательно проверять проект на ошибки TypeScript и ESLint** (либо точечно по изменённым файлам, либо по всему проекту) и устранять найденные проблемы, если это возможно без изменения бизнес‑логики.
77
+
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: Избегать спред-а пропов при передаче в компоненты
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Не использовать спред пропов при передаче в компоненты
7
+
8
+ При вызове React-компонентов **передавать пропы явно**, а не через spread (`{...props}`).
9
+
10
+ ## Почему
11
+
12
+ - Явная передача делает зависимости компонента очевидными при чтении кода.
13
+ - Упрощает рефакторинг и поиск использований.
14
+ - Снижает риск случайно пробросить лишние или устаревшие пропы.
15
+
16
+ ## Примеры
17
+
18
+ ```tsx
19
+ // ❌ Плохо
20
+ const commonProps = { a, b, c }
21
+ return <Child {...commonProps} />
22
+
23
+ // ❌ Плохо
24
+ return <Child {...props} />
25
+
26
+ // ✅ Хорошо
27
+ return (
28
+ <Child
29
+ a={a}
30
+ b={b}
31
+ c={c}
32
+ />
33
+ )
34
+ ```
35
+
36
+ ## Исключения
37
+
38
+ - Передача всех пропов в нативный DOM-элемент (`<div {...rest} />`) допустима, если `rest` содержит только валидные HTML-атрибуты.
39
+ - Делегирование пропов в обёртку (wrapper) допустимо, если это явно документировано и обосновано.
@@ -0,0 +1,72 @@
1
+ ---
2
+ description: Playwright Agents (planner/generator/healer) configuration for e2e structure in app/__tests__/e2e
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Playwright Agents in this project
7
+
8
+ In this repository, Playwright Agents (planner, generator, healer) **must follow the existing e2e structure**:
9
+
10
+ - **Test directory**: `app/__tests__/e2e`
11
+ - **Test plans (specs)**: `*.cases.md` files under `app/__tests__/e2e/**`
12
+ - **Executable tests**: `*.spec.ts` files under `app/__tests__/e2e/**`
13
+ - **Seed test**: `app/__tests__/e2e/seed.spec.ts`
14
+
15
+ Do **not** introduce separate top-level `specs/` and `tests/` folders for real test coverage. Those may be used only as temporary sandboxes if explicitly requested.
16
+
17
+ ## Planner (test plans)
18
+
19
+ When acting as a **Planner** (or working with the Playwright planner agent):
20
+
21
+ - **Treat `*.cases.md` as the canonical test plan files**, equivalent to Playwright's `specs/*.md`.
22
+ - **Location**:
23
+ - For a feature/domain, use the corresponding `*.cases.md` file under `app/__tests__/e2e`, e.g.:
24
+ - `app/__tests__/e2e/MedcardRecords/medcard-records.cases.md`
25
+ - `app/__tests__/e2e/RequestForAnalysis/schedule-display.cases.md`
26
+ - **Content requirements**:
27
+ - Group scenarios by feature and subfeature using headings.
28
+ - For each scenario include:
29
+ - clear title,
30
+ - preconditions,
31
+ - ordered steps,
32
+ - expected results.
33
+ - Write in concise business language, but precise enough for automatic test generation.
34
+ - **Seed**:
35
+ - Assume environment is prepared by `app/__tests__/e2e/seed.spec.ts` (login, baseURL, mocks, etc.).
36
+
37
+ When asked to "generate a test plan" for a feature, **create or update the appropriate `*.cases.md` file in `app/__tests__/e2e/**`**, not in a separate `specs/` folder.
38
+
39
+ ## Generator (tests from plans)
40
+
41
+ When acting as a **Generator** (or working with the Playwright generator agent):
42
+
43
+ - **Source of truth for scenarios**:
44
+ - Use the relevant `*.cases.md` file under `app/__tests__/e2e/**` as the test plan.
45
+ - **Target for tests**:
46
+ - Generate or update `*.spec.ts` files under the same folder, e.g.:
47
+ - plan: `app/__tests__/e2e/MedcardRecords/medcard-records.cases.md`
48
+ - tests: `app/__tests__/e2e/MedcardRecords/medcard-records.spec.ts` (or additional `*.spec.ts` in that folder if needed).
49
+ - **Structure**:
50
+ - Use `test.describe` to group by top-level plan sections (feature / user flow).
51
+ - Use `test(...)` titles that match scenario names from the plan.
52
+ - Prefer Page Object and fluent interfaces that already exist in this project, for example:
53
+ - `app/__tests__/e2e/MedcardRecords/MedcardRecordsPage.ts`
54
+ - shared helpers under `app/__tests__/e2e/_shared/`.
55
+ - **Seed**:
56
+ - If a seed test is needed, use `app/__tests__/e2e/seed.spec.ts` as the reference for environment setup.
57
+
58
+ Do **not** generate Playwright tests into a separate `tests/` folder by default. Keep all e2e tests under `app/__tests__/e2e/**` to respect project conventions.
59
+
60
+ ## Healer (fixing tests)
61
+
62
+ When acting as a **Healer** (or working with the Playwright healer agent):
63
+
64
+ - Operate only on `*.spec.ts` files under `app/__tests__/e2e/**`.
65
+ - Use `*.cases.md` in the same folder as **documentation of the intended behavior**:
66
+ - Do not weaken or change business assertions in tests in a way that conflicts with the corresponding `*.cases.md`.
67
+ - Prefer updating locators, waits, and flow details to match the UI while keeping the scenario semantics intact.
68
+ - When multiple specs are involved, prioritize:
69
+ - the spec file in the same folder as the failing test,
70
+ - then shared utilities in `app/__tests__/e2e/_shared/`.
71
+
72
+ Healer should keep tests aligned with the existing test plans (`*.cases.md`) and with the page objects and helpers already used in the project.
@@ -0,0 +1,67 @@
1
+ ---
2
+ description: Паттерны React/Next UI и Linaria в emedcard-web
3
+ globs: src/ui/**/*.tsx
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Общие правила компонентов
8
+
9
+ - Использовать **функциональные компоненты** с хуками, без классов.
10
+ - Компонент должен:
11
+ - быть максимально "тонким" по бизнес‑логике;
12
+ - делегировать состояние в store/хуки, если оно нужно в нескольких местах;
13
+ - использовать SDS‑компоненты как строительные блоки.
14
+ - Перед созданием нового UI‑контрола агент должен явно рассмотреть существующие компоненты `@sds/*` и, если есть близкий по назначению, переиспользовать или расширить его вместо написания кастомного с нуля.
15
+ - Для повторяемой логики создавать `useSomething`‑хуки рядом или в `src/ui/hooks/**`.
16
+ - При обращении к store, API, общим хелперам и утилитам компоненты и хуки должны использовать только их **public API** (например, `@/store`, `@/store/slices/Foo`, `@/lib/utils`), а не импортировать внутренние файлы реализации других модулей.
17
+
18
+ # Структура файлов
19
+
20
+ Для страницы/крупного блока:
21
+ - `FeatureBlock.tsx` — JSX и композиция.
22
+ - `styles.ts` — Linaria‑стили (`styled`, `css`).
23
+ - `index.ts` — реэкспорт (если нужно наружу).
24
+
25
+ Для переиспользуемого компонента:
26
+ - Папка с именем компонента:
27
+ - `ComponentName.tsx`
28
+ - `styles.ts`
29
+ - опционально: `types.ts`, `hooks.ts`.
30
+
31
+ # Использование SDS и Linaria
32
+
33
+ - Для UI‑контролов использовать компоненты из `@sds/*`:
34
+ - кнопки, чекбоксы, поля ввода и т.д.
35
+ - Стили:
36
+ - Использовать Linaria (`@linaria/react`, `@linaria/core`) со статическими стилями.
37
+ - Стили располагать в `styles.ts` рядом с компонентом.
38
+ - Применять дизайн‑токены из `@sds/tokens-*`, `@sds/brand-colors` и `@sds/tokens-typography` для цветов, типографики, отступов, размеров, радиусов, теней и т.д., а не “магические” значения.
39
+ - Избегать:
40
+ - inline‑стилей, кроме самых простых случаев;
41
+ - дублирования CSS, уже представленного в дизайн‑системе;
42
+ - «сырого» CSS вида `#xxxxxx`, `rgb(...)`, произвольных `padding: 17px`, `margin: 23px`, нестандартизированных размеров и теней.
43
+ - Если подходящего токена пока нет, допускается ввод локальных примитивов (например, `const spacingMedium = '16px'`) **в одном месте** с последующим переездом на официальные токены @sds при первой возможности.
44
+
45
+ # Пропсы и типизация
46
+
47
+ - Описывать пропсы через `type Props = { ... }` или `interface Props { ... }`.
48
+ - Не использовать `any`; при необходимости:
49
+ - обобщения (`<T>`), `unknown`, тип‑предикаты и user‑defined type guards.
50
+ - Для доменных сущностей использовать типы из `@/types/**`, а не описывать их заново.
51
+
52
+ # Логика и side effects
53
+
54
+ - Side effects и асинхронщина:
55
+ - по возможности выносить в store (thunk‑и, middleware) или в отдельные хуки.
56
+ - Компоненты не должны:
57
+ - напрямую знать детали API (URL, структура DTO);
58
+ - заниматься маппингом "сырых" DTO — только доменные типы;
59
+ - содержать нетривиальные вычисления и преобразования данных (булевы флаги, сложная склейка строк, агрегаты и т.п.). В большинстве случаев данные для отображения должны быть подготовлены на этапах маппинга/подготовки данных (API -> доменная модель -> store), а компоненты использовать уже готовые поля.
60
+
61
+ # Тестирование UI
62
+
63
+ - Для нетривиальных компонентов добавлять тесты:
64
+ - использовать `@testing-library/react` и `@testing-library/jest-dom`.
65
+ - проверять поведение и бизнес‑правила, а не конкретные CSS‑классы.
66
+ - В тестах ориентироваться на текст, роли и aria‑атрибуты.
67
+
@@ -0,0 +1,59 @@
1
+ ---
2
+ description: Redux Toolkit и состояние приложения
3
+ globs: src/store/**/*.ts
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Общие принципы
8
+
9
+ - Использовать **Redux Toolkit**:
10
+ - `createSlice`, `createAsyncThunk`, RTK Query (если используется).
11
+ - Хранить в store **доменные модели**, не "сырые" DTO из API.
12
+ - Все вычисления и преобразования данных (включая вычисляемые поля, булевые флаги, агрегаты, человеко‑читаемые строки и т.п.) должны выполняться **между ответом API и записью в store** — в мапперах или отдельном слое подготовки данных. Store хранит уже подготовленную доменную модель.
13
+ - Разделять:
14
+ - "серверное" состояние (данные из API) и
15
+ - локальное UI‑состояние (выбор/фильтры/флаги).
16
+
17
+ # Структура слайсов
18
+
19
+ - Каждый доменный модуль — свой слайс в `src/store/slices/**`.
20
+ - Слайс экспортирует:
21
+ - `reducer` по умолчанию;
22
+ - `actions` именованным экспортом;
23
+ - селекторы `selectSomething(state: RootState): Type`.
24
+ - Состояние:
25
+ - явный тип для state;
26
+ - аккуратная инициализация initialState.
27
+
28
+ # Асинхронность и сайд‑эффекты
29
+
30
+ - Асинхронные запросы:
31
+ - через `createAsyncThunk` или RTK Query.
32
+ - внутри thunk:
33
+ - вызывать API через сервисы из `@/api/services/**`;
34
+ - не использовать `fetch`/`axios` напрямую.
35
+ - Сайд‑эффекты (логирование, аналитика, работа с файлами):
36
+ - выносить в middleware (`src/store/middleware/**`) или специализированные слайсы.
37
+
38
+ # Типизация
39
+
40
+ - Использовать `RootState`, `AppDispatch` и типизированные хуки `useAppDispatch`, `useAppSelector` (если есть).
41
+ - Для сущностей:
42
+ - доменные типы (включая вычисляемые поля) определять в `@/types/**` и импортировать в слайсы как **источник правды** для структуры данных;
43
+ - избегать дублирования описаний сущностей в нескольких местах.
44
+
45
+ # Тестирование слайсов
46
+
47
+ - Для важных слайсов:
48
+ - тестировать редюсеры (инициализация, основные переходы состояний).
49
+ - тестировать селекторы (включая edge cases).
50
+ - Thunk‑и:
51
+ - по возможности покрывать тестами с моками API‑слоя.
52
+
53
+ # Требование к агенту
54
+
55
+ При изменении/создании слайса:
56
+ - Не класть логику API внутрь редюсеров/компонентов.
57
+ - Строго типизировать state и actions.
58
+ - Использовать единый стиль именования actions и селекторов, как в существующих слайсах.
59
+
@@ -0,0 +1,51 @@
1
+ ---
2
+ description: Структура e2e тестов и планов (Playwright)
3
+ globs: app/__tests__/e2e/**/*
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Структура e2e в проекте
8
+
9
+ - Папка e2e: `app/__tests__/e2e/**`.
10
+ - Планы сценариев:
11
+ - `*.cases.md` файлы — **канонический источник сценариев**.
12
+ - Тесты:
13
+ - `*.spec.ts` файлы — реализация сценариев на Playwright.
14
+ - Общие утилиты и абстракции:
15
+ - `app/__tests__/e2e/_shared/**` — константы, fluent‑интерфейсы, хелперы.
16
+
17
+ # Принципы
18
+
19
+ - Каждый сценарий из `*.cases.md` должен иметь соответствующий тест (или набор тестов).
20
+ - **Нельзя** ослаблять проверки в тестах, если это противоречит бизнес‑ожиданиям из планов.
21
+ - Предпочтительно использовать:
22
+ - page‑objects (например, `MedcardRecordsPage.ts`);
23
+ - общие хелперы из `_shared`.
24
+
25
+ # Именование e2e‑тестов
26
+
27
+ - Язык:
28
+ - все названия `test` / `it`, `describe`‑блоков и шагов в `*.cases.md` должны быть сформулированы **на русском языке**, описывая поведение и ожидаемый результат.
29
+ - Формат заголовков e2e‑тестов (`test(...)` / `it(...)`):
30
+ - перед текстовым описанием сценария указывается **префикс с номером** в формате: `ПРЕФИКС-XXX Описание сценария`.
31
+ - `ПРЕФИКС` — аббревиатура из **первых букв слов** тестируемой сущности, записанная **латиницей в верхнем регистре**.
32
+ - пример: `MedcardRecords` → `MR`, `RequestForAnalysis` → `RFA`.
33
+ - `XXX` — порядковый номер теста **с тремя разрядами и лидирующими нулями**: `001`, `002`, `010`, `123` и т.д.
34
+ - пример полного названия e2e‑теста:
35
+ - `test('MR-001 Отображается список записей медкарты', async ({ page }) => { ... })`
36
+ - внутри одной сущности (`ПРЕФИКС`) номера тестов должны образовывать **непротиворечивую последовательность**, без дубликатов номеров.
37
+
38
+ # data-testid для e2e
39
+
40
+ - **Приоритет селекторов:** `data-testid` для стабильных элементов; `getByRole` и `getByLabel` для форм и доступных элементов.
41
+ - **Именование:** схема `{parent}__{element}` (например, `history-page__title`, `history-page__recognition-banner__attach-files-button`).
42
+ - **Где добавлять:** на корневые контейнеры страниц и ключевые интерактивные элементы (кнопки, ссылки, поля), к которым обращаются page objects.
43
+ - **При изменении UI:** обновлять data-testid в компонентах и соответствующие селекторы в page objects; сверять с `*.cases.md`.
44
+
45
+ # Требование к агенту
46
+
47
+ При добавлении/изменении e2e‑тестов:
48
+ - Сначала смотреть соответствующий `*.cases.md` и синхронизировать названия сценариев.
49
+ - Размещать спеки рядом с планами в той же директории.
50
+ - Переиспользовать общие page‑objects и хелперы, а не копировать селекторы напрямую в каждый тест.
51
+
@@ -0,0 +1,46 @@
1
+ ---
2
+ description: Unit и интеграционные тесты (Jest, Testing Library)
3
+ globs: src/**/*.test.{ts,tsx}
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Общие правила тестирования
8
+
9
+ - Фреймворк: **Jest** + **@testing-library/react**.
10
+ - Основная цель тестов:
11
+ - проверять **поведение и бизнес‑правила**, а не реализацию или внутренние детали.
12
+ - Именование:
13
+ - названия `describe` / `it` / `test` и любые человекочитаемые описания в тестах **должны быть на русском языке**, формулироваться как понятные бизнес‑фразы (что именно ожидается от системы).
14
+ - строки в `describe` / `it` / `test` **должны начинаться с заглавной буквы**.
15
+
16
+ # Тесты компонентов
17
+
18
+ - Использовать `render` из `@testing-library/react`.
19
+ - Ассерты:
20
+ - `@testing-library/jest-dom` (`toBeInTheDocument`, `toHaveTextContent` и т.п.).
21
+ - Взаимодействия:
22
+ - `userEvent` из `@testing-library/user-event`.
23
+
24
+ # Изоляция и моки
25
+
26
+ - Для работы с API/store:
27
+ - мокать store (через test‑store) или использовать MSW, если это принято.
28
+ - Не мокать то, что является частью публичного контракта фичи, если это ломает смысл теста.
29
+
30
+ # Мапперы и преобразование данных
31
+
32
+ - Функции маппинга данных (DTO -> доменная модель и обратно), особенно содержащие вычисляемые поля и ветвления, должны быть покрыты unit‑тестами.
33
+ - В тестах мапперов особое внимание уделять edge‑кейсам и регрессии бизнес‑правил (например, граничные значения, отсутствие полей, неожиданные комбинации значений).
34
+
35
+ # Требование к агенту
36
+
37
+ При добавлении тестов:
38
+ - Следовать существующей структуре и паттернам тестов в `src/**/__tests__/**` или рядом с компонентом.
39
+ - Добавлять тесты для критичных веток логики и edge‑кейсов.
40
+ - При работе с данными:
41
+ - использовать **типы респонса** из API (DTO‑типы), а также **целевые доменные типы** из `@/types/**`, не дублировать интерфейсы в тестах;
42
+ - по возможности опираться на данные и хендлеры мок‑сервера **MSW** из `app/src/mocks/**`, а не плодить случайные тестовые данные "с нуля".
43
+ - При написании unit‑тестов рядом с компонентом или модулем:
44
+ - **не создавать** поддиректорию `__tests__` внутри папки компонента;
45
+ - именовать файлы тестов с суффиксом `*.spec.ts` / `*.spec.tsx`, а не `*.test.ts` / `*.test.tsx`.
46
+
@@ -1,9 +0,0 @@
1
- ---
2
- description: Next.js stack conventions (placeholder — extend this preset)
3
- globs: **/*.{ts,tsx}
4
- alwaysApply: false
5
- ---
6
-
7
- # Next.js preset
8
-
9
- This file is a placeholder for the **next** Cursor preset. Replace with your project rules.