@nitra/cursor 5.3.3 → 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 (157) 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 +17 -0
  4. package/bin/n-cursor.js +43 -22
  5. package/lib/docs/llm.md +23 -12
  6. package/lib/docs/models.md +29 -18
  7. package/lib/docs/omlx-trace.md +51 -0
  8. package/lib/docs/omlx.md +31 -15
  9. package/lib/omlx.mjs +2 -5
  10. package/package.json +1 -1
  11. package/rules/abie/docs/fix.md +17 -11
  12. package/rules/adr/docs/fix.md +25 -140
  13. package/rules/bun/docs/fix.md +18 -151
  14. package/rules/capacitor/docs/fix.md +16 -13
  15. package/rules/capacitor/js/docs/platforms.md +31 -43
  16. package/rules/changelog/docs/fix.md +25 -169
  17. package/rules/ci4/docs/fix.md +11 -14
  18. package/rules/doc-files/doc-files.mdc +60 -0
  19. package/rules/doc-files/docs/fix.md +31 -0
  20. package/rules/doc-files/fix.mjs +19 -0
  21. package/{skills → rules}/doc-files/js/docgen-extract.mjs +42 -19
  22. package/{skills → rules}/doc-files/js/docgen-ignore.mjs +2 -1
  23. package/{skills → rules}/doc-files/js/docgen-scan.mjs +9 -1
  24. package/{skills → rules}/doc-files/js/docs/docgen-crc.md +1 -1
  25. package/rules/doc-files/js/docs/docgen-extract-anchors.md +45 -0
  26. package/rules/doc-files/js/docs/docgen-extract.md +39 -0
  27. package/rules/doc-files/js/docs/docgen-files-batch.md +35 -0
  28. package/rules/doc-files/js/docs/docgen-gen.md +46 -0
  29. package/rules/doc-files/js/docs/docgen-ignore.md +37 -0
  30. package/rules/doc-files/js/docs/docgen-prompts.md +39 -0
  31. package/rules/doc-files/js/docs/docgen-scan.md +54 -0
  32. package/rules/doc-files/js/docs/lint.md +36 -0
  33. package/rules/doc-files/js/docs/units-js.md +31 -0
  34. package/rules/doc-files/js/docs/units-rs.md +35 -0
  35. package/rules/doc-files/js/docs/units.md +30 -0
  36. package/rules/doc-files/js/lint.mjs +96 -0
  37. package/{skills → rules}/doc-files/js/units-rs.mjs +37 -17
  38. package/rules/doc-files/lint/docs/lint.md +37 -0
  39. package/rules/doc-files/lint/lint.mjs +105 -0
  40. package/rules/doc-files/meta.json +1 -0
  41. package/rules/docker/docs/fix.md +21 -161
  42. package/rules/efes/docs/fix.md +23 -194
  43. package/rules/feedback/docs/fix.md +10 -8
  44. package/rules/ga/docs/fix.md +10 -5
  45. package/rules/graphql/docs/fix.md +23 -119
  46. package/rules/hasura/docs/fix.md +19 -5
  47. package/rules/hasura/js/docs/internal_urls.md +34 -307
  48. package/rules/image-avif/docs/fix.md +16 -127
  49. package/rules/image-compress/docs/fix.md +20 -141
  50. package/rules/image-compress/js/docs/package_setup.md +22 -182
  51. package/rules/js-bun-db/docs/fix.md +23 -139
  52. package/rules/js-bun-db/js/docs/safety.md +33 -221
  53. package/rules/js-bun-redis/docs/fix.md +25 -114
  54. package/rules/js-bun-redis/js/docs/imports.md +18 -166
  55. package/rules/js-lint/docs/fix.md +30 -108
  56. package/rules/js-lint/js/docs/lint-findings.md +37 -17
  57. package/rules/js-lint/js/docs/lint.md +22 -238
  58. package/rules/js-lint/js/docs/tooling.md +34 -331
  59. package/rules/js-lint-ci/docs/fix.md +16 -149
  60. package/rules/js-lint-ci/js/docs/lint.md +16 -136
  61. package/rules/js-mssql/docs/fix.md +18 -123
  62. package/rules/js-mssql/js/docs/deps.md +28 -251
  63. package/rules/js-run/docs/fix.md +23 -138
  64. package/rules/js-run/js/docs/runtime.md +24 -378
  65. package/rules/k8s/docs/fix.md +18 -123
  66. package/rules/nginx-default-tpl/docs/fix.md +22 -118
  67. package/rules/nginx-default-tpl/js/docs/template.md +38 -360
  68. package/rules/npm-module/docs/fix.md +27 -89
  69. package/rules/npm-module/js/docs/header_doc_pointer.md +15 -15
  70. package/rules/npm-module/js/docs/package_structure.md +36 -258
  71. package/rules/npm-module/js/docs/rule_meta.md +25 -127
  72. package/rules/npm-module/js/docs/skill_meta.md +18 -180
  73. package/rules/php/docs/fix.md +21 -98
  74. package/rules/php/js/docs/tooling.md +20 -143
  75. package/rules/python/docs/fix.md +25 -157
  76. package/rules/python/js/docs/applies.md +20 -98
  77. package/rules/python/js/docs/tooling.md +27 -144
  78. package/rules/rego/docs/fix.md +24 -112
  79. package/rules/rego/js/docs/applies.md +20 -164
  80. package/rules/rego/js/docs/lint.md +15 -110
  81. package/rules/release/docs/fix.md +16 -114
  82. package/rules/rust/docs/fix.md +24 -119
  83. package/rules/rust/js/docs/applies.md +20 -129
  84. package/rules/security/docs/fix.md +21 -78
  85. package/rules/security/js/docs/sample_secret.md +23 -182
  86. package/rules/security/js/docs/trufflehog.md +19 -128
  87. package/rules/style-lint/docs/fix.md +16 -150
  88. package/rules/style-lint/js/docs/lint.md +21 -172
  89. package/rules/style-lint/js/docs/tooling.md +19 -184
  90. package/rules/tauri/docs/fix.md +26 -152
  91. package/rules/tauri/js/docs/cargo_mutants_config.md +21 -159
  92. package/rules/tauri/js/docs/tooling.md +20 -217
  93. package/rules/test/docs/fix.md +19 -127
  94. package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +15 -127
  95. package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +17 -153
  96. package/rules/test/js/docs/cargo_mutants_config.md +24 -164
  97. package/rules/test/js/docs/location.md +24 -126
  98. package/rules/test/js/docs/no-process-chdir.md +20 -151
  99. package/rules/test/js/docs/no-relative-fs-path.md +24 -261
  100. package/rules/test/js/docs/stryker_config.md +48 -148
  101. package/rules/test/js/docs/vitest-config-pool-forks.md +21 -164
  102. package/rules/text/docs/fix.md +25 -113
  103. package/rules/text/js/docs/forbidden-prettier.md +21 -132
  104. package/rules/text/js/docs/formatting.md +60 -251
  105. package/rules/text/js/docs/lint.md +17 -114
  106. package/rules/vue/docs/fix.md +25 -118
  107. package/rules/vue/js/docs/packages.md +25 -323
  108. package/rules/worktree/docs/fix.md +31 -150
  109. package/scripts/coverage-classify/docs/index.md +23 -209
  110. package/scripts/coverage-classify/docs/verdict-schema.md +14 -159
  111. package/scripts/dispatcher/docs/trace.md +35 -0
  112. package/scripts/docs/auto-rules.md +37 -361
  113. package/scripts/docs/lint-cli.md +12 -13
  114. package/scripts/docs/post-tool-use-fix.md +16 -15
  115. package/scripts/docs/skills-cli.md +26 -23
  116. package/scripts/docs/sync-claude-config.md +94 -34
  117. package/scripts/docs/worktree-cli.md +11 -34
  118. package/scripts/lib/docs/assert-project-root.md +14 -16
  119. package/scripts/lib/docs/changed-files.md +24 -139
  120. package/scripts/lib/docs/discover-check-rules-from-cursor.md +14 -146
  121. package/scripts/lib/docs/rule-predicates.md +20 -17
  122. package/scripts/lib/docs/run-rule-cli.md +14 -18
  123. package/scripts/lib/docs/run-rule.md +13 -20
  124. package/scripts/lib/docs/run-standard-rule.md +12 -15
  125. package/scripts/lib/docs/sync-gitignore-worktree.md +15 -18
  126. package/scripts/lib/rule-predicates.mjs +1 -1
  127. package/scripts/sync-claude-config.mjs +4 -1
  128. package/scripts/utils/docs/with-lock.md +19 -12
  129. package/scripts/utils/with-lock.mjs +4 -2
  130. package/skills/doc-aggregate/SKILL.md +2 -2
  131. package/skills/doc-aggregate/js/docgen-ignore.mjs +6 -6
  132. package/skills/doc-aggregate/js/docs/docgen-ignore.md +1 -1
  133. package/skills/doc-aggregate/js/docs/docgen-scan.md +78 -0
  134. package/skills/doc-files/.changes/260612-0012.md +5 -0
  135. package/skills/doc-files/.changes/260612-0031.md +5 -0
  136. package/skills/doc-files/.changes/260612-0036.md +5 -0
  137. package/skills/doc-files/.changes/260612-0114.md +5 -0
  138. package/skills/doc-files/SKILL.md +6 -6
  139. package/skills/fix/js/docs/llm-worker.md +17 -15
  140. package/skills/fix/js/docs/orchestrator.md +30 -23
  141. package/skills/fix/js/docs/t0.md +26 -16
  142. package/skills/start-check/js/docs/check.md +26 -22
  143. package/skills/taze/js/docs/diff.md +44 -20
  144. package/skills/doc-files/js/docs/docgen-extract-anchors.md +0 -27
  145. package/skills/doc-files/js/docs/docgen-extract.md +0 -29
  146. package/skills/doc-files/js/docs/docgen-files-batch.md +0 -25
  147. package/skills/doc-files/js/docs/docgen-gen.md +0 -30
  148. package/skills/doc-files/js/docs/docgen-prompts.md +0 -32
  149. package/skills/doc-files/js/docs/docgen-scan.md +0 -25
  150. package/skills/doc-files/js/docs/units-rs.md +0 -35
  151. /package/{skills → rules}/doc-files/js/docgen-crc.mjs +0 -0
  152. /package/{skills → rules}/doc-files/js/docgen-extract-anchors.mjs +0 -0
  153. /package/{skills → rules}/doc-files/js/docgen-files-batch.mjs +0 -0
  154. /package/{skills → rules}/doc-files/js/docgen-gen.mjs +0 -0
  155. /package/{skills → rules}/doc-files/js/docgen-prompts.mjs +0 -0
  156. /package/{skills → rules}/doc-files/js/units-js.mjs +0 -0
  157. /package/{skills → rules}/doc-files/js/units.mjs +0 -0
