@nitra/cursor 5.3.4 → 5.4.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 (151) hide show
  1. package/.claude-template/settings.template.json +2 -2
  2. package/.pi-template/extensions/n-cursor-adr/docs/index.md +13 -24
  3. package/CHANGELOG.md +11 -0
  4. package/bin/n-cursor.js +43 -22
  5. package/lib/docs/models.md +29 -18
  6. package/lib/docs/omlx-trace.md +51 -0
  7. package/lib/docs/omlx.md +31 -15
  8. package/lib/omlx.mjs +2 -5
  9. package/package.json +1 -1
  10. package/rules/abie/docs/fix.md +17 -11
  11. package/rules/adr/docs/fix.md +25 -140
  12. package/rules/bun/docs/fix.md +18 -151
  13. package/rules/capacitor/docs/fix.md +16 -13
  14. package/rules/capacitor/js/docs/platforms.md +31 -43
  15. package/rules/changelog/docs/fix.md +25 -169
  16. package/rules/ci4/docs/fix.md +11 -14
  17. package/rules/doc-files/doc-files.mdc +60 -0
  18. package/rules/doc-files/docs/fix.md +31 -0
  19. package/rules/doc-files/fix.mjs +19 -0
  20. package/{skills → rules}/doc-files/js/docgen-extract.mjs +42 -19
  21. package/{skills → rules}/doc-files/js/docgen-ignore.mjs +2 -1
  22. package/{skills → rules}/doc-files/js/docgen-scan.mjs +9 -1
  23. package/{skills → rules}/doc-files/js/docs/docgen-crc.md +1 -1
  24. package/{skills → rules}/doc-files/js/docs/docgen-extract-anchors.md +1 -1
  25. package/{skills → rules}/doc-files/js/docs/docgen-extract.md +2 -2
  26. package/{skills → rules}/doc-files/js/docs/docgen-files-batch.md +1 -1
  27. package/{skills → rules}/doc-files/js/docs/docgen-gen.md +1 -1
  28. package/{skills → rules}/doc-files/js/docs/docgen-ignore.md +4 -4
  29. package/rules/doc-files/js/docs/docgen-prompts.md +39 -0
  30. package/rules/doc-files/js/docs/docgen-scan.md +54 -0
  31. package/rules/doc-files/js/docs/lint.md +36 -0
  32. package/rules/doc-files/js/docs/units-js.md +31 -0
  33. package/rules/doc-files/js/docs/units-rs.md +35 -0
  34. package/rules/doc-files/js/docs/units.md +30 -0
  35. package/rules/doc-files/js/lint.mjs +96 -0
  36. package/{skills → rules}/doc-files/js/units-rs.mjs +37 -17
  37. package/rules/doc-files/lint/docs/lint.md +37 -0
  38. package/rules/doc-files/lint/lint.mjs +105 -0
  39. package/rules/doc-files/meta.json +1 -0
  40. package/rules/docker/docs/fix.md +21 -161
  41. package/rules/efes/docs/fix.md +23 -194
  42. package/rules/feedback/docs/fix.md +10 -8
  43. package/rules/ga/docs/fix.md +10 -5
  44. package/rules/graphql/docs/fix.md +23 -119
  45. package/rules/hasura/docs/fix.md +19 -5
  46. package/rules/hasura/js/docs/internal_urls.md +34 -307
  47. package/rules/image-avif/docs/fix.md +16 -127
  48. package/rules/image-compress/docs/fix.md +20 -141
  49. package/rules/image-compress/js/docs/package_setup.md +22 -182
  50. package/rules/js-bun-db/docs/fix.md +23 -139
  51. package/rules/js-bun-db/js/docs/safety.md +33 -221
  52. package/rules/js-bun-redis/docs/fix.md +25 -114
  53. package/rules/js-bun-redis/js/docs/imports.md +18 -166
  54. package/rules/js-lint/docs/fix.md +30 -108
  55. package/rules/js-lint/js/docs/lint-findings.md +37 -17
  56. package/rules/js-lint/js/docs/lint.md +22 -238
  57. package/rules/js-lint/js/docs/tooling.md +34 -331
  58. package/rules/js-lint-ci/docs/fix.md +16 -149
  59. package/rules/js-lint-ci/js/docs/lint.md +16 -136
  60. package/rules/js-mssql/docs/fix.md +18 -123
  61. package/rules/js-mssql/js/docs/deps.md +28 -251
  62. package/rules/js-run/docs/fix.md +23 -138
  63. package/rules/js-run/js/docs/runtime.md +24 -378
  64. package/rules/k8s/docs/fix.md +18 -123
  65. package/rules/nginx-default-tpl/docs/fix.md +22 -118
  66. package/rules/nginx-default-tpl/js/docs/template.md +38 -360
  67. package/rules/npm-module/docs/fix.md +27 -89
  68. package/rules/npm-module/js/docs/header_doc_pointer.md +15 -15
  69. package/rules/npm-module/js/docs/package_structure.md +36 -258
  70. package/rules/npm-module/js/docs/rule_meta.md +25 -127
  71. package/rules/npm-module/js/docs/skill_meta.md +18 -180
  72. package/rules/php/docs/fix.md +21 -98
  73. package/rules/php/js/docs/tooling.md +20 -143
  74. package/rules/python/docs/fix.md +25 -157
  75. package/rules/python/js/docs/applies.md +20 -98
  76. package/rules/python/js/docs/tooling.md +27 -144
  77. package/rules/rego/docs/fix.md +24 -112
  78. package/rules/rego/js/docs/applies.md +20 -164
  79. package/rules/rego/js/docs/lint.md +15 -110
  80. package/rules/release/docs/fix.md +16 -114
  81. package/rules/rust/docs/fix.md +24 -119
  82. package/rules/rust/js/docs/applies.md +20 -129
  83. package/rules/security/docs/fix.md +21 -78
  84. package/rules/security/js/docs/sample_secret.md +23 -182
  85. package/rules/security/js/docs/trufflehog.md +19 -128
  86. package/rules/style-lint/docs/fix.md +16 -150
  87. package/rules/style-lint/js/docs/lint.md +21 -172
  88. package/rules/style-lint/js/docs/tooling.md +19 -184
  89. package/rules/tauri/docs/fix.md +26 -152
  90. package/rules/tauri/js/docs/cargo_mutants_config.md +21 -159
  91. package/rules/tauri/js/docs/tooling.md +20 -217
  92. package/rules/test/docs/fix.md +19 -127
  93. package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +15 -127
  94. package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +17 -153
  95. package/rules/test/js/docs/cargo_mutants_config.md +24 -164
  96. package/rules/test/js/docs/location.md +24 -126
  97. package/rules/test/js/docs/no-process-chdir.md +20 -151
  98. package/rules/test/js/docs/no-relative-fs-path.md +24 -261
  99. package/rules/test/js/docs/stryker_config.md +48 -148
  100. package/rules/test/js/docs/vitest-config-pool-forks.md +21 -164
  101. package/rules/text/docs/fix.md +25 -113
  102. package/rules/text/js/docs/forbidden-prettier.md +21 -132
  103. package/rules/text/js/docs/formatting.md +60 -251
  104. package/rules/text/js/docs/lint.md +17 -114
  105. package/rules/vue/docs/fix.md +25 -118
  106. package/rules/vue/js/docs/packages.md +25 -323
  107. package/rules/worktree/docs/fix.md +31 -150
  108. package/scripts/coverage-classify/docs/index.md +23 -209
  109. package/scripts/coverage-classify/docs/verdict-schema.md +14 -159
  110. package/scripts/dispatcher/docs/trace.md +35 -0
  111. package/scripts/docs/auto-rules.md +37 -361
  112. package/scripts/docs/lint-cli.md +12 -13
  113. package/scripts/docs/post-tool-use-fix.md +16 -15
  114. package/scripts/docs/skills-cli.md +26 -23
  115. package/scripts/docs/sync-claude-config.md +94 -34
  116. package/scripts/docs/worktree-cli.md +11 -34
  117. package/scripts/lib/docs/assert-project-root.md +14 -16
  118. package/scripts/lib/docs/changed-files.md +24 -139
  119. package/scripts/lib/docs/discover-check-rules-from-cursor.md +14 -146
  120. package/scripts/lib/docs/rule-predicates.md +20 -17
  121. package/scripts/lib/docs/run-rule-cli.md +14 -18
  122. package/scripts/lib/docs/run-rule.md +13 -20
  123. package/scripts/lib/docs/run-standard-rule.md +12 -15
  124. package/scripts/lib/docs/sync-gitignore-worktree.md +15 -18
  125. package/scripts/lib/rule-predicates.mjs +1 -1
  126. package/scripts/sync-claude-config.mjs +4 -1
  127. package/scripts/utils/docs/with-lock.md +19 -12
  128. package/scripts/utils/with-lock.mjs +4 -2
  129. package/skills/doc-aggregate/SKILL.md +2 -2
  130. package/skills/doc-aggregate/js/docgen-ignore.mjs +6 -6
  131. package/skills/doc-aggregate/js/docs/docgen-ignore.md +1 -1
  132. package/skills/doc-aggregate/js/docs/docgen-scan.md +78 -0
  133. package/skills/doc-files/.changes/260612-0031.md +5 -0
  134. package/skills/doc-files/.changes/260612-0036.md +5 -0
  135. package/skills/doc-files/.changes/260612-0114.md +5 -0
  136. package/skills/doc-files/SKILL.md +6 -6
  137. package/skills/fix/js/docs/llm-worker.md +17 -15
  138. package/skills/fix/js/docs/orchestrator.md +30 -23
  139. package/skills/fix/js/docs/t0.md +26 -16
  140. package/skills/start-check/js/docs/check.md +26 -22
  141. package/skills/taze/js/docs/diff.md +44 -20
  142. package/skills/doc-files/js/docs/docgen-prompts.md +0 -32
  143. package/skills/doc-files/js/docs/docgen-scan.md +0 -25
  144. package/skills/doc-files/js/docs/units-rs.md +0 -35
  145. /package/{skills → rules}/doc-files/js/docgen-crc.mjs +0 -0
  146. /package/{skills → rules}/doc-files/js/docgen-extract-anchors.mjs +0 -0
  147. /package/{skills → rules}/doc-files/js/docgen-files-batch.mjs +0 -0
  148. /package/{skills → rules}/doc-files/js/docgen-gen.mjs +0 -0
  149. /package/{skills → rules}/doc-files/js/docgen-prompts.mjs +0 -0
  150. /package/{skills → rules}/doc-files/js/units-js.mjs +0 -0
  151. /package/{skills → rules}/doc-files/js/units.mjs +0 -0
