@7n/rules 1.31.0 → 1.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +1 -1
  3. package/rules/{test → k8s/dremio_logging}/docs/index.md +2 -4
  4. package/rules/k8s/dremio_logging/docs/main.md +31 -0
  5. package/skills/taze/js/docs/index.md +4 -6
  6. package/skills/taze/js/docs/migration-cache.md +38 -0
  7. package/rules/test/cargo_mutants_config/cargo_mutants_config.mdc +0 -18
  8. package/rules/test/cargo_mutants_config/concern.json +0 -8
  9. package/rules/test/cargo_mutants_config/data/cargo_mutants_config/mutants.toml.baseline +0 -7
  10. package/rules/test/cargo_mutants_config/docs/fix-cargo_mutants_config.md +0 -31
  11. package/rules/test/cargo_mutants_config/docs/index.md +0 -12
  12. package/rules/test/cargo_mutants_config/docs/main.md +0 -36
  13. package/rules/test/cargo_mutants_config/fix-cargo_mutants_config.mjs +0 -49
  14. package/rules/test/cargo_mutants_config/main.mjs +0 -62
  15. package/rules/test/lib/collect-test-file-offenders.mjs +0 -49
  16. package/rules/test/lib/docs/collect-test-file-offenders.md +0 -30
  17. package/rules/test/lib/docs/index.md +0 -9
  18. package/rules/test/location/concern.json +0 -8
  19. package/rules/test/location/docs/index.md +0 -11
  20. package/rules/test/location/docs/main.md +0 -36
  21. package/rules/test/location/location.mdc +0 -52
  22. package/rules/test/location/main.mjs +0 -70
  23. package/rules/test/main.json +0 -1
  24. package/rules/test/main.mdc +0 -26
  25. package/rules/test/no-bun-test-import/concern.json +0 -7
  26. package/rules/test/no-bun-test-import/docs/fix-no-bun-test-import.md +0 -31
  27. package/rules/test/no-bun-test-import/docs/index.md +0 -10
  28. package/rules/test/no-bun-test-import/docs/main.md +0 -36
  29. package/rules/test/no-bun-test-import/fix-no-bun-test-import.mjs +0 -51
  30. package/rules/test/no-bun-test-import/main.mjs +0 -105
  31. package/rules/test/no-bun-test-import/no-bun-test-import.mdc +0 -9
  32. package/rules/test/no-console-store-restore/concern.json +0 -7
  33. package/rules/test/no-console-store-restore/docs/index.md +0 -11
  34. package/rules/test/no-console-store-restore/docs/main.md +0 -44
  35. package/rules/test/no-console-store-restore/main.mjs +0 -55
  36. package/rules/test/no-console-store-restore/no-console-store-restore.mdc +0 -11
  37. package/rules/test/no-process-chdir/concern.json +0 -7
  38. package/rules/test/no-process-chdir/docs/index.md +0 -11
  39. package/rules/test/no-process-chdir/docs/main.md +0 -32
  40. package/rules/test/no-process-chdir/main.mjs +0 -40
  41. package/rules/test/no-process-chdir/no-process-chdir.mdc +0 -15
  42. package/rules/test/no-relative-fs-path/concern.json +0 -7
  43. package/rules/test/no-relative-fs-path/docs/index.md +0 -11
  44. package/rules/test/no-relative-fs-path/docs/main.md +0 -34
  45. package/rules/test/no-relative-fs-path/main.mjs +0 -239
  46. package/rules/test/no-relative-fs-path/no-relative-fs-path.mdc +0 -22
  47. package/rules/test/package_json/concern.json +0 -11
  48. package/rules/test/package_json/package_json.mdc +0 -18
  49. package/rules/test/package_json/package_json.rego +0 -25
  50. package/rules/test/package_json/template/package.json.contains.json +0 -6
  51. package/rules/test/sandbox-aware-test/concern.json +0 -7
  52. package/rules/test/sandbox-aware-test/docs/index.md +0 -11
  53. package/rules/test/sandbox-aware-test/docs/main.md +0 -55
  54. package/rules/test/sandbox-aware-test/main.mjs +0 -89
  55. package/rules/test/sandbox-aware-test/sandbox-aware-test.mdc +0 -28
  56. package/rules/test/stryker_config/concern.json +0 -8
  57. package/rules/test/stryker_config/data/stryker_config/docs/index.md +0 -13
  58. package/rules/test/stryker_config/data/stryker_config/docs/stryker-vue-macros-ignorer.md +0 -31
  59. package/rules/test/stryker_config/data/stryker_config/docs/stryker.config.baseline.md +0 -31
  60. package/rules/test/stryker_config/data/stryker_config/docs/stryker.config.vue.baseline.md +0 -35
  61. package/rules/test/stryker_config/data/stryker_config/stryker-vue-macros-ignorer.mjs +0 -48
  62. package/rules/test/stryker_config/data/stryker_config/stryker.config.baseline.mjs +0 -18
  63. package/rules/test/stryker_config/data/stryker_config/stryker.config.vue.baseline.mjs +0 -23
  64. package/rules/test/stryker_config/data/vitest_config/docs/index.md +0 -11
  65. package/rules/test/stryker_config/data/vitest_config/docs/vitest.config.baseline.md +0 -35
  66. package/rules/test/stryker_config/data/vitest_config/vitest.config.baseline.js +0 -22
  67. package/rules/test/stryker_config/docs/fix-stryker_config.md +0 -42
  68. package/rules/test/stryker_config/docs/index.md +0 -12
  69. package/rules/test/stryker_config/docs/main.md +0 -38
  70. package/rules/test/stryker_config/fix-stryker_config.mjs +0 -76
  71. package/rules/test/stryker_config/main.mjs +0 -504
  72. package/rules/test/stryker_config/stryker_config.mdc +0 -26
  73. package/rules/test/vitest-api-conventions/concern.json +0 -7
  74. package/rules/test/vitest-api-conventions/docs/index.md +0 -9
  75. package/rules/test/vitest-api-conventions/docs/main.md +0 -40
  76. package/rules/test/vitest-api-conventions/main.mjs +0 -153
  77. package/rules/test/vitest-api-conventions/vitest-api-conventions.mdc +0 -129
  78. package/rules/test/vitest-config-pool-forks/concern.json +0 -7
  79. package/rules/test/vitest-config-pool-forks/docs/index.md +0 -11
  80. package/rules/test/vitest-config-pool-forks/docs/main.md +0 -42
  81. package/rules/test/vitest-config-pool-forks/main.mjs +0 -41
  82. package/rules/test/vitest-config-pool-forks/vitest-config-pool-forks.mdc +0 -34
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.32.0] - 2026-07-19
4
+
5
+ ### Changed
6
+
7
+ - lint: правило test переїхало у @7n/rules-lang-js (vitest/stryker/ізоляція тестів), а концерн cargo_mutants_config — у правило rust плагіна @7n/rules-lang-rust (семантично канон rust-тулчейну; активація за glob Cargo.toml, у rust-only репо працює без lang-js) — у ядрі 23 правила, мовних правил не лишилось
8
+
3
9
  ## [1.31.0] - 2026-07-19