@@ -1,98 +1,36 @@
1
- # fix.mjs — точка входу правила `npm-module`
1
+ ---
2
+ docgen:
3
+ source: npm/rules/npm-module/fix.mjs
4
+ crc: 38cf876b
5
+ score: 100
6
+ ---
2
7
 
3
- ## Огляд
4
-
5
- `fix.mjs` — мінімалістична точка входу (entry-point) для правила з ідентифікатором, що відповідає назві теки, у якій файл розташований (`npm/rules/npm-module/`). Файл виконує дві ролі одночасно:
6
-
7
- 1. **Library mode** — експортує функцію `run(ctx)`, яку викликає оркестратор `npm/scripts/lib/run-standard-rule.mjs` через стандартний імпорт. Це дозволяє іншому коду (наприклад, агрегатору правил `@nitra/cursor`) виконувати правило у складі загального прогону.
8
- 2. **Standalone mode** — якщо файл стартує напряму (наприклад, `bun npm/rules/npm-module/fix.mjs`), він прогорає еквівалент команди `npx @nitra/cursor fix npm-module` через `runRuleCli` із завантаженням конфігу, whitelist та фінальним summary; повертає у процес коректний exit-code для CI/IDE.
9
-
10
- Логіки самого правила тут немає — файл лише делегує виконання у стандартний раннер `runStandardRule`, який послідовно проганяє чотири фази правила: `applies` → `JS-concerns` → `policy` → `mdc-refs`.
11
-
12
- ## Експорти / API
13
-
14
- | Назва | Тип | Призначення |
15
- | ----- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
16
- | `run` | `function (ctx?) => Promise<number>` | Іменований експорт для library-mode. Викликає `runStandardRule` зі шляхом до теки правила та опційним контекстом. Повертає Promise з exit-кодом: `0` — правило не зафіксувало порушень, `1` — є порушення. |
17
-
18
- Дефолтних експортів немає. Side-effect верхнього рівня: за умови запуску як CLI, наприкінці модуля викликається `process.exit(...)` з кодом, який повернув `runRuleCli`.
19
-
20
- ## Функції (сигнатура / параметри / повертає / side effects)
21
-
22
- ### `run(ctx)`
23
-
24
- ```js
25
- export function run(ctx)
26
- ```
27
-
28
- - **Параметри**
29
- - `ctx` _(опційний)_ — об'єкт типу `RuleContext`, імпортований з `../../scripts/lib/run-standard-rule.mjs`. Може містити, зокрема, `walkCache` (закешований обхід дерева файлів), щоб уникнути повторного walk при паралельному прогоні кількох правил.
30
- - **Повертає** `Promise<number>`:
31
- - `0` — правило не виявило порушень або не застосовується до поточного workspace.
32
- - `1` — зафіксовано принаймні одне порушення.
33
- - **Side effects**
34
- - Жодних прямих побічних ефектів у самій `run`. Усі побічні ефекти (читання файлів, друк summary, мутація `walkCache`) — у `runStandardRule` та підлеглих фазах правила.
35
- - **Реалізація**
36
-
37
- ```js
38
- return runStandardRule(import.meta.dirname, ctx)
39
- ```
8
+ # fix.mjs
40
9
 