@@ -1,166 +1,30 @@
1
1
  ---
2
2
  docgen:
3
3
  source: npm/rules/test/js/data/stryker_config/stryker.config.vue.baseline.mjs
4
- crc: a1405dc2
4
+ crc: 579865c3
5
+ score: 95
5
6
  ---
6
7
 
7
8
  # stryker.config.vue.baseline.mjs
8
9
 
9
10
  ## Огляд
10
11
 
11
- Файл `stryker.config.vue.baseline.mjs` це **базова (еталонна) конфігурація Stryker** для мутаційного тестування Vue-проєктів, яка використовується як тестові дані (fixture) в наборі тестів правил `npm/rules/test/js/data/stryker_config/`. Розташований у директорії `data/stryker_config/` каталогу тестів пакета `npm/rules`, файл слугує канонічним зразком "як має виглядати правильно налаштований `stryker.config.mjs`" для проєкту з Vue Single-File Components.
12
+ Файл запускає тестування за допомогою фреймворку vitest. Використовує конфігурацію vitest з файлом mutation.json. Налаштовує аналіз покриття для запуску лише на мутовані лінії кожного тесту. Визначає директорію тимчасових файлів за допомогою tempDirName. Генерує звіти у форматах json та clear-text за допомогою reporters. Конфігурує jsonReporter для збереження результатів у файлі reports/stryker/mutation.json. Увімкнено incremental для збереження результатів між запусками та відновлення після збою. Використовує incrementalFile для збереження стану для інкрементального запуску. Ігнорує мутації Vue `<script setup>`-макросів за допомогою плагінів. Ігнорує Vue-макроси за допомогою плагінів.
12
13
 