4
10
 
5
11
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/rules",
3
- "version": "1.31.0",
3
+ "version": "1.32.0",
4
4
  "description": "CLI еталонних правил і skills (префікс n-): синк у репозиторій, дельта-lint, конформність",
5
5
  "keywords": [
6
6
  "cli",
@@ -1,11 +1,9 @@
1
1
  ---
2
2
  type: Directory Index
3
- title: npm/rules/test
4
- resource: npm/rules/test/
3
+ title: npm/rules/k8s/dremio_logging
4
+ resource: npm/rules/k8s/dremio_logging/
5
5
  ---
6
6
 
7
- # npm/rules/test
8
-
9
7
  | Файл | Тип |
10
8
  | ------------------- | --------- |
11
9
  | [main.mjs](main.md) | JS Module |
@@ -0,0 +1,31 @@
1
+ ---
2
+ type: JS Module
3
+ title: main.mjs
4
+ resource: npm/rules/k8s/dremio_logging/main.mjs
5
+ docgen:
6
+ crc: a89abb0a
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
+ score: 95
10
+ issues: anchor-miss:(k8s.mdc),judge:inaccurate:0.99
11
+ judgeModel: openai-codex/gpt-5.4-mini
12
+ ---
13
+
14
+ ## Огляд
15
+
16
+ `zkLogbackRootLevelViolation` перевіряє повідомлення, пов’язані з надто гучним `root` у `k8s.mdc`, а `lint` збирає ці перевірки в один pass і повертає результат без зупинки процесу. Поведінка read-only: правило не пише у ФС чи БД, працює fail-safe й не кидає винятків назовні.
17
+
18
+ ## Поведінка
19
+
20
+ - `zkLogbackRootLevelViolation` — перевіряє, чи вбудований `logback.xml` у ZooKeeper-templated файлі не тримає `root` на надто гучному рівні; повертає текст порушення з міткою `` або `null`, якщо перевірка не потрібна або рівень уже прийнятний.
21
+ - `lint` — проходить по вказаних файлах у read-only режимі, збирає порушення для `k8s.dremio_logging` і не виводить помилки назовні; пропускає файли, які не вдалося прочитати, та позначає знайдені проблеми міткою ``.
22
+
23
+ ## Публічний API
24
+
25
+ - zkLogbackRootLevelViolation — позначає ZooKeeper Helm-темплейт, якщо вбудований `logback.xml` має занадто гучний `root`-рівень (`info`, `debug`, `trace`) або взагалі не задає `root`; не чіпає файли, де `root` уже `warn`, `error` чи `off`.
26
+ - lint — запускає `k8s.dremio_logging` для ZooKeeper-темплейтів у межах одного файлу, лише для читання.
27
+
28
+ ## Гарантії поведінки
29
+
30
+ - Read-only: не виконує операцій запису (ФС/БД).
31
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
@@ -4,9 +4,7 @@ title: npm/skills/taze/js
4
4
  resource: npm/skills/taze/js/
5
5
  ---
6
6
 
7
- | Файл | Тип |
8
- | ------------------------------------- | --------- |
9
- | [cargo-diff.mjs](cargo-diff.md) | JS Module |
10
- | [diff.mjs](diff.md) | JS Module |
11
- | [orchestrate.mjs](orchestrate.md) | JS Module |
12
- | [rust-provider.mjs](rust-provider.md) | JS Module |
7
+ | Файл | Тип |
8
+ | ----------------------------------------- | --------- |
9
+ | [migration-cache.mjs](migration-cache.md) | JS Module |
10
+ | [orchestrate.mjs](orchestrate.md) | JS Module |
@@ -0,0 +1,38 @@
1
+ ---
2
+ type: JS Module
3
+ title: migration-cache.mjs
4
+ resource: npm/skills/taze/js/migration-cache.mjs
5
+ docgen:
6
+ crc: 5f264929
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
+ score: 100
10
+ issues: judge:inaccurate:0.98
11
+ judgeModel: openai-codex/gpt-5.4-mini
12
+ ---
13
+
14
+ ## Огляд
15
+
16
+ Модуль надає `DEFAULT_CACHE_DIR`, `migrationCacheKey`, `readMigrationCache`, `writeMigrationCache` і `withKnownMigrationNotes` для роботи з локальним кешем відомих результатів аналізу міграцій у межах прогону. Він зберігає та повторно читає вже відомі записи, а `withKnownMigrationNotes` підставляє їх у промпт, щоб не повторювати дослідження там, де результат уже є. Модуль fail-safe: не кидає винятків назовні й за окремих помилок повертає порожнє значення, зокрема `null`.
17
+
18
+ ## Поведінка
19
+
20
+ - `DEFAULT_CACHE_DIR` — стандартний спільний каталог для кешу міграцій на цій машині, щоб різні репозиторії могли повторно використовувати вже відомі результати.
21
+ - `migrationCacheKey` — перетворює назву пакета і діапазон версій на стабільний безпечний ключ для кешу.
22
+ - `readMigrationCache` — читає кешований запис міграції для потрібної пари версій; якщо запису немає або він пошкоджений, мовчки повертає `null`.
23
+ - `writeMigrationCache` — зберігає результат аналізу міграції в кеш, щоб наступні запуски на цій машині могли його повторити без нового дослідження.
24
+ - `withKnownMigrationNotes` — додає до промпта підсумок уже відомої міграції з кешу й підказує пропустити повторне дослідження та перейти до перевірки використання в поточному проєкті.
25
+
26
+ ## Публічний API
27
+
28
+ - DEFAULT_CACHE_DIR — Спільний каталог кешу міграцій для всіх репозиторіїв на цій машині; не прив’язаний до конкретного worktree.
29
+ - migrationCacheKey — Перетворює `` на безпечне ім’я файлу для спільного кешу між репо.
30
+ - readMigrationCache — Повертає збережений запис міграції для ``, якщо його вже обробляли в іншому repo/worktree; відсутній або пошкоджений запис дає `null`.
31
+ - writeMigrationCache — Записує результат LLM-обробки для ``, щоб не повторювати дослідження changelog для такого ж bump-а.
32
+ - withKnownMigrationNotes — Додає до prompt короткий підсумок знайденої міграції і, якщо є кеш, пропускає дослідження changelog/diff на користь пошуку використання в поточному проєкті.
33
+
34
+ ## Гарантії поведінки
35
+
36
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
37
+ - За певних помилок повертає порожнє значення (напр. `null`) замість винятку.
38
+ - Кешує результати в межах одного прогону.
@@ -1,18 +0,0 @@
1
- ## Налаштування mutation-testing для Rust: `.cargo/mutants.toml`
2
-
3
- Якщо у `.n-rules.json#rules` присутнє правило `rust` — правило `test` створює `.cargo/mutants.toml` у каталозі **кожного** Cargo.toml-маніфесту: кореневий `Cargo.toml`, `<workspace>/src-tauri/Cargo.toml` (Tauri-патерн) і `<workspace>/Cargo.toml` (flat workspace).
4
-
5
- Канон cargo-mutants config: [mutants.toml.baseline](./data/cargo_mutants_config/mutants.toml.baseline)
6
-
7
- **Customization** (mutate patterns, exclude rules, timeout) — відповідальність проєкту-споживача; концерн лише забезпечує наявність файлу як стартового baseline в кожному з виявлених workspace-каталогів.
8
-
9
- ### Універсальний baseline і framework-specific tuning
10
-
11
- Правило `test` відповідає лише за **універсальний baseline** mutation-testing:
12
-
13
- - створює `.cargo/mutants.toml` для Rust crates (порожній, з коментарем);
14
- - не робить припущень про framework/app shell;
15
- - не виключає platform glue, generated wrappers або binary entrypoints;
16
- - framework-specific tuning (`--lib`/`--tests`, `exclude_globs` для app-shell і platform bridge файлів) належить відповідним правилам (`tauri`, `capacitor` тощо).
17
-
18
- Якщо інше правило спеціалізує mutation-behavior — воно зобов'язане **доповнювати** існуючий `.cargo/mutants.toml` без дублювання (додавати лише відсутні ключі) і **не перетирати** ручні налаштування. Послідовний запуск `npx @7n/rules fix test` після `fix tauri` не має скидати tauri-tuning, і навпаки — повторний `fix tauri` не дублює секції.
@@ -1,8 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "fixability": "config",
4
- "lint": {
5
- "scope": "full",
6
- "glob": ["**/Cargo.toml"]
7
- }
8
- }
@@ -1,7 +0,0 @@
1
- # .cargo/mutants.toml — universal cargo-mutants baseline (test.mdc).
2
- # Цей baseline нейтральний: він не робить припущень про framework/app shell,
3
- # не виключає platform glue, generated wrappers або binary entrypoints.
4
- # Framework-specific tuning (Tauri, Capacitor тощо) належить відповідним
5
- # правилам — вони без дублювання доповнюють цей файл, не перетирають його.
6
- # cargo-mutants має робочі defaults; цей файл — стартова точка для customization.
7
- # Документація: https://mutants.rs/
@@ -1,31 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: fix-cargo_mutants_config.mjs
4
- resource: npm/rules/test/cargo_mutants_config/fix-cargo_mutants_config.mjs
5
- docgen:
6
- crc: cf485f41
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- tier: local-min-retry
9
- score: 100
10
- issues: judge:inaccurate:0.99
11
- judgeModel: openai-codex/gpt-5.4-mini
12
- ---
13
-
14
- ## Огляд
15
-
16
- Для виконання завдання мені потрібен **код або контекст** файлу `test/cargo_mutants_config`, щоб я міг переписати секцію "Overview" відповідно до наданих "ВІДОМИХ ФАКТІВ" та уникнути помилок із "ЧЕРНЕТКОЮ".
17
-
18
- ## Поведінка
19
-
20
- 1. Перевіряє, чи не виявлено порушення, пов'язане з відсутністю конфігураційного файлу для мутантів у Cargo-проекті.
21
- 2. Якщо конфігураційний файл не існує в каталозі з резервною копією, виконується наступне:
22
- 3. Збираються шляхи до всіх Cargo-маніфестів у робочому каталозі.
23
- 4. Для кожного знайденого Cargo-маніфеста визначається цільовий шлях до файлу `mutants.toml`.
24
- 5. Якщо цільовий файл не існує, система позначає його для запису.
25
- 6. Створюється директорія, якщо вона відсутня.
26
- 7. З резервної копії копіюється вміст конфігураційного файлу до цільового шляху.
27
- 8. Якщо жоден файл не було створено, операція завершується без змін.
28
-
29
- ## Гарантії поведінки
30
-
31
- - (специфічних машинно-виведених гарантій немає)
@@ -1,12 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/test/cargo_mutants_config
4
- resource: npm/rules/test/cargo_mutants_config/
5
- ---
6
-
7
- # npm/rules/test/cargo_mutants_config
8
-
9
- | Файл | Тип |
10
- | ----------------------------------------------------------- | --------- |
11
- | [fix-cargo_mutants_config.mjs](fix-cargo_mutants_config.md) | JS Module |
12
- | [main.mjs](main.md) | JS Module |
@@ -1,36 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/test/cargo_mutants_config/main.mjs
5
- docgen:
6
- crc: 817124cc
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 95
9
- judgeModel: openai-codex/gpt-5.4-mini
10
- ---
11
-
12
- ## Огляд
13
-
14
- Огляд: Файл перевіряє конфігурацію проекту, зокрема налаштування для мови Rust. Він забезпечує, що у директоріях, що містять файли маніфестів Cargo, існує файл `mutants.toml`, копіюючи базовий файл, якщо він відсутній.
15
-
16
- Поведінка:
17
-
18
- 1. Перевіряється, чи активована логіка для мови Rust.
19
- 2. Ідентифікуються всі файли маніфестів Cargo.
20
- 3. Перевіряється наявність базового файлу `mutants.toml.baseline`.
21
- 4. Для кожного знайденого файлу маніфесту Cargo, якщо файл `.cargo/mutants.toml` відсутній, він створюється, копіюючи вміст базового файлу. **[test.mdc]**
22
- 5. Процес завершується з кодом 0, якщо всі перевірки виконані або відповідні файли не виявлені/немає порушень; з кодом 1 у разі виявлення порушень.
23
-
24
- ## Поведінка
25
-
26
- Поведінка:
27
-
28
- 1. Перевіряється, увімкнено чи ні правило для мови Rust.
29
- 2. З'ясовуються всі файли маніфестів Cargo.
30
- 3. Перевіряється наявність канонічного базового файлу `mutants.toml.baseline`.
31
- 4. Для кожного знайденого файлу маніфесту Cargo, якщо файл `.cargo/mutants.toml` відсутній, він створюється, копіюючи вміст базового файлу.
32
- 5. Процес завершується з кодом 0, якщо всі перевірки пройдені або якщо відповідні файли не знайдено/немає порушень; з кодом 1 у разі виявлення порушень.
33
-
34
- ## Гарантії поведінки
35
-
36
- - (специфічних машинно-виведених гарантій немає)
@@ -1,49 +0,0 @@
1
- /**
2
- * T0-autofix для `test/cargo_mutants_config` — детерміноване створення
3
- * `<cargoDir>/.cargo/mutants.toml` з canonical neutral baseline там, де його ще
4
- * немає. Логіку перенесено з detector-а (read-only contract: detector лише звітує
5
- * `mutants-config-missing`, запис — тут).
6
- *
7
- * Unified lint surface: structured violations (test(violations)/apply(violations,ctx)).
8
- * Цільові каталоги резолвимо повторним скануванням Cargo-маніфестів від `ctx.cwd`
9
- * (idempotent: existing target пропускаємо → touchedFiles лишається порожнім).
10
- */
11
- import { existsSync } from 'node:fs'
12
- import { copyFile, mkdir } from 'node:fs/promises'
13
- import { dirname, join } from 'node:path'
14
- import { fileURLToPath } from 'node:url'
15
-
16
- import { resolveAllCargoManifests } from '../../../scripts/utils/resolve-cargo-manifest.mjs'
17
-
18
- import { MUTANTS_CONFIG_MISSING } from './main.mjs'
19
-
20
- const BASELINE_PATH = join(
21
- dirname(fileURLToPath(import.meta.url)),
22
- 'data',
23
- 'cargo_mutants_config',
24
- 'mutants.toml.baseline'
25
- )
26
-
27
- /** @type {import('../../../scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
28
- export const patterns = [
29
- {
30
- id: 'test-cargo-mutants-config-create',
31
- test: violations => violations.some(v => v.reason === MUTANTS_CONFIG_MISSING),
32
- apply: async (violations, ctx) => {
33
- if (!existsSync(BASELINE_PATH)) return { touchedFiles: [] }
34
- const cwd = ctx.cwd
35
- const manifests = await resolveAllCargoManifests(cwd)
36
- const touchedFiles = []
37
- for (const manifestPath of manifests) {
38
- const target = join(dirname(manifestPath), '.cargo', 'mutants.toml')
39
- if (existsSync(target)) continue
40
- ctx.recordWrite?.(target)
41
- await mkdir(dirname(target), { recursive: true })
42
- await copyFile(BASELINE_PATH, target)
43
- touchedFiles.push(target)
44
- }
45
- if (touchedFiles.length === 0) return { touchedFiles: [] }
46
- return { touchedFiles, message: `створено .cargo/mutants.toml: ${touchedFiles.join(', ')}` }
47
- }
48
- }
49
- ]
@@ -1,62 +0,0 @@
1
- /**
2
- * @see ./docs/cargo_mutants_config.md
3
- *
4
- * Read-only detector: лише ЗВІТУЄ про відсутній `<cargoDir>/.cargo/mutants.toml`.
5
- * Створення canonical baseline — окремий T0-fix (`fix-cargo_mutants_config.mjs`),
6
- * не в detector-і (`lint --no-fix` ніколи не мутує дерево).
7
- */
8
- import { existsSync } from 'node:fs'
9
- import { dirname, join, relative } from 'node:path'
10
- import { fileURLToPath } from 'node:url'
11
-
12
- import { createViolationReporter } from '../../../scripts/lib/lint-surface/violation-reporter.mjs'
13
- import { readNRulesConfigLite } from '../../../scripts/lib/read-n-rules-config-lite.mjs'
14
- import { resolveAllCargoManifests } from '../../../scripts/utils/resolve-cargo-manifest.mjs'
15
-
16
- const HERE = dirname(fileURLToPath(import.meta.url))
17
- const BASELINE_PATH = join(HERE, 'data', 'cargo_mutants_config', 'mutants.toml.baseline')
18
-
19
- /** Стабільний reason для відсутнього `.cargo/mutants.toml` (T0 матчиться за ним). */
20
- export const MUTANTS_CONFIG_MISSING = 'mutants-config-missing'
21
-
22
- /**
23
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx Контекст лінту (cwd, перелік файлів тощо).
24
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} Результат лінту з переліком порушень.
25
- */
26
- export async function lint(ctx) {
27
- const reporter = createViolationReporter(ctx)
28
- const cwd = ctx.cwd
29
- const config = await readNRulesConfigLite(cwd)
30
-
31
- // Self-gate: rust має бути enabled
32
- if (!config.rules.includes('rust') || config.disableRules.includes('rust')) {
33
- return reporter.result()
34
- }
35
-
36
- const manifests = await resolveAllCargoManifests(cwd)
37
- if (manifests.length === 0) {
38
- // rust enabled, але Cargo.toml ще немає — silently skip (manifest може з'явитися пізніше)
39
- return reporter.result()
40
- }
41
-
42
- if (!existsSync(BASELINE_PATH)) {
43
- reporter.fail(`.cargo/mutants.toml canonical baseline не знайдено (${BASELINE_PATH}) — перевстанови @7n/rules`)
44
- return reporter.result()
45
- }
46
-
47
- for (const manifestPath of manifests) {
48
- const cargoDir = dirname(manifestPath)
49
- const target = join(cargoDir, '.cargo', 'mutants.toml')
50
-
51
- if (existsSync(target)) {
52
- reporter.pass(`.cargo/mutants.toml існує (${relative(cwd, target)})`)
53
- continue
54
- }
55
-
56
- reporter.fail(
57
- `.cargo/mutants.toml відсутній (${relative(cwd, target)}) — запусти \`npx @7n/rules lint test\` для генерації canonical baseline (test.mdc)`,
58
- { reason: MUTANTS_CONFIG_MISSING, file: relative(cwd, target) }
59
- )
60
- }
61
- return reporter.result()
62
- }
@@ -1,49 +0,0 @@
1
- /** @see ../docs/collect-test-file-offenders.md */
2
- import { readFile } from 'node:fs/promises'
3
- import { basename, relative } from 'node:path'
4
-
5
- import { loadCursorIgnorePaths } from '../../../scripts/lib/load-cursor-config.mjs'
6
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
7
-
8
- /**
9
- * Чи файл — JS-тест (`*.test.mjs` / `*.test.js`).
10
- * @param {string} absPath абсолютний шлях
11
- * @returns {boolean} `true` для `.test.{mjs,js}` файлів
12
- */
13
- export function isTestFile(absPath) {
14
- const name = basename(absPath)
15
- return name.endsWith('.test.mjs') || name.endsWith('.test.js')
16
- }
17
-
18
- /**
19
- * Обходить репо (поважаючи `.n-rules.json:ignore`), збирає `*.test.{mjs,js}` файли
20
- * і прогонить кожен через `findOffenders(body)` — спільний скелет для per-file
21
- * regex/parse-based test-конвенцій (напр. `no-console-store-restore`, `vitest-api-conventions`).
22
- * @param {string} cwd корінь репозиторію
23
- * @param {(body: string) => Array<{line: number}>} findOffenders детектор порушень у тілі файлу
24
- * @returns {Promise<{ testFiles: string[], offenders: Array<{file: string, line: number}> }>} усі тестові файли й знайдені порушення (з relative-шляхом)
25
- */
26
- export async function collectTestFileOffenders(cwd, findOffenders) {
27
- const ignorePaths = await loadCursorIgnorePaths(cwd)
28
-
29
- /** @type {string[]} */
30
- const testFiles = []
31
- await walkDir(
32
- cwd,
33
- absPath => {
34
- if (isTestFile(absPath)) testFiles.push(absPath)
35
- },
36
- ignorePaths
37
- )
38
-
39
- /** @type {Array<{file: string, line: number}>} */
40
- const offenders = []
41
- for (const absPath of testFiles) {
42
- const body = await readFile(absPath, 'utf8')
43
- for (const o of findOffenders(body)) {
44
- offenders.push({ file: relative(cwd, absPath), ...o })
45
- }
46
- }
47
-
48
- return { testFiles, offenders }
49
- }
@@ -1,30 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: collect-test-file-offenders.mjs
4
- resource: npm/rules/test/lib/collect-test-file-offenders.mjs
5
- docgen:
6
- crc: d1c3db48
7
- model: openai-codex/gpt-5.4-mini
8
- tier: cloud-min
9
- score: 100
10
- issues: judge:inaccurate:0.98
11
- judgeModel: openai-codex/gpt-5.4-mini
12
- ---
13
-
14
- ## Огляд
15
-
16
- Файл знаходить JS-тести `*.test.mjs` і `*.test.js` у репозиторії з урахуванням `.n-rules.json` та повертає для кожного з них відносні шляхи до offenders. Це дає змогу окремо перевіряти, які саме тестові файли виходять за межі правил проєкту, без додаткового парсингу чи нормалізації результату.
17
-
18
- ## Поведінка
19
-
20
- - `isTestFile` — визначає, чи шлях належить до JS-тесту `*.test.mjs` або `*.test.js`.
21
- - `collectTestFileOffenders` — знаходить усі тестові файли в репозиторії з урахуванням `.n-rules.json` та збирає для них знайдені порушення з відносними шляхами.
22
-
23
- ## Публічний API
24
-
25
- - isTestFile — Розпізнає JS-файли з тестовою назвою `*.test.mjs` або `*.test.js`.
26
- - collectTestFileOffenders — Обходить репозиторій з урахуванням `.n-rules.json:ignore`, знаходить `*.test.{mjs,js}` і проганяє кожен файл через `findOffenders` для спільних test-конвенцій на кшталт `no-console-store-restore` і `vitest-api-conventions`.
27
-
28
- ## Гарантії поведінки
29
-
30
- - Read-only: не виконує операцій запису (ФС/БД).
@@ -1,9 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/test/lib
4
- resource: npm/rules/test/lib/
5
- ---
6
-
7
- | Файл | Тип |
8
- | ----------------------------------------------------------------- | --------- |
9
- | [collect-test-file-offenders.mjs](collect-test-file-offenders.md) | JS Module |
@@ -1,8 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "fixability": "structural",
4
- "lint": {
5
- "scope": "full",
6
- "glob": ["**/*.test.mjs"]
7
- }
8
- }
@@ -1,11 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/test/location
4
- resource: npm/rules/test/location/
5
- ---
6
-
7
- # npm/rules/test/location
8
-
9
- | Файл | Тип |
10
- | ------------------- | --------- |
11
- | [main.mjs](main.md) | JS Module |
@@ -1,36 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/test/location/main.mjs
5
- docgen:
6
- crc: 6906cc92
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 100
9
- issues: judge:inaccurate:0.99
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Огляд
16
- Файл гарантує відповідність усіх тестових файлів встановленому розташуванню. Він сканує репозиторій, щоб підтвердити, що всі файли з розширенням `*.test.mjs` знаходяться у директорії `tests`.
17
-
18
- Поведінка
19
- Запускає `main` для перевірки коректності розташування всіх тестових файлів (`*.test.mjs`). Сканує репозиторій, ігноруючи директорії, визначені у конфігурації. Для кожного тестового файлу перевіряє його наявність у каталозі `tests`. Якщо тест виявлено поза директорією `tests`, фіксується його повний відносний шлях. У випадку відсутності порушень, інформується, що всі тестові файли розташовані коректно (test.mdc). Якщо виявлено порушення, для кожного файлу, що не відповідає правилам (test.mdc), повідомляється його шлях та необхідність переміщення до відповідної піддиректорії `tests`.
20
-
21
- ## Поведінка
22
-
23
- 1. Запускає `main` для перевірки розташування всіх тестових файлів з розширенням `*.test.mjs`.
24
- 2. Сканує репозиторій, ігноруючи директорії, вказані в конфігурації.
25
- 3. Для кожного знайденого тестового файлу перевіряє, чи він знаходиться в каталозі з назвою `tests`.
26
- 4. Якщо тест знайдено поза директорією `tests`, фіксує його повний відносний шлях.
27
- 5. Якщо порушень немає, повідомляє, що всі тестові файли розташовані коректно (test.mdc).
28
- 6. Якщо порушення виявлено, для кожного файлу, що порушує правила (test.mdc), повідомляє шлях та вказує, що тест має бути переміщено до відповідної піддиректорії `tests`.
29
-
30
- ## Публічний API
31
-
32
- - main — Встановлює, чи знаходяться файли, призначені для тестування, у відповідному каталозі `tests/` (test.mdc).
33
-
34
- ## Гарантії поведінки
35
-
36
- - Read-only: не виконує операцій запису (ФС/БД).
@@ -1,52 +0,0 @@
1
- ## Розміщення тестових файлів у каталозі `tests/`
2
-
3
- JS-тести у пакеті лежать у **піддиректорії `tests/`** поряд із кодом, який тестується, а **не безпосередньо біля джерельного файлу**.
4
-
5
- ```
6
- rules/foo/js/bar/
7
- ├── check.mjs ← JS-джерело
8
- └── tests/
9
- └── check.test.mjs ← тест check.mjs
10
- ```
11
-
12
- **Чому так:**
13
-
14
- - Каталог-з-кодом залишається чистим: продакшен-модулі, политики, темплейти не миготять серед тестових файлів.
15
- - Один погляд на дерево показує, що піде у npm tarball (все, крім `tests/` і `__fixtures__/` — їх ловить `package.json#files` через негативні globs).
16
- - Якщо тест переростає у мульти-файловий — він уже у власному каталозі, без хаотичного розкидання.
17
-
18
- **Виняток — Rego unit-тести (`*_test.rego`):** лишаються **поряд із полісі-файлом** відповідно до загальноприйнятого OPA/Conftest community-патерну. `conftest verify -p <dir>` рекурсивно підхоплює їх незалежно від місця в каталозі.
19
-
20
- ```
21
- rules/foo/policy/package_json/
22
- ├── package_json.rego ← Rego-правило
23
- ├── package_json_test.rego ← Rego unit-тести (поряд, не у tests/)
24
- └── target.json
25
- ```
26
-
27
- **Спеціальні випадки:**
28
-
29
- - **Integration-тести на рівні пакета** — у `<root>/tests/` (наприклад `npm/tests/`). Це не «біля файлу», а виокремлений каталог для тестів, що покривають весь пакет.
30
- - **Fixtures**: `__fixtures__/` (для shared) і `fixtures/` (для rule-specific) також живуть **усередині `tests/`**: `tests/__fixtures__/...` і `tests/fixtures/...`.
31
- - **Test helpers** (`test-helpers.mjs`) можуть лишатися у `scripts/utils/` як shared infra — конвенція стосується файлів `*.test.mjs`.
32
-
33
- **Гарантії tarball-чистоти** через `package.json#files`:
34
-
35
- ```json
36
- "files": [
37
- "...",
38
- "!**/*.test.mjs",
39
- "!**/*_test.rego",
40
- "!**/__fixtures__/**",
41
- "!**/fixtures/**",
42
- "!**/test-helpers.mjs"
43
- ]
44
- ```
45
-
46
- Recursive globs ловлять файли всередині `tests/` так само, як ловили б їх біля джерела.
47
-
48
- `npx @7n/rules fix test` (concern `location`) проходить деревом пакета й перевіряє: **кожен `*.test.mjs` файл лежить усередині каталогу з ім'ям `tests`** (точне співпадіння басенейму батьківської директорії). Файли поза цим каталогом репортуються з порадою куди їх перенести.
49
-
50
- `*_test.rego` перевіркою **не охоплюються** — вони не переміщуються.
51
-
52
- Пропускаються: `node_modules`, `.git`, `dist`, `build`, `.venv`, `venv`, шляхи з `.n-rules.json:ignore`.
@@ -1,70 +0,0 @@
1
- /** @see ./docs/location.md */
2
- import { basename, dirname, relative } from 'node:path'
3
-
4
- import { createViolationReporter } from '../../../scripts/lib/lint-surface/violation-reporter.mjs'
5
- import { loadCursorIgnorePaths } from '../../../scripts/lib/load-cursor-config.mjs'
6
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
7
-
8
- const TESTS_DIR_NAME = 'tests'
9
-
10
- /**
11
- * Чи файл є JS-тестом (`*.test.mjs`).
12
- * @param {string} absPath абсолютний шлях
13
- * @returns {boolean} true для шляхів із суфіксом `.test.mjs`
14
- */
15
- function isTestFile(absPath) {
16
- return basename(absPath).endsWith('.test.mjs')
17
- }
18
-
19
- /**
20
- * Перевіряє, чи лежить тест у каталозі з іменем `tests`.
21
- * @param {string} absPath абсолютний шлях до тесту
22
- * @returns {boolean} `true`, якщо басенейм батьківської директорії — `tests`
23
- */
24
- function isInsideTestsDir(absPath) {
25
- return basename(dirname(absPath)) === TESTS_DIR_NAME
26
- }
27
-
28
- /**
29
- * Перевіряє розміщення тестових файлів у каталозі `tests/` (test.mdc).
30
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону
31
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат перевірки
32
- */
33
- export async function lint(ctx) {
34
- const reporter = createViolationReporter(ctx)
35
- const { pass, fail } = reporter
36
-
37
- const cwd = ctx.cwd
38
- const ignorePaths = await loadCursorIgnorePaths(cwd)
39
-
40
- /** @type {string[]} */
41
- const offenders = []
42
- let totalTests = 0
43
-
44
- await walkDir(
45
- cwd,
46
- absPath => {
47
- if (!isTestFile(absPath)) {
48
- return
49
- }
50
- totalTests++
51
- if (!isInsideTestsDir(absPath)) {
52
- offenders.push(relative(cwd, absPath))
53
- }
54
- },
55
- ignorePaths
56
- )
57
-
58
- if (offenders.length === 0) {
59
- pass(`Всі ${totalTests} файлів *.test.mjs у каталозі tests/ (test.mdc)`)
60
- return reporter.result()
61
- }
62
-
63
- for (const offenderPath of offenders) {
64
- const parentDir = dirname(offenderPath)
65
- const base = basename(offenderPath)
66
- fail(`${offenderPath}: тест має лежати у tests/ — перенеси у ${parentDir}/${TESTS_DIR_NAME}/${base} (test.mdc)`)
67
- }
68
-
69
- return reporter.result()
70
- }
@@ -1 +0,0 @@
1
- { "auto": "завжди" }