41
- `import.meta.dirname` дає абсолютний шлях до теки правила (`.../npm/rules/npm-module/`); цей шлях `runStandardRule` використовує як корінь для пошуку фаз правила (`applies.mjs`, `js/`, `policy.mjs`, `mdc-refs.mjs` тощо).
42
-
43
- ### Standalone-блок (без іменованої функції)
44
-
45
- ```js
46
- if (isRunAsCli(import.meta.url)) {
47
- process.exit(await runRuleCli(import.meta.dirname))
48
- }
49
- ```
50
-
51
- - **Умова** — `isRunAsCli(import.meta.url)` повертає `true`, якщо модуль є точкою входу процесу (а не імпортується іншим модулем).
52
- - **Дія** — `await runRuleCli(import.meta.dirname)` виконує повний CLI-цикл (config-loading, whitelist, прогін правила, summary) і повертає exit-код. Цей код передається у `process.exit`.
53
- - **Коментар у коді** свідомо вимикає правила лінтера `n/no-process-exit` та `unicorn/no-process-exit`, оскільки standalone-entry-point має повертати exit-код для CI/IDE.
54
-
55
- ## Залежності
56
-
57
- Прямі (внутрішні) залежності — два модулі зі спільної бібліотеки скриптів проєкту:
58
-
59
- | Шлях імпорту | Що бере | Призначення |
60
- | ----------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
61
- | `../../scripts/lib/run-rule-cli.mjs` | `isRunAsCli`, `runRuleCli` | Допоміжна логіка для роботи у standalone-режимі: визначення, чи модуль є entry-point процесу, і запуск повного CLI-циклу правила, який є еквівалентом `npx @nitra/cursor fix <id>`. |
62
- | `../../scripts/lib/run-standard-rule.mjs` | `runStandardRule`, тип `RuleContext` (через JSDoc) | Уніфікований раннер чотирифазного правила (`applies → JS-concerns → policy → mdc-refs`). Через нього прогрівається walk-cache і виконуються фази у фіксованому порядку. |
63
-
64
- Зовнішніх (npm) залежностей файл не має. Він спирається на Node.js / Bun рантайм-можливості:
65
-
66
- - `import.meta.url` — для визначення, чи модуль запущений як CLI.
67
- - `import.meta.dirname` — для отримання абсолютного шляху до теки правила.
68
- - `process.exit` — для повернення exit-коду у standalone-режимі.
69
-
70
- ## Потік виконання / Використання
71
-
72
- ### Сценарій A: Library mode (через оркестратор `@nitra/cursor`)
10
+ ## Огляд
73
11
 
74
- 1. Оркестратор імпортує модуль: `const mod = await import('npm/rules/npm-module/fix.mjs')`.
75
- 2. `isRunAsCli(import.meta.url)` повертає `false` (модуль не є entry-point) — standalone-блок ігнорується.
76
- 3. Оркестратор викликає `await mod.run(ctx)`, передаючи спільний `RuleContext` (наприклад, з заздалегідь побудованим `walkCache`).
77
- 4. `run` делегує виконання `runStandardRule(import.meta.dirname, ctx)`, який проганяє чотири фази правила і повертає `0` або `1`.
78
- 5. Оркестратор агрегує exit-коди всіх правил у фінальний код процесу.
12
+ Виконує обробку JS-занепокоєних на наданому контексті прогону, застосовує політику [Політика_X] та генерує посилання MDC.
79
13
 
80
- ### Сценарій B: Standalone mode
14
+ ## Поведінка
81
15
 
82
- 1. Користувач запускає `bun npm/rules/npm-module/fix.mjs` (еквівалент `npx @nitra/cursor fix npm-module`).
83
- 2. Модуль завантажується як entry-point — `isRunAsCli(import.meta.url)` повертає `true`.
84
- 3. Виконується `await runRuleCli(import.meta.dirname)`:
85
- - завантажується конфіг (`.cursor`/проектні налаштування),
86
- - застосовується whitelist (якщо є),
87
- - запускається чотирифазне правило,
88
- - друкується summary з кількістю порушень.
89
- 4. Повернутий exit-код передається у `process.exit(...)`, що завершує процес. CI/IDE отримує `0` (успіх) або `1` (порушення).
16
+ 1. Запуск правила.
17
+ * Приймає контекст прогону.
18
+ * Виконує застосування JS-занепокоєних.
19
+ * Застосовує політику.
20
+ * Генерує посилання MDC.
21
+ * Повертає результат прогону.
22
+ 2. Виконання у режимі CLI.
23
+ * Виконується як автономний скрипт.
24
+ * Виконує повний еквівалент команди `npx @nitra/cursor fix <id>`.
25
+ * Повертає код виходу з процесу.
90
26
 
91
- ### Контракт двох ролей
27
+ ## Публічний API
92
28
 
93
- Дизайн «library + standalone в одному файлі» є типовим для правил `@nitra/cursor`:
29
+ run запускає правило: applies JS-concerns policy mdc-refs (через runStandardRule).
30
+ Library mode — викликається CLI orchestration через `import + run`.
94
31
 
95
- - Функція `run` — публічний API для оркестратора; вона **не** викликає `process.exit` і не друкує summary, лише повертає код.
96
- - Standalone-блок навпаки відповідає за повноцінний CLI-UX: завантаження конфігу, whitelist, summary, exit-code — усе, що очікується від `fix.mjs` правила, який запускається окремо.
32
+ ## Гарантії поведінки
97
33
 
98
- Завдяки цьому контракту той самий файл інтегрується і у пакетний прогін правил, і в локальне налагодження одного правила без дублювання логіки.
34
+ - Read-only: файл не виконує операцій запису у файлову систему.
35
+ - Кешує результати в межах одного прогону.
36
+ - Не звертається до мережі.
@@ -1,32 +1,32 @@
1
1
  ---
2
2
  docgen:
3
3
  source: npm/rules/npm-module/js/header_doc_pointer.mjs
4
- crc: 9058c4ea
4
+ crc: d96a2957
5
+ score: 100
5
6
  ---
6
7
 
7
8
  # header_doc_pointer.mjs
8
9
 
9
10
  ## Огляд
10
11
 
11
- Концерн правила `npm-module`, що закріплює контракт між `docs/<stem>.md` і module-level JSDoc у скриптах правил і скілів. Якщо файл вже описано у `docs/<stem>.md` — наратив у заголовному коментарі файлу є дублюванням і заборонений. Якщо `docs` немає header залишається єдиним джерелом опису поведінки і жодних обмежень немає.
12
+ Файл виконує перевірку документації для модулів. Сканує директорії npm/rules та npm/skills. Перевіряє наявність файлів docs/<stem>.md у піддиректоріях правил/скілів. Перевіряє, чи містить відповідні js-файли не більше одного рядка JSDoc. У разі перевищення ліміту, генерує звіт про порушення.
12
13
 
13
14
  ## Поведінка
14
15
 
15
- 1. Сканує всі `.mjs`-файли (крім `.test.mjs`) у `npm/rules/*/js/` та `npm/skills/*/js/`.
16
- 2. Для кожного файлу перевіряє наявність `docs/<stem>.md` поруч із `js/`.
17
- 3. Якщо `docs/<stem>.md` **відсутній** пропускає файл: перевірка не застосовується.
18
- 4. Якщо `docs/<stem>.md` **присутній** знаходить module-level JSDoc (перший `/** ... */` до першого `import`/`export` на початку рядка).
19
- 5. Рахує непорожні змістовні рядки блоку (після зрізання відступу `*`). Більше одного → порушення.
16
+ 1. Сканувати директорії npm/rules та npm/skills.
17
+ 2. Для кожної директорії перевіряти піддиректорії правил/скілів.
18
+ 3. Для кожного знайденого js-файлу перевіряти наявність файлу docs/<stem>.md.
19
+ 4. Якщо файл docs/<stem>.md існує, перевіряти, чи містить module-level JSDoc не більше одного непорожного рядка.
20
+ 5. У разі перевищення ліміту, зарепортувати порушення.
21
+ 6. Повертати код виходу репортера.
20
22
 
21
- Допустимі форми при наявних docs:
23
+ ## Публічний API
22
24
 
23
- - відсутній module-level JSDoc (0 рядків)
24
- - `/** @see ./docs/<stem>.md */` (1 рядок)
25
- - `/** Контракт: ./docs/<stem>.md */` (1 рядок)
25
+ - check сканує файли `npm/rules/*/js/*.mjs` та `npm/skills/*/js/*.mjs`.
26
+ - Якщо існує `docs/<stem>.md`, модуль повинен мати посилання на JSDoc (не наратив).
27
+ - Якщо `docs` відсутній, обмеження не застосовуються.
26
28
 
27
29
  ## Гарантії поведінки
28
30
 
29
- - Файли без `docs/`-відповідника повністю ігноруються — перевірка не створює обмежень до того, як docgen запишеться.
30
- - Якщо у файлі немає жодного module-level JSDoc — перевірка проходить.
31
- - Тестові файли (`*.test.mjs`) не скануються.
32
- - Підкаталоги `tests/`, `data/`, `templates/` у `js/` не скануються (discovery бере лише `*.mjs` безпосередньо в `js/`, не рекурсивно).
31
+ - Read-only: файл не виконує операцій запису у файлову систему.
32
+ - Не звертається до мережі.
@@ -1,274 +1,52 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/npm-module/js/package_structure.mjs
4
+ crc: 943e3b76
5
+ score: 85
6
+ ---
7
+
1
8
  # package_structure.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Модуль `package_structure.mjs` — це checker правила `npm-module.mdc` у пакеті `@nitra/cursor`. Він валідує структуру npm-модуля в монорепо: наявність каталогу `npm/`, файлу `npm/package.json`, конфігурації hk (`hk.pkl` або `.config/hk.pkl`), workflow `npm-publish.yml`, та узгодженість TypeScript-emit (поле `types`, генерація `index.d.ts`, виклик `tsc` у pre-commit hook).
6
-
7
- Модуль підтримує два альтернативні layout-и npm-модуля:
8
-
9
- 1. **`npm/src` + `.js`-файли** — канонічний layout зі згенерованим `npm/types/index.d.ts` через `tsc` з прапорцями `--declaration --allowJs --emitDeclarationOnly --outDir types --skipLibCheck`.
10
- 2. **`npm/tsconfig.emit-types.json`** — коли `.js`-файлів під `npm/src` немає; типи виганяються через `tsc -p tsconfig.emit-types.json`.
11
-
12
- Окремо модуль контролює, щоб опублікований пакет (`npm pack`) не містив тестів і фікстур: сканує каталог `npm/` за полем `"files"` з `package.json` (з урахуванням негативних glob-патернів) і відсіює test-style каталоги, імена файлів та AST-імпорти test-фреймворків.
13
-
14
- Деякі перевірки (структура `npm/package.json`, валідація `compilerOptions` у `tsconfig.emit-types.json`, валідація полів `npm-publish.yml`) делеговані Rego-полісі у `npm/policy/npm_module/`. У цьому файлі лишається лише cross-file / FS / AST-частина: чи реально існує файл на диску, чи містить опублікований tarball тести, чи має `hk.pkl` правильні підрядки команди `tsc`.
15
-
16
- Узгодженість `version`/`CHANGELOG.md` у файлі **не** перевіряється — це робить `changelog/js/consistency.mjs` за моделлю `n-changelog.mdc`.
17
-
18
- ## Експорти / API
19
-
20
- | Експорт | Тип | Призначення |
21
- | ----------------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------- |
22
- | `globToRegex(glob)` | `function` | Перетворює glob-патерн на `RegExp` із якорями `^` / `$`; підтримує `**`, `*`, `?`, `{a,b,c}`. |
23
- | `findTestFrameworkImport(content, virtualPath)` | `async function` | Парсить JS/TS через `oxc-parser` і повертає назву модуля test-фреймворку, якщо знайдено import / require / dynamic import. |
24
- | `classifyPublishedFileAsTest(relPath, cwd?)` | `async function` | Класифікує файл як test/fixture за каталогом, basename або AST-імпортом. |
25
- | `check(cwd?)` | `async function` | Головна точка входу checker-а правила `npm-module.mdc`; повертає exit-code `0` / `1`. |
26
-
27
- Решта функцій (`npmSrcTreeHasJsFile`, `readHkConfig`, `missingHkSrcLayoutFragments`, `missingHkEmitTypesConfigFragments`, `npmTypesFileFromPackageField`, `checkNpmPackageJson`, `checkEmitTypesConfig`, `checkPublishWorkflow`, `collectPublishedFiles`, `checkNoTestsInPublishedFiles`, `checkNpmModuleBasicStructure`) — приватні для модуля.
28
-
29
- ## Константи
30
-
31
- | Константа | Значення / Опис |
32
- | ------------------------ | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
33
- | `EMIT_TYPES_CONFIG` | `'npm/tsconfig.emit-types.json'` — шлях до TS-config для emit без `src`. |
34
- | `TEST_DIR_NAMES` | `Set` з `'tests'`, `'__tests__'`, `'fixtures'`, `'__fixtures__'`, `'spec'`, `'test'`. |
35
- | `TEST_FILE_PATTERNS` | `[/^.+\.(test | spec)\.[cm]?[jt]sx?$/iu]` — патерн test-файлів за basename. Rego-файли (`\*\_test.rego`) свідомо не входять (conftest-конвенція). |
36
- | `JS_LIKE_EXT_RE` | `/\.[cm]?[jt]sx?$/iu` — розширення, у яких сканується AST на імпорти test-фреймворків. |
37
- | `TEST_FRAMEWORK_MODULES` | `Set` з `'bun:test'`, `'node:test'`, `'vitest'`, `'@jest/globals'`, `'jest'`, `'mocha'`, `'ava'`, `'tap'`, `'tape'`. |
38
- | `REGEX_SPECIAL_IN_GLOB` | `Set` спецсимволів regex, які екрануються у glob-сегменті (без `*`/`?`). |
39
- | `GLOBSTAR_LEADING_RE` | `/^__GLOBSTAR__\//u` — маркер `**/` на початку. |
40
- | `GLOBSTAR_TRAILING_RE` | `/\/__GLOBSTAR__$/u` — маркер `/**` у кінці. |
41
-
42
- ## Функції
43
-
44
- ### `npmSrcTreeHasJsFile(cwd, ignorePaths = [])`
45
-
46
- - **Сигнатура:** `async (cwd: string, ignorePaths?: string[]) => Promise<boolean>`
47
- - **Параметри:**
48
- - `cwd` — корінь репозиторію.
49
- - `ignorePaths` — абсолютні шляхи каталогів, повністю виключених з обходу (з `loadCursorIgnorePaths`).
50
- - **Повертає:** `true`, якщо хоча б один `.js` під `npm/src` (рекурсивно); інакше `false`. Якщо `npm/src` не існує — одразу `false`.
51
- - **Side effects:** жодних (тільки FS-читання).
52
-
53
- ### `readHkConfig(cwd)`
54
-
55
- - **Сигнатура:** `async (cwd: string) => Promise<{ path: string, text: string } | null>`
56
- - **Параметри:** `cwd` — корінь репозиторію.
57
- - **Повертає:** обʼєкт із relative-шляхом (`hk.pkl` або `.config/hk.pkl`) і повним текстом файлу; `null`, якщо жоден кандидат не існує.
58
- - **Side effects:** читання файлу через `readFile`.
59
-
60
- ### `missingHkSrcLayoutFragments(hkText)`
61
-
62
- - **Сигнатура:** `(hkText: string) => string[]`
63
- - **Параметри:** `hkText` — текст hk-конфігурації.
64
- - **Повертає:** список фрагментів, яких немає в тексті. Очікувані фрагменти: `["pre-commit"]`, `bunx -p typescript tsc`, `src/**/*.js`, `--declaration`, `--allowJs`, `--emitDeclarationOnly`, `--outDir types`, `--skipLibCheck`.
65
- - **Side effects:** немає.
66
-
67
- ### `missingHkEmitTypesConfigFragments(hkText)`
68
-
69
- - **Сигнатура:** `(hkText: string) => string[]`
70
- - **Параметри:** `hkText` — текст hk-конфігурації.
71
- - **Повертає:** список відсутніх фрагментів для layout-у через `tsconfig.emit-types.json`: `["pre-commit"]`, `bunx -p typescript tsc`, `tsconfig.emit-types.json`.
72
- - **Side effects:** немає.
73
-
74
- ### `npmTypesFileFromPackageField(typesField)`
75
-
76
- - **Сигнатура:** `(typesField: unknown) => string | null`
77
- - **Параметри:** `typesField` — значення поля `types` з `npm/package.json`.
78
- - **Повертає:** posix-шлях `npm/<rel>` (наприклад, `npm/types/bin/x.d.ts`) або `null`, якщо значення не починається з `./types/` чи не є рядком.
79
- - **Side effects:** немає.
80
-
81
- ### `checkNpmPackageJson(useSrcJsLayout, passFn, failFn, cwd)`
82
-
83
- - **Сигнатура:** `async (useSrcJsLayout: boolean, passFn, failFn, cwd: string) => Promise<void>`
84
- - **Поведінка:**
85
- - Якщо `npm/package.json` відсутній — нічого не робить (вище у потоці це вже відловлено).
86
- - Для layout `src+js`: очікує існування `npm/types/index.d.ts`.
87
- - Для layout `emit-types`: бере `npm/<types-field>` і перевіряє існування.
88
- - **Викликає:** `passFn(msg)` при успіху, `failFn(msg)` при помилці.
89
- - **Side effects:** читає `npm/package.json`.
90
-
91
- ### `checkEmitTypesConfig(passFn, failFn, cwd)`
92
-
93
- - **Сигнатура:** `(passFn, failFn, cwd: string) => void`
94
- - **Поведінка:** перевіряє лише існування `npm/tsconfig.emit-types.json`. Структуру `compilerOptions` валідує Rego-полісі `npm_module/emit_types_config`.
95
-
96
- ### `checkPublishWorkflow(passFn, failFn, cwd)`
97
-
98
- - **Сигнатура:** `(passFn, failFn, cwd: string) => void`
99
- - **Поведінка:** перевіряє лише існування `.github/workflows/npm-publish.yml`. Структуру полів workflow валідує Rego-полісі `npm_module/npm_publish_yml`.
100
-
101
- ### `globToRegex(glob)` (експортована)
102
-
103
- - **Сигнатура:** `(glob: string) => RegExp`
104
- - **Параметри:** `glob` — posix-шлях у glob-нотації.
105
- - **Повертає:** `RegExp` з якорями `^` / `$` і прапорцем `u`.
106
- - **Підтримка синтаксису:**
107
- - `**` — нуль або більше сегментів (`(?:/.*/|/)` між сегментами, `(?:.*/)?` на початку, `(?:/.*)?` у кінці, `.*` як єдиний токен).
108
- - `*` — будь-які символи без `/` (`[^/]*`).
109
- - `?` — один символ без `/` (`[^/]`).
110
- - `{a,b,c}` — brace-альтернативи (`(?:a|b|c)`).
111
- - **Не підтримує:** клас `[…]` (для негативних патернів `files` цього достатньо).
112
- - **Safety:** усі спецсимволи екрануються через `REGEX_SPECIAL_IN_GLOB`; eslint правило `security/detect-non-literal-regexp` явно вимкнено, бо вхід контрольований (поле `files` з `npm/package.json`).
113
-
114
- ### `collectPublishedFiles(filesField, cwd)`
115
-
116
- - **Сигнатура:** `async (filesField: string[], cwd: string) => Promise<string[]>`
117
- - **Параметри:**
118
- - `filesField` — значення поля `files` з `npm/package.json`.
119
- - `cwd` — корінь репозиторію.
120
- - **Алгоритм:**
121
- 1. Розділяє patterns на позитивні і негативні (за префіксом `!`).
122
- 2. Для кожного позитивного pattern: якщо це файл — додає до `collected`; якщо директорія — рекурсивно через `walkDir` додає всі знайдені файли (posix-шляхи без `npm/` префікса).
123
- 3. Фільтрує: викидає файли, які матчать будь-який негативний `globToRegex`.
124
- 4. Сортує `[].sort()` (лексикографічно) і повертає.
125
- - **Side effects:** `stat()` для кожного позитивного pattern, `walkDir` для директорій.
126
- - **Обмеження:** не дублює всю логіку `npm pack` (LICENSE / README / mandatory files); сканує лише простір імен `files`.
127
-
128
- ### `findTestFrameworkImport(content, virtualPath)` (експортована)
129
-
130
- - **Сигнатура:** `(content: string, virtualPath: string) => string | null`
131
- - **Параметри:**
132
- - `content` — повний текст файлу.
133
- - `virtualPath` — шлях файлу (для вибору `lang` через `langFromPath`).
134
- - **Повертає:** ім'я модуля test-фреймворку (з `TEST_FRAMEWORK_MODULES`), якщо знайдено; `null` інакше.
135
- - **Алгоритм:**
136
- 1. Парсить через `parseSync` із `oxc-parser`; при помилці парсингу — повертає `null` (це не AST-checker для синтаксису).
137
- 2. Якщо `result.errors.length` ≠ 0 — повертає `null`.
138
- 3. Спочатку перевіряє `result.module.staticImports`.
139
- 4. Якщо в static-import не знайдено — обходить AST через `walkAstWithAncestors` і шукає `require(...)` (через `requireCallModule`) та `import(...)` dynamic (через `dynamicImportModule`).
140
- - **Side effects:** немає.
141
-
142
- ### `classifyPublishedFileAsTest(relPath, cwd = process.cwd())` (експортована)
143
-
144
- - **Сигнатура:** `async (relPath: string, cwd?: string) => Promise<string | null>`
145
- - **Параметри:**
146
- - `relPath` — posix-шлях відносно `npm/`.
147
- - `cwd` — корінь репозиторію (за замовчуванням `process.cwd()`).
148
- - **Повертає:** рядок-причину порушення або `null`, якщо файл валідний.
149
- - **Класифікація (за пріоритетом):**
150
- 1. У path є сегмент із `TEST_DIR_NAMES` → `'test-style каталог "<seg>/"'`.
151
- 2. Basename матчить `TEST_FILE_PATTERNS` → `"test-style ім'я файлу"`.
152
- 3. Розширення JS-like і AST містить імпорт test-фреймворку → `'імпорт test-фреймворку "<mod>"'`.
153
- - **Carve-out:** для `rules/<rule-name>/...` сегмент `<rule-name>` (індекс 1) ігнорується, бо це ім'я правила (наприклад, правило з id `test` саме описує конвенцію тестів і не є fixture-каталогом). Подальші сегменти (`rules/<r>/js/<c>/tests/`) продовжують перевірятись.
154
- - **Side effects:** для JS-like розширень — `readFile(join(cwd, 'npm', relPath))`.
155
-
156
- ### `checkNoTestsInPublishedFiles(pass, fail, cwd)`
157
-
158
- - **Сигнатура:** `async (pass, fail, cwd: string) => Promise<void>`
159
- - **Поведінка:**
160
- - Якщо `npm/package.json` відсутній або поле `files` не масив — нічого не робить.
161
- - Інакше збирає файли через `collectPublishedFiles` і прогонить кожен через `classifyPublishedFileAsTest`.
162
- - На порушення викликає `fail(...)` з підказкою додати негативний glob у `files`.
163
- - На повну чистоту — `pass(...)` з кількістю перевірених файлів.
164
-
165
- ### `checkNpmModuleBasicStructure(pass, fail, cwd)`
166
-
167
- - **Сигнатура:** `async (pass, fail, cwd: string) => Promise<void>`
168
- - **Поведінка:** перевіряє наявність `package.json`, директорії `npm/` і `npm/package.json`. Поле `workspaces ∋ "npm"` у кореневому `package.json` валідує Rego.
169
-
170
- ### `check(cwd = process.cwd())` (експортована, головна)
171
-
172
- - **Сигнатура:** `async (cwd?: string) => Promise<number>`
173
- - **Повертає:** `0` — все OK, `1` — є проблеми (через `reporter.getExitCode()`).
174
- - **Алгоритм:**
175
- 1. Створює `createCheckReporter()`, дістає `pass`, `fail`.
176
- 2. `checkNpmModuleBasicStructure` — `package.json`, `npm/`, `npm/package.json`.
177
- 3. `checkNoTestsInPublishedFiles` — компактність tarball.
178
- 4. `loadCursorIgnorePaths(cwd)` для подальшого скану `npm/src`.
179
- 5. `npmSrcTreeHasJsFile` → визначає `useSrcJsLayout`.
180
- 6. `checkNpmPackageJson(useSrcJsLayout, ...)` — поле `types` і відповідний файл на диску.
181
- 7. Якщо НЕ `useSrcJsLayout` — `checkEmitTypesConfig`.
182
- 8. `readHkConfig` → знайти hk; перевірити pre-commit-фрагменти через `missingHkSrcLayoutFragments` або `missingHkEmitTypesConfigFragments` залежно від layout.
183
- 9. `.github/workflows/` існує.
184
- 10. `checkPublishWorkflow` — `npm-publish.yml`.
185
- 11. `return reporter.getExitCode()`.
186
-
187
- ## Залежності
188
-
189
- ### Node.js core
190
-
191
- - `node:fs` — `existsSync`.
192
- - `node:fs/promises` — `readFile`, `stat`.
193
- - `node:path` — `join`, `sep`.
194
-
195
- ### Зовнішні npm
196
-
197
- - `oxc-parser` — `parseSync` для AST-парсингу JS/TS у `findTestFrameworkImport`.
198
-
199
- ### Внутрішні (relative)
200
-
201
- - `../../../scripts/utils/ast-scan-utils.mjs` — `dynamicImportModule`, `langFromPath`, `requireCallModule`, `walkAstWithAncestors`.
202
- - `../../../scripts/lib/check-reporter.mjs` — `createCheckReporter` (повертає `{ pass, fail, getExitCode }`).
203
- - `../../../scripts/lib/load-cursor-config.mjs` — `loadCursorIgnorePaths` (читає `.cursorignore`-подібні шляхи).
204
- - `../../../scripts/utils/walkDir.mjs` — `walkDir(root, callback, ignorePaths?)` для рекурсивного обходу.
205
-
206
- ## Потік виконання / Використання
207
-
208
- ### Базовий потік `check(cwd)`
209
-
210
- ```text
211
- check(cwd)
212
- ├── createCheckReporter() → { pass, fail, getExitCode }
213
- ├── checkNpmModuleBasicStructure(pass, fail, cwd)
214
- │ ├── existsSync(cwd/package.json) ? pass : fail
215
- │ ├── existsSync(cwd/npm) && stat(...).isDirectory() ? pass : fail
216
- │ └── existsSync(cwd/npm/package.json) ? pass : fail
217
- ├── checkNoTestsInPublishedFiles(pass, fail, cwd)
218
- │ ├── readFile(npm/package.json) → pkg
219
- │ ├── if !Array.isArray(pkg.files) → return
220
- │ ├── files = collectPublishedFiles(pkg.files, cwd)
221
- │ └── for rel of files: classifyPublishedFileAsTest(rel, cwd)
222
- ├── ignorePaths = loadCursorIgnorePaths(cwd)
223
- ├── useSrcJsLayout = npmSrcTreeHasJsFile(cwd, ignorePaths)
224
- ├── checkNpmPackageJson(useSrcJsLayout, pass, fail, cwd)
225
- ├── if !useSrcJsLayout → checkEmitTypesConfig(pass, fail, cwd)
226
- ├── hk = readHkConfig(cwd)
227
- │ ├── hk == null → fail (потрібен hk.pkl)
228
- │ └── inakshe →
229
- │ missing = useSrcJsLayout
230
- │ ? missingHkSrcLayoutFragments(hk.text)
231
- │ : missingHkEmitTypesConfigFragments(hk.text)
232
- │ missing.length === 0 ? pass : fail
233
- ├── existsSync(.github/workflows/) ? pass : fail
234
- ├── checkPublishWorkflow(pass, fail, cwd)
235
- └── return reporter.getExitCode()
236
- ```
12
+ globToRegex
13
+ Перетворює glob-патерн у RegExp з якорями `^` та `$`.
237
14
 
238
- ### Точка інтеграції
15
+ findTestFrameworkImport
16
+ Знаходить імпорт модуля тест-фреймворку з контенту файлу.
239
17
 
240
- Цей файл — частина пакету `@nitra/cursor` (`npm/rules/npm-module/js/`). Він викликається CLI `npx @nitra/cursor fix` (або `n-cursor`) у режимі checker правила `npm-module`. Експортована функція `check(cwd?)` — стандартний контракт для checker-ів правил у каталозі `npm/rules/<rule>/js/`.
18
+ classifyPublishedFileAsTest
19
+ Класифікує опублікований файл як test/fixture за ознаками.
241
20
 
242
- ### Розподіл відповідальностей із Rego
21
+ check
22
+ Перевіряє відповідність проєкту правилам (npm-module.mdc).
243
23
 
244
- - **Цей JS:** FS-existence (чи є файл / директорія), AST-сканування (test-imports), glob-обчислення для `files`, cross-file (`package.json` ↔ файли на диску).
245
- - **Rego (`npm/policy/npm_module/`):**
246
- - `npm_package_json` — структура `npm/package.json` (whitelist `files`, заборона `devDependencies`, тощо).
247
- - `emit_types_config` — `compilerOptions` у `npm/tsconfig.emit-types.json`.
248
- - `npm_publish_yml` — поля workflow (`on.push.paths`, `branches`, `id-token: write`, кроки JS-DevTools/npm-publish), парсяться після YAML-parse.
249
- - `root_package_json` — `workspaces ∋ "npm"` у кореневому `package.json`.
24
+ ## Поведінка
250
25
 
251
- ### Приклад інтеграції
26
+ globToRegex
27
+ Перетворює glob-патерн у RegExp з якорями `^` / `$`.
252
28
 
253
- ```js
254
- import { check } from '@nitra/cursor/rules/npm-module/js/package_structure.mjs'
29
+ findTestFrameworkImport
30
+ Знаходить імпорт модуля тест-фреймворку з контенту файлу.
255
31
 
256
- const exitCode = await check(process.cwd())
257
- process.exit(exitCode)
258
- ```
32
+ classifyPublishedFileAsTest
33
+ Класифікує опублікований файл як test/fixture за ознаками.
259
34
 
260
- ### Що НЕ робить файл
35
+ check
36
+ Перевіряє відповідність проєкту правилам npm-module.mdc.
261
37
 
262
- - Не перевіряє узгодженість `version` ↔ `CHANGELOG.md` — це `changelog/js/consistency.mjs` (правило `n-changelog.mdc`).
263
- - Не валідує сам формат AST/синтаксис коду — за помилки парсингу `findTestFrameworkImport` мовчки повертає `null`.
264
- - Не дублює логіку `npm pack` (LICENSE / README / mandatory files) — сканує лише простір імен `files`.
265
- - Не перевіряє вміст Rego-полісі — лише дискову наявність / FS / AST.
38
+ ## Публічний API
266
39
 
267
- ## Rebuild Test
40
+ GlobToRegex перетворює glob-патерн у RegExp з використанням `^` та `$`. Підтримує globstar, `*`, `?` та brace-альтернативи.
41
+ FindTestFrameworkImport — визначає наявність імпорту/require/dynamic-import модуля тест-фреймворку. Парсинг через oxc-parser повертає `null` у разі помилки.
42
+ ClassifyPublishedFileAsTest — відносить опублікований файл до test/fixture, якщо присутні ознаки: каталог з `TEST_DIR_NAMES`, збіг імені файлу з `TEST_FILE_PATTERNS`, або імпорт тест-фреймворку для JS/TS розширень.
43
+ Carve-out — витягує ім'я правила з шляху `rules/<rule-name>/...` (індекс 1), що позначає ім'я правила. Правило з id `test` або `tests` описує конвенцію розміщення тестів, але не є test-fixture. Подальші сегменти продовжують перевірку.
44
+ Check — перевіряє відповідність проєкту правилам npm-module.mdc.
268
45
 
269
- Файл можна повністю відтворити з опису вище:
46
+ ## Гарантії поведінки
270
47
 
271
- - Імпорти: `node:fs` (`existsSync`), `node:fs/promises` (`readFile`, `stat`), `node:path` (`join`, `sep`), `oxc-parser` (`parseSync`), і чотири внутрішні модулі (`ast-scan-utils.mjs`, `check-reporter.mjs`, `load-cursor-config.mjs`, `walkDir.mjs`).
272
- - Константи: `EMIT_TYPES_CONFIG`, `TEST_DIR_NAMES`, `TEST_FILE_PATTERNS`, `JS_LIKE_EXT_RE`, `TEST_FRAMEWORK_MODULES`, `REGEX_SPECIAL_IN_GLOB`, `GLOBSTAR_LEADING_RE`, `GLOBSTAR_TRAILING_RE`.
273
- - Експорти: `globToRegex`, `findTestFrameworkImport`, `classifyPublishedFileAsTest`, `check`.
274
- - Алгоритми описано у секціях "Функції" і "Потік виконання".
48
+ - Read-only: файл не виконує операцій запису у файлову систему.
49
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
50
+ - За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
51
+ - Свідомо пропускає шляхи: `.github`, `.git`.
52
+ - Не звертається до мережі.