@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,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
+ - Не звертається до мережі.