13
- Файл є простим ES-модулем без логіки: він експортує об'єкт конфігурації за замовчуванням (`export default`). Цей об'єкт повністю описує параметри запуску Stryker mutator-а для Vue-стека (Vitest як test runner, кастомний ignorer для Vue-макросів, increment-кешування, JSON-репортер).
14
+ ## Поведінка
14
15
 
15
- Контекст використання:
16
+ 1. Запуск тестування з використанням фреймворку vitest.
17
+ 2. Використання конфігурації vitest з файлом vitest.config.mjs.
18
+ 3. Налаштування аналізу покриття для запуску лише на мутовані лінії кожного тесту.
19
+ 4. Використання назви tempDirName для визначення директорії тимчасових файлів.
20
+ 5. Використання reporters для генерації звітів у форматах json та clear-text.
21
+ 6. Налаштування jsonReporter для збереження результатів у файлі reports/stryker/mutation.json.
22
+ 7. Увімкнення incremental для збереження результатів між запусками та відновлення після збою.
23
+ 8. Використання incrementalFile для збереження стану для інкрементального запуску.
24
+ 9. Використання плагінів для ігнорування мутації Vue <script setup>-макросів.
25
+ 10. Використання плагінів для ігнорування Vue-макросів.
16
26
 
17
- - як **очікуваний baseline** (еталон) у тестах правил, що перевіряють або генерують `stryker.config.mjs` для Vue-проєктів;
18
- - як **довідковий шаблон** для команд `n-coverage` / `n-cursor coverage`, які запускають мутаційне тестування у Vue-воркспейсах;
19
- - як **документація-приклад** оптимальних налаштувань (perTest coverage, vitest-runner, incremental, local Vue-macros ignorer plugin).
27
+ ## Гарантії поведінки
20
28
 
21
- ## Експорти / API
22
-
23
- Файл має **єдиний експорт** — `default`.
24
-
25
- | Експорт | Тип | Опис |
26
- | --------- | --------------------------------------------------- | ------------------------------------------------------------------- |
27
- | `default` | `PartialStrykerOptions` (з `@stryker-mutator/core`) | Об'єкт конфігурації Stryker для Vue-проєкту з Vitest test runner-ом |
28
-
29
- JSDoc-анотація `/** @type {import('@stryker-mutator/core').PartialStrykerOptions} */` встановлює тип об'єкта згідно з офіційним TS-типом Stryker, що дає IDE/TS-серверу повну валідацію полів та автодоповнення.
30
-
31
- ### Структура експортованого об'єкта
32
-
33
- | Ключ | Значення | Призначення |
34
- | ----------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
35
- | `testRunner` | `'vitest'` | Обирає Vitest як тест-раннер для запуску мутантів |
36
- | `vitest.configFile` | `'vitest.config.js'` | Шлях до конфігурації Vitest, яку має підхопити vitest-runner |
37
- | `coverageAnalysis` | `'perTest'` | Аналіз покриття на рівні окремих тестів — для кожного мутанта запускаються лише ті тести, що покривають відповідний рядок коду |
38
- | `tempDirName` | `'reports/stryker/.tmp'` | Тимчасова директорія Stryker (зберігається всередині `reports/`, а не в корені) |
39
- | `reporters` | `['json', 'clear-text']` | Активні репортери: машинно-читабельний JSON + текстовий вивід у термінал |
40
- | `jsonReporter.fileName` | `'reports/stryker/mutation.json'` | Куди писати JSON-звіт мутацій |
41
- | `incremental` | `true` | Вмикає інкрементальний режим: зберігає попередні результати між запусками |
42
- | `incrementalFile` | `'reports/stryker/incremental.json'` | Файл-кеш для incremental-режиму |
43
- | `plugins` | `['@stryker-mutator/vitest-runner', './stryker-vue-macros-ignorer.mjs']` | Підключені Stryker-плагіни: офіційний vitest-runner і локальний ignorer для Vue compiler-macros |
44
- | `ignorers` | `['vue-macros']` | Активні ignorer-плагіни — ім'я `vue-macros` походить з локального плагіна `./stryker-vue-macros-ignorer.mjs` |
45
-
46
- ## Функції
47
-
48
- Файл **не містить функцій** — це чисто декларативний конфіг-модуль, що експортує статичний об'єкт. Жодних викликів, фабрик, factory-функцій чи hook-ів немає.
49
-
50
- ### Side effects
51
-
52
- Side effects на рівні модуля **відсутні**:
53
-
54
- - немає `import`-ів (окрім JSDoc type-import у коментарі, який не виконується);
55
- - немає викликів функцій верхнього рівня;
56
- - немає мутацій глобального стану;
57
- - немає I/O.
58
-
59
- Файл при `import`-уванні просто повертає літерал об'єкта.
60
-
61
- ## Залежності
62
-
63
- ### Прямі імпорти
64
-
65
- **Жодних `import`-операторів немає.** Файл самодостатній на рівні JS-завантаження.
66
-
67
- ### Тип-залежності (лише через JSDoc)
68
-
69
- | Пакет | Призначення | Спосіб використання |
70
- | ----------------------- | ---------------------------------------------------------- | ----------------------------------------------------------- |
71
- | `@stryker-mutator/core` | Базовий тип `PartialStrykerOptions` для типізації експорту | Через JSDoc `@type {import('...')}` — не впливає на рантайм |
72
-
73
- ### Імпліцитні runtime-залежності (за іменами рядків)
74
-
75
- Конфіг **посилається на зовнішні модулі та файли через рядкові ідентифікатори**, які підвантажує сам Stryker під час виконання:
76
-
77
- | Залежність | Тип | Опис |
78
- | -------------------------------------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
79
- | `'vitest'` (значення `testRunner`) | npm-плагін Stryker | Ім'я раннера — Stryker шукає `@stryker-mutator/vitest-runner` у `node_modules` |
80
- | `'@stryker-mutator/vitest-runner'` (елемент `plugins`) | npm-пакет | Власне реалізація vitest-runner, мусить бути встановленою як devDependency |
81
- | `'./stryker-vue-macros-ignorer.mjs'` (елемент `plugins`) | локальний модуль | Кастомний Stryker-плагін у тій самій директорії, що пропускає мутацію Vue compiler-macros (`defineProps`, `defineEmits`, `defineModel`, `defineSlots`, `defineExpose`, `defineOptions`) |
82
- | `'vitest.config.js'` (значення `vitest.configFile`) | файл воркспейсу | Конфігурація Vitest у корені тестованого Vue-воркспейсу |
83
- | `'vue-macros'` (елемент `ignorers`) | ім'я ignorer-а | Внутрішнє ім'я ignorer-а, яке експортує `./stryker-vue-macros-ignorer.mjs` |
84
-
85
- ## Потік виконання / Використання
86
-
87
- ### Як файл використовується
88
-
89
- 1. **Як test-fixture (eталон)** — тестовий код у `npm/rules/test/js/` читає цей файл як еталонний baseline і порівнює з реальним `stryker.config.mjs` у проєктах, що перевіряються правилом.
90
- 2. **Як шаблон для генератора** — правило, що автоматично створює/нормалізує `stryker.config.mjs` для Vue-воркспейсів, може використовувати цей файл як вихідну форму.
91
- 3. **Як приклад у документації** — для розробників, що налаштовують мутаційне тестування Vue вручну.
92
-
93
- ### Як цей конфіг виконує Stryker (якщо запустити проти Vue-воркспейсу)
94
-
95
- При виклику `bunx stryker run` (чи через `n-cursor coverage`) Stryker:
96
-
97
- 1. читає експортований об'єкт як `PartialStrykerOptions`;
98
- 2. завантажує плагіни зі списку `plugins`:
99
- - офіційний `@stryker-mutator/vitest-runner` — для запуску мутантів через Vitest;
100
- - локальний `./stryker-vue-macros-ignorer.mjs` — реєструє ignorer з іменем `'vue-macros'`;
101
- 3. активує ignorer-и зі списку `ignorers` — у цьому випадку `'vue-macros'` пропускає мутацію аргументів `defineProps` / `defineEmits` / `defineModel` / `defineSlots` / `defineExpose` / `defineOptions`, оскільки інакше Stryker огортав би їх у coverage-тернарник, який `@vue/compiler-sfc` не зміг би статично проаналізувати, і компіляція SFC падала б;
102
- 4. встановлює `testRunner: 'vitest'` і передає йому `vitest.configFile`;
103
- 5. виконує **perTest coverage analysis** — заздалегідь запускає тести один раз, фіксує мапу "який тест покриває який рядок", і потім для кожного мутанта виконує лише релевантний підмножину тестів (значно швидше за `command` runner, де довелось би ганяти весь test-suite на кожен мутант);
104
- 6. використовує `reports/stryker/.tmp` як тимчасову директорію (всередині `reports/`, щоб не засмічувати корінь);
105
- 7. зберігає звіт у `reports/stryker/mutation.json` через `json`-репортер, паралельно друкує `clear-text` у термінал;
106
- 8. при `incremental: true` після першого прогону зберігає стан у `reports/stryker/incremental.json`; наступні запуски (особливо noop-прогони, коли код не змінився) виконуються в ~262× швидше (за результатами `benchmarks/runner-comparison/SPIKE.md`, на який посилається коментар у файлі).
107
-
108
- ### Архітектурні рішення (з коментарів у файлі)
109
-
110
- - **`coverageAnalysis: 'perTest'`** — головний приріст швидкості проти `command` runner-а, де довелось би запускати весь test-suite на кожен мутант.
111
- - **Відсутність `inPlace`** — vitest-runner ізолює мутантів у пам'яті через AST-patching, без копіювання `node_modules` у sandbox (стара проблема command runner у Bun monorepo).
112
- - **`concurrency` не задано** — Stryker за замовчуванням обирає `os.cpus().length - 1`, що оптимально для більшості машин.
113
- - **Локальний `vue-macros` ignorer** — обов'язковий для Vue-проєктів, інакше Stryker зламає компіляцію SFC при мутації compiler-macros у блоках `<script setup>`.
114
-
115
- ### Типовий life-cycle конфіга
116
-
117
- ```text
118
- import default з stryker.config.vue.baseline.mjs
119
- |
120
- v
121
- PartialStrykerOptions → передається в @stryker-mutator/core
122
- |
123
- v
124
- плагіни підвантажуються: vitest-runner + локальний ignorer
125
- |
126
- v
127
- testRunner='vitest' стартує з vitest.config.js
128
- |
129
- v
130
- perTest coverage map будується
131
- |
132
- v
133
- для кожного мутанта запускається підмножина тестів,
134
- ignorer 'vue-macros' пропускає Vue compiler-macros
135
- |
136
- v
137
- звіт → reports/stryker/mutation.json (+ clear-text у термінал)
138
- |
139
- v
140
- incremental.json зберігає стан для наступного запуску
141
- ```
142
-
143
- ## Rebuild Test
144
-
145
- Перевірка, що документація відображає реальний вміст файлу:
146
-
147
- 1. **Експорт**: файл містить **рівно один** `export default` зі статичним об'єктом — підтверджено.
148
- 2. **Ключі об'єкта**: рівно 10 ключів верхнього рівня: `testRunner`, `vitest`, `coverageAnalysis`, `tempDirName`, `reporters`, `jsonReporter`, `incremental`, `incrementalFile`, `plugins`, `ignorers` — підтверджено.
149
- 3. **Значення**:
150
- - `testRunner === 'vitest'`
151
- - `vitest.configFile === 'vitest.config.js'`
152
- - `coverageAnalysis === 'perTest'`
153
- - `tempDirName === 'reports/stryker/.tmp'`
154
- - `reporters` — масив з двох рядків `['json', 'clear-text']`
155
- - `jsonReporter.fileName === 'reports/stryker/mutation.json'`
156
- - `incremental === true`
157
- - `incrementalFile === 'reports/stryker/incremental.json'`
158
- - `plugins` — масив з двох рядків: `'@stryker-mutator/vitest-runner'` та `'./stryker-vue-macros-ignorer.mjs'`
159
- - `ignorers` — масив з одного рядка `['vue-macros']`
160
- 4. **JSDoc-тип**: `/** @type {import('@stryker-mutator/core').PartialStrykerOptions} */` присутній над `export default` — підтверджено.
161
- 5. **Імпорти**: жодного `import`-оператора немає — підтверджено.
162
- 6. **Функції**: жодних оголошень функцій (ні `function`, ні стрілкових) — підтверджено.
163
- 7. **Side effects на рівні модуля**: відсутні — підтверджено.
164
- 8. **Коментарі**: усі ключові рішення (`perTest`, відсутність `inPlace`, `incremental` із посиланням на `benchmarks/runner-comparison/SPIKE.md`, призначення локального `vue-macros` ignorer-а) задокументовані inline-коментарями у вихідному файлі — відображено в розділах "Архітектурні рішення" та "Залежності".
165
-
166
- Документація сумісна з вмістом файла і не містить вигаданих фактів.
29
+ - Read-only: файл не виконує операцій запису у файлову систему.
30
+ - Не звертається до мережі.
@@ -1,173 +1,33 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/test/js/cargo_mutants_config.mjs
4
+ crc: 4078e955
5
+ score: 100
6
+ ---
7
+
1
8
  # cargo_mutants_config.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Файл реалізує концерн `cargo_mutants_config` правила `test` (відповідає правилу
6
- `test.mdc`) для пакета `@nitra/cursor`. Призначення концерну — забезпечити, що
7
- у кожному Cargo-крейті проєкту присутній файл `.cargo/mutants.toml` із
8
- канонічним baseline-вмістом, який потрібен інструменту
9
- [`cargo-mutants`](https://mutants.rs/) для запуску мутаційного тестування Rust.
10
-
11
- Логіка self-gating: концерн виконується тільки якщо в `.n-cursor.json` правило
12
- `rust` присутнє у списку `rules` і не присутнє у списку `disable-rules`. Якщо
13
- правило `rust` вимкнене — функція мовчки повертає успіх. Якщо правило
14
- ввімкнене, але в проєкті ще немає жодного `Cargo.toml` (наприклад, манифест
15
- з'явиться пізніше) — функція теж мовчки повертає успіх, не вважаючи це
16
- порушенням.
17
-
18
- У разі, якщо canonical baseline-файл `data/cargo_mutants_config/mutants.toml.baseline`
19
- відсутній у дистрибутиві `@nitra/cursor` (наприклад, через зламану інсталяцію),
20
- концерн фейлить із вказівкою перевстановити пакет.
21
-
22
- Для кожного знайденого `Cargo.toml` (cwd, всі workspace-члени, включно з
23
- Tauri-патерном `src-tauri/Cargo.toml`) концерн перевіряє наявність файлу
24
- `.cargo/mutants.toml` у відповідному каталозі манифеста. Якщо файл існує —
25
- позначає його як pass і йде далі. Якщо не існує — створює каталог `.cargo/`
26
- (`recursive: true`) та копіює canonical baseline у `.cargo/mutants.toml`.
27
-
28
- Baseline-файл — порожній з коментарем; у `cargo-mutants` працюють робочі
29
- defaults, тож фактичні налаштування не потрібні.
30
-
31
- ## Експорти / API
32
-
33
- | Експорт | Тип | Опис |
34
- | ------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------ |
35
- | `check` | `async function(cwd?: string): Promise<number>` | Основна точка входу концерну. Повертає exit-код: `0` — OK або silently skipped, `1` — порушення. |
36
-
37
- Інших експортів модуль не має. Константи `HERE` та `BASELINE_PATH` —
38
- внутрішні, не експортуються.
39
-
40
- ## Функції
41
-
42
- ### `check(cwd = process.cwd())`
43
-
44
- Асинхронна функція, що виконує перевірку та (за потреби) копіювання canonical
45
- baseline `.cargo/mutants.toml` у кожен Cargo-крейт проєкту.
46
-
47
- **Сигнатура:**
48
-
49
- ```js
50
- export async function check(cwd = process.cwd()): Promise<number>
51
- ```
52
-
53
- **Параметри:**
54
-
55
- - `cwd` — `string`, необов'язковий. Корінь проєкту, у якому шукати
56
- `.n-cursor.json` та `Cargo.toml`. За замовчуванням — `process.cwd()`
57
- (підтримка CLI-сценарію виклику).
58
-
59
- **Повертає:**
60
-
61
- - `Promise<number>` — exit-код, який повертає `reporter.getExitCode()`:
62
- - `0` — концерн пройшов успішно (включно з випадками silently skip:
63
- rust не enabled або немає жодного Cargo.toml).
64
- - `1` — concer зафейлив (наприклад, відсутній canonical baseline у
65
- дистрибутиві `@nitra/cursor`).
66
-
67
- **Алгоритм:**
68
-
69
- 1. Створює `reporter` через `createCheckReporter()`.
70
- 2. Читає `.n-cursor.json` через `readNCursorConfigLite(cwd)`, отримує
71
- `config.rules` і `config.disableRules`.
72
- 3. Self-gate: якщо `rust` не у `config.rules` або є у `config.disableRules` —
73
- повертає `reporter.getExitCode()` без жодних повідомлень.
74
- 4. Резолвить усі `Cargo.toml` у проєкті через
75
- `resolveAllCargoManifests(cwd)` (cwd, workspaces, Tauri-патерн).
76
- 5. Якщо манифестів немає — silently skip, повертає `reporter.getExitCode()`.
77
- 6. Перевіряє існування canonical baseline за шляхом `BASELINE_PATH`. Якщо
78
- файлу немає — `reporter.fail()` із рекомендацією перевстановити
79
- `@nitra/cursor` і повертає `reporter.getExitCode()`.
80
- 7. Ітерує по кожному `manifestPath`:
81
- - Обчислює `cargoDir = dirname(manifestPath)`.
82
- - Обчислює `target = join(cargoDir, '.cargo', 'mutants.toml')`.
83
- - Якщо `target` існує — `reporter.pass()` з повідомленням
84
- `.cargo/mutants.toml існує (<relative-path>)`, переходить до наступного
85
- манифеста.
86
- - Інакше — створює каталог `dirname(target)` (тобто `.cargo/`) із
87
- прапорцем `{ recursive: true }`, копіює `BASELINE_PATH` у `target`,
88
- повідомляє `reporter.pass()` з повідомленням
89
- `.cargo/mutants.toml створено з canonical baseline (<relative-path>) (test.mdc)`.
90
- 8. Повертає `reporter.getExitCode()`.
91
-
92
- **Side effects:**
93
-
94
- - Читання файлової системи: `.n-cursor.json` (через
95
- `readNCursorConfigLite`), `Cargo.toml` (через `resolveAllCargoManifests`),
96
- перевірка існування `BASELINE_PATH` і `target` (через `existsSync`).
97
- - Запис у файлову систему:
98
- - Створення каталогу `.cargo/` у кожному cargo-крейті, де ще нема
99
- `.cargo/mutants.toml` (`mkdir` з `recursive: true`).
100
- - Копіювання `BASELINE_PATH` у `.cargo/mutants.toml` (`copyFile`).
101
- - Виклики reporter (`pass` / `fail`) — у stdout/stderr формат залежить
102
- від реалізації `createCheckReporter`.
103
-
104
- ## Залежності
105
-
106
- ### Стандартна бібліотека Node.js
107
-
108
- - `node:fs` — `existsSync`.
109
- - `node:fs/promises` — `copyFile`, `mkdir`.
110
- - `node:path` — `dirname`, `join`, `relative`.
111
- - `node:url` — `fileURLToPath` (для обчислення абсолютного шляху до
112
- baseline через `import.meta.url`).
113
-
114
- ### Внутрішні модулі проєкту
115
-
116
- - `../../../scripts/lib/check-reporter.mjs` — `createCheckReporter()`,
117
- фабрика репортера; об'єкт із методами `pass(msg)`, `fail(msg)`,
118
- `getExitCode()`.
119
- - `../../../scripts/lib/read-n-cursor-config-lite.mjs` —
120
- `readNCursorConfigLite(cwd)`, читає `.n-cursor.json` і повертає об'єкт із
121
- полями `rules: string[]` і `disableRules: string[]`.
122
- - `../../../scripts/utils/resolve-cargo-manifest.mjs` —
123
- `resolveAllCargoManifests(cwd)`, повертає масив абсолютних шляхів до всіх
124
- `Cargo.toml` у проєкті (cwd, workspace-члени, Tauri-патерн
125
- `src-tauri/Cargo.toml`).
126
-
127
- ### Файлові ресурси
128
-
129
- - `data/cargo_mutants_config/mutants.toml.baseline` (відносно теки модуля,
130
- обчислюється через `HERE`) — canonical baseline `.cargo/mutants.toml`.
131
- Має бути частиною дистрибутиву `@nitra/cursor`. Порожній файл з
132
- коментарем, `cargo-mutants` використовує робочі defaults.
133
-
134
- ## Потік виконання / Використання
135
-
136
- ### Як викликається
137
-
138
- Модуль експортує `check(cwd)`, яку диспетчер правила `test` (через
139
- `test.mdc` / контрактний раннер `@nitra/cursor`) викликає під час перевірки
140
- правил у проєкті. Можлива також CLI-сумісність — функція приймає
141
- необов'язковий `cwd` і за замовчуванням використовує `process.cwd()`.
142
-
143
- ### Типовий сценарій
144
-
145
- 1. Користувач додає у `.n-cursor.json` правило `rust` (поза `disable-rules`).
146
- 2. Раннер виконує концерн `cargo_mutants_config` (через `check(cwd)`).
147
- 3. Концерн читає конфіг, проходить self-gate.
148
- 4. Концерн через `resolveAllCargoManifests` знаходить усі `Cargo.toml`
149
- (cwd, workspace-члени, `src-tauri/Cargo.toml` для Tauri-проєктів).
150
- 5. Для кожного манифеста, що не має `.cargo/mutants.toml`, файл
151
- створюється з canonical baseline; для тих, що вже мають — pass.
152
- 6. Раннер отримує exit-код `0` або `1` і агрегує його з рештою концернів.
153
-
154
- ### Сценарії silently skip
12
+ Огляд
155
13
 
156
- - `rust` не у `rules` концерн не релевантний, скіп.
157
- - `rust` у `disable-rules` — користувач свідомо вимкнув, скіп.
158
- - Жодного `Cargo.toml` у проєкті — манифест ще не створено, скіп
159
- (не помилка).
14
+ Файл отримує робочий каталог, читає конфігурацію курсора та перевіряє налаштування проєкту. Перевіряється наявність правил rust або їх вимкнення, маніфестів Cargo та файлу canonical baseline. Якщо знайдено файл mutants.toml, процес створення файлу mutants.toml пропускається. У випадку наявності mutants.toml, створюється директорія для цільового файлу, копіюється canonical baseline у цей файл та повідомляється про створення файлу mutants.toml (test.mdc).
160
15
 
161
- ### Сценарій порушення (`exit 1`)
16
+ ## Поведінка
162
17
 
163
- - canonical baseline `data/cargo_mutants_config/mutants.toml.baseline`
164
- відсутній у дистрибутиві `@nitra/cursor` — інсталяція пакета зламана,
165
- потрібно перевстановити.
18
+ 1. Отримати корінь проєкту або використовувати поточний робочий каталог
19
+ 2. Зчитати конфігурацію курсора
20
+ 3. Перевірити наявність правила rust або його вимкнення
21
+ 4. Звернути увагу, якщо не знайдено маніфестів Cargo
22
+ 5. Перевірити наявність файлу canonical baseline
23
+ 6. Ітерувати по всіх знайдених маніфестах
24
+ 7. Для кожного маніфеста визначити директорію цільового файлу
25
+ 8. Перевірити наявність файлу mutants.toml
26
+ 9. Якщо файл mutants.toml існує, пропустити
27
+ 10. Створити директорію для цільового файлу
28
+ 11. Скопіювати canonical baseline у цільовий файл
29
+ 12. Повідомити про створення файлу mutants.toml з canonical baseline (test.mdc)
166
30
 
167
- ### Внутрішні константи
31
+ ## Гарантії поведінки
168
32
 
169
- - `HERE = dirname(fileURLToPath(import.meta.url))` — абсолютний шлях до
170
- теки, де лежить цей `.mjs`.
171
- - `BASELINE_PATH = join(HERE, 'data', 'cargo_mutants_config', 'mutants.toml.baseline')` —
172
- абсолютний шлях до canonical baseline. Шлях відраховується від
173
- розташування самого модуля, тому стабільний незалежно від `cwd`.
33
+ - Не звертається до мережі.
@@ -1,136 +1,34 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/test/js/location.mjs
4
+ crc: 9ea5f9b8
5
+ score: 100
6
+ ---
7
+
1
8
  # location.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Модуль реалізує перевірку правила `test.mdc` щодо **розміщення тестових файлів** у JS-кодовій базі.
6
-
7
- Конвенція: усі файли з суфіксом `.test.mjs` повинні лежати у каталозі `tests/`, що розташований поряд із джерельним файлом. Тобто для джерела `dir/foo.mjs` правильне розташування тесту — `dir/tests/foo.test.mjs`, а не `dir/foo.test.mjs`.
8
-
9
- Особливості:
10
-
11
- - Виключено `*_test.rego` — Rego unit-тести, за конвенцією OPA community, лежать поряд із полісі.
12
- - Обхід дерева через `walkDir` автоматично пропускає `node_modules`, `.git`, `dist`, `build`, `.venv`, `venv`.
13
- - Додатково ігноруються шляхи з `.n-cursor.json:ignore` (через `loadCursorIgnorePaths`).
14
-
15
- Файл експортує асинхронну функцію `check`, яка призначена для запуску з кореня репозиторію (зазвичай через runner правил у `npm/rules/`). Повертає exit-код (0 — успіх, 1 — порушення), формуючи звіт через `createCheckReporter`.
16
-
17
- ## Експорти / API
18
-
19
- | Експорт | Тип | Опис |
20
- | ------- | ---------------------------------------- | ------------------------------------------------------------ |
21
- | `check` | `(cwdParam?: string) => Promise<number>` | Запуск перевірки розміщення `*.test.mjs`. Повертає exit-код. |
22
-
23
- Внутрішні (не експортовані) допоміжні функції:
24
-
25
- - `isTestFile(absPath: string): boolean`
26
- - `isInsideTestsDir(absPath: string): boolean`
27
-
28
- Внутрішня константа:
29
-
30
- - `TESTS_DIR_NAME = 'tests'` — канонічна назва каталогу для тестів.
31
-
32
- ## Функції
33
-
34
- ### `isTestFile(absPath)`
35
-
36
- - **Сигнатура:** `function isTestFile(absPath: string): boolean`
37
- - **Параметри:**
38
- - `absPath` — абсолютний (або відносний — функція не залежить від форми) шлях до файла.
39
- - **Повертає:** `true`, якщо `basename(absPath)` закінчується на `.test.mjs`, інакше `false`.
40
- - **Side effects:** немає; функція чиста.
41
- - **Використання:** фільтрує лише JS-тести; інші розширення (`.test.ts`, `_test.rego` тощо) ігноруються.
42
-
43
- ### `isInsideTestsDir(absPath)`
44
-
45
- - **Сигнатура:** `function isInsideTestsDir(absPath: string): boolean`
46
- - **Параметри:**
47
- - `absPath` — шлях до тестового файла.
48
- - **Повертає:** `true`, якщо басенейм безпосередньої батьківської директорії дорівнює `tests` (значення `TESTS_DIR_NAME`).
49
- - **Side effects:** немає; функція чиста.
50
- - **Зауваження:** перевіряється саме безпосередній батько (`basename(dirname(absPath))`), а не наявність `tests/` будь-де у шляху. Тобто `pkg/tests/sub/foo.test.mjs` буде вважатися **поза** `tests/` (батько — `sub`, а не `tests`).
51
-
52
- ### `check(cwdParam = process.cwd())`
53
-
54
- - **Сигнатура:** `export async function check(cwdParam?: string): Promise<number>`
55
- - **Параметри:**
56
- - `cwdParam` _(опціонально)_ — корінь репозиторію, з якого починається обхід. За замовчуванням — `process.cwd()`.
57
- - **Повертає:** `Promise<number>` — exit-код від `reporter.getExitCode()`. За домовленістю з `createCheckReporter`: `0` — порушень немає, `1` — є порушення.
58
- - **Side effects:**
59
- - Читання файлової системи: обхід дерева від `cwd` через `walkDir`.
60
- - Читання конфігурації: `.n-cursor.json` через `loadCursorIgnorePaths`.
61
- - Запис у `stdout` / `stderr`: повідомлення про `pass` / `fail` через `createCheckReporter` (формат повідомлень визначається репортером).
62
- - **Алгоритм:**
63
- 1. Створити репортер: `const reporter = createCheckReporter()`, дістати `pass` і `fail`.
64
- 2. Завантажити список ігнорованих шляхів: `ignorePaths = await loadCursorIgnorePaths(cwd)`.
65
- 3. Ініціалізувати лічильник `totalTests = 0` та масив `offenders: string[]`.
66
- 4. Обійти дерево `walkDir(cwd, visitor, ignorePaths)`. Для кожного файла:
67
- - Якщо `!isTestFile(absPath)` — пропустити.
68
- - Інакше `totalTests++`.
69
- - Якщо `!isInsideTestsDir(absPath)` — додати **відносний** до `cwd` шлях у `offenders` (через `relative(cwd, absPath)`).
70
- 5. Якщо `offenders.length === 0` — викликати `pass('Всі ${totalTests} файлів *.test.mjs у каталозі tests/ (test.mdc)')` і повернути `reporter.getExitCode()`.
71
- 6. Інакше — для кожного `offenderPath`:
72
- - Обчислити `parentDir = dirname(offenderPath)` і `base = basename(offenderPath)`.
73
- - Викликати `fail` з повідомленням-підказкою: тест має лежати у `tests/` — рекомендований шлях `${parentDir}/tests/${base}` (з посиланням на правило `test.mdc`).
74
- 7. Повернути `reporter.getExitCode()`.
75
-
76
- ## Залежності
77
-
78
- ### Стандартна бібліотека Node.js
79
-
80
- - `node:path` — функції `basename`, `dirname`, `relative`.
81
-
82
- ### Внутрішні модулі репозиторію (відносні шляхи від `npm/rules/test/js/location.mjs`)
83
-
84
- - `../../../scripts/lib/check-reporter.mjs` — фабрика репортерів `createCheckReporter()`, що повертає об'єкт з методами `pass(msg)`, `fail(msg)` та `getExitCode()`.
85
- - `../../../scripts/lib/load-cursor-config.mjs` — `loadCursorIgnorePaths(cwd)`: повертає список глобів/шляхів, які слід пропустити при обході (зчитується з `.n-cursor.json`, ключ `ignore`).
86
- - `../../../scripts/utils/walkDir.mjs` — асинхронний рекурсивний обхід дерева: `walkDir(rootDir, visitor, ignorePaths)`; за замовчуванням пропускає `node_modules`, `.git`, `dist`, `build`, `.venv`, `venv`.
87
-
88
- ### Зовнішні правила (концептуальні залежності)
89
-
90
- - `test.mdc` — правило, що формалізує конвенцію розміщення тестів і на яке посилаються повідомлення `pass`/`fail`.
91
-
92
- ## Потік виконання / Використання
93
-
94
- ### Типове використання як перевірка правила
95
-
96
- Файл є частиною системи перевірок (`npm/rules/test/js/`). Зазвичай викликається runner'ом, який знає про expor `check`:
97
-
98
- ```js
99
- import { check } from './location.mjs'
100
-
101
- process.exit(await check())
102
- ```
103
-
104
- або з явним коренем:
105
-
106
- ```js
107
- const code = await check('/path/to/repo')
108
- ```
109
-
110
- ### Послідовність виконання
12
+ Файл перевіряє структуру директорій для ідентифікації та визначення тестів. Він призначений для перегляду шляхів та формування інструкцій щодо коректного розміщення тестів. (test.mdc)
111
13
 
112
- 1. Виклик `check()` (опційно з `cwdParam`).
113
- 2. Створення репортера → завантаження `ignorePaths`.
114
- 3. Однопрохідний обхід дерева від `cwd`:
115
- - на кожному кроці фільтр `isTestFile`,
116
- - інкремент `totalTests`,
117
- - перевірка `isInsideTestsDir`, накопичення `offenders`.
118
- 4. Звіт:
119
- - якщо `offenders.length === 0` — один `pass` з підсумком `totalTests`;
120
- - інакше — `fail` для кожного порушника з підказкою куди перенести.
121
- 5. Повернення exit-коду (`0` або `1`).
14
+ ## Поведінка
122
15
 
123
- ### Граничні випадки
16
+ 1. Початок перевірки.
17
+ 2. Завантаження конфігурації ігнорованих шляхів.
18
+ 3. Початок обходу директорій.
19
+ 4. Перевірка кожного файлу.
20
+ 5. Якщо файл не має суфікса `.test.mjs`, пропускається.
21
+ 6. Якщо файл має суфікс `.test.mjs`, збільшується лічильник тестів.
22
+ 7. Якщо файл не знаходиться у каталозі з іменем `tests/`, записується шлях до порушення.
23
+ 8. Якщо жодного порушення не знайдено, повертається код успіху.
24
+ 9. Якщо знайдено порушення, для кожного порушення генерується повідомлення про необхідність переміщення тесту у (test.mdc).
25
+ 10. Повернення коду звітного генератора.
124
26
 
125
- - **Немає жодного `*.test.mjs`:** `totalTests === 0`, `offenders === []` — буде успішний `pass('Всі 0 файлів *.test.mjs у каталозі tests/ (test.mdc)')`.
126
- - **Тест у вкладеному каталозі `tests/`:** наприклад, `dir/tests/sub/foo.test.mjs` — буде вважатися порушенням, бо безпосередній батько — `sub`, а не `tests`.
127
- - **Файли з частковим суфіксом:** `foo.test.mjs.bak` — не вважається тестом (не закінчується на `.test.mjs`).
128
- - **Шляхи з `.n-cursor.json:ignore`** не відвідуються `walkDir` і не впливають на лічильники.
27
+ ## Публічний API
129
28
 
130
- ### Rebuild Test
29
+ check перевіряє, чи знаходяться тестові файли у каталозі `tests/` (test.mdc).
131
30
 
132
- Для верифікації коректності документації — мисленний rebuild:
31
+ ## Гарантії поведінки
133
32
 
134
- - Дано: дерево з файлами `a/foo.test.mjs`, `a/tests/bar.test.mjs`, `b/baz.test.mjs`.
135
- - Очікувано: `totalTests === 3`; `offenders === ['a/foo.test.mjs', 'b/baz.test.mjs']`; два виклики `fail`; exit-код `1`.
136
- - Повідомлення `fail` для `a/foo.test.mjs` міститимуть підказку: `a/foo.test.mjs: тест має лежати у tests/ — перенеси у a/tests/foo.test.mjs (test.mdc)`.
33
+ - Read-only: файл не виконує операцій запису у файлову систему.
34
+ - Не звертається до мережі.