@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,183 +1,39 @@
1
1
  ---
2
2
  docgen:
3
3
  source: npm/rules/changelog/fix.mjs
4
- crc: 12fc1644
4
+ crc: 38cf876b
5
+ score: 100
5
6
  ---
6
7
 
7
- # fix.mjs — точка входу правила `changelog`
8
+ # fix.mjs
8
9
 
9
10
  ## Огляд
10
11
 
11
- Файл `npm/rules/changelog/fix.mjs` тонкий **entry-point** для правила `changelog` у складі пакета `@nitra/cursor`. Він виконує дві ролі одночасно:
12
+ Виконує застосування JS-занепокоєних на наданому контексті прогону. Застосовує визначену політику та генерує посилання MDC. Повертає результат прогону.
12
13
 
13
- 1. **Library mode** — експортує функцію `run(ctx)`, яку викликає зовнішній CLI-оркестратор (`scripts/cli/fix.mjs` або аналог), коли користувач запускає `npx @nitra/cursor fix changelog` (чи прогін усіх правил `fix`). У цьому режимі `runStandardRule` отримує контекст із кешем обходу файлової системи (`walkCache`), shared summary тощо.
14
- 2. **Standalone mode** — якщо файл запущено напряму (`bun npm/rules/changelog/fix.mjs`), виконується повноцінний CLI-сценарій із завантаженням конфігу, whitelist-фільтрацією й friendly summary — тобто еквівалент `npx @nitra/cursor fix changelog`.
14
+ ## Поведінка
15
15
 
16
- Сам файл **не містить бізнес-логіки** правила: вся перевірка/автофікс ділиться між суб-модулями (`applies` → `JS-concerns` → `policy` → `mdc-refs`), які підтягуються конвенційно через `runStandardRule(import.meta.dirname, ctx)`. Поведінка повністю детермінована директорією, в якій лежить `fix.mjs` (`import.meta.dirname` вказує на `npm/rules/changelog/`).
16
+ 1. Запуск правила.
17
+ * Приймає контекст прогону.
18
+ * Виконує застосування JS-занепокоєних.
19
+ * Застосовує політику.
20
+ * Генерує посилання MDC.
21
+ * Повертає результат прогону.
22
+ 2. Виконання у режимі CLI.
23
+ * Виконується як окремий скрипт.
24
+ * Еквівалент команди `npx @nitra/cursor fix <id>`.
25
+ * Виконує завантаження конфігурації.
26
+ * Виконує перевірку дозволених елементів.
27
+ * Генерує зведену інформацію.
28
+ * Виконує повний еквівалент `fix.mjs`.
17
29
 
18
- Це шаблонний файл-обгортка — він повторюється для **кожного** правила в `npm/rules/<rule-id>/fix.mjs`. Зміни тут зазвичай небажані; натомість конкретна перевірка живе у сусідніх теках (`js/`, `lib/`, `meta.json`, `changelog.mdc`).
30
+ ## Публічний API
19
31
 
20
- ## Експорти / API
32
+ run запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
33
+ Library mode — викликається CLI orchestration через `import + run`.
21
34
 
22
- | Експорт | Тип | Призначення |
23
- | ------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
24
- | `run` | `function (ctx?: RuleContext) => Promise<number>` | Library-функція для виклику з зовнішнього CLI; повертає exit-code `0` (OK) або `1` (є порушення). |
35
+ ## Гарантії поведінки
25
36
 
26
- Сторонніх іменованих експортів немає. Default export відсутній.
27
-
28
- ### Side-effect при імпорті
29
-
30
- Файл містить **top-level умовний блок**:
31
-
32
- ```js
33
- if (isRunAsCli(import.meta.url)) {
34
- process.exit(await runRuleCli(import.meta.dirname))
35
- }
36
- ```
37
-
38
- — якщо модуль виконується як точка входу процесу (`process.argv[1]` відповідає `import.meta.url`), він **завершить процес** через `process.exit(...)`. У звичайному library-імпорті (`import { run } from '.../fix.mjs'`) `isRunAsCli` повертає `false`, отже `process.exit` НЕ викликається — імпорт безпечний.
39
-
40
- Зверніть увагу на `await` на top-level — файл потребує підтримки top-level await (ESM, Node ≥ 14.8 / Bun).
41
-
42
- ## Функції
43
-
44
- ### `run(ctx)`
45
-
46
- ```js
47
- /**
48
- *
49
- */
50
- export function run(ctx) {
51
- return runStandardRule(import.meta.dirname, ctx)
52
- }
53
- ```
54
-
55
- - **Сигнатура:** `run(ctx?: RuleContext): Promise<number>`
56
- - **Параметри:**
57
- - `ctx` _(optional)_ — об'єкт `RuleContext`, тип якого імпортується з `../../scripts/lib/run-standard-rule.mjs`. Зазвичай несе спільний стан між кількома правилами: кеш обходу файлів (`walkCache`), accumulator для summary, прапорці dry-run/auto-fix тощо. Якщо `ctx` не передано — `runStandardRule` створить дефолтний контекст всередині.
58
- - **Повертає:** `Promise<number>` — exit-code правила:
59
- - `0` — порушень немає (або всі автоматично виправлені);
60
- - `1` — є невиправні порушення / помилки.
61
- - **Side effects:**
62
- - Делегує всю роботу до `runStandardRule(dir, ctx)`. Це може включати: обхід файлової системи (`walkdir`), читання/запис файлів-учасників правила (auto-fix), вивід у `stdout`/`stderr` через спільний логер, мутацію `ctx.walkCache` тощо.
63
- - **Не** викликає `process.exit` напряму.
64
- - **Помилки:** будь-який reject від `runStandardRule` пробрасується нагору (caller відповідає за `try/catch`).
65
-
66
- ### Анонімний CLI-блок (top-level)
67
-
68
- ```js
69
- if (isRunAsCli(import.meta.url)) {
70
- process.exit(await runRuleCli(import.meta.dirname))
71
- }
72
- ```
73
-
74
- - **Тригер:** виконується **лише** коли файл — точка входу процесу. Використовує `isRunAsCli(import.meta.url)` для надійного визначення (порівняння `import.meta.url` з `process.argv[1]` через `pathToFileURL`).
75
- - **Дія:** делегує до `runRuleCli(import.meta.dirname)` — повноцінного CLI-обгортача, який:
76
- - завантажує конфіг (`.cursor/cursor.json` чи аналог);
77
- - застосовує whitelist/blacklist;
78
- - збирає friendly summary;
79
- - запускає `runStandardRule` всередині.
80
- - **Завершення:** `process.exit(<exit-code>)` — пробрасує код у shell для CI/IDE-інтеграцій.
81
- - **ESLint disables:**
82
- - `n/no-process-exit` та `unicorn/no-process-exit` свідомо вимкнено коментарем — standalone entry-point **зобов'язаний** повертати exit-code для CI/IDE.
83
-
84
- ## Залежності
85
-
86
- ### Внутрішні (relative imports)
87
-
88
- | Модуль | Що використано | Призначення |
89
- | ----------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
- | `../../scripts/lib/run-rule-cli.mjs` | `isRunAsCli`, `runRuleCli` | Хелпери standalone-режиму: детект "запущено як CLI" та повноцінна CLI-обгортка. |
91
- | `../../scripts/lib/run-standard-rule.mjs` | `runStandardRule` | Універсальний раннер, що виконує "стандартну" послідовність етапів правила: `applies → JS-concerns → policy → mdc-refs`. Також експортує тип `RuleContext` (через JSDoc-`import`). |
92
-
93
- Шлях `../../` веде з `npm/rules/changelog/` до `npm/scripts/lib/`.
94
-
95
- ### Сусідні артефакти правила `changelog`
96
-
97
- Не імпортуються напряму з цього файлу, але **використовуються `runStandardRule`** конвенційно (за іменами файлів у тій самій теці):
98
-
99
- - `npm/rules/changelog/meta.json` — метадані правила (id, опис, теги, прапорці `worktree`/`policy`).
100
- - `npm/rules/changelog/changelog.mdc` — людинозрозумілий зміст правила (Cursor MDC).
101
- - `npm/rules/changelog/js/` — JS-concerns (перевірки/фікси для коду).
102
- - `npm/rules/changelog/lib/` — допоміжні модулі правила.
103
-
104
- ### Зовнішні (Node/runtime)
105
-
106
- - `import.meta.url` — стандарт ESM, для детекту CLI-режиму.
107
- - `import.meta.dirname` — потребує Node ≥ 20.11 або Bun (Bun підтримує). Передається в обидва раннери як корінь правила.
108
- - `process.exit` — глобал Node/Bun.
109
- - Top-level `await` — ESM-фіча, потребує сумісного runtime.
110
-
111
- ## Потік виконання / Використання
112
-
113
- ### Library mode (типовий — виклик з оркестратора `fix`)
114
-
115
- ```text
116
- npx @nitra/cursor fix
117
-
118
-
119
- scripts/cli/fix.mjs (orchestrator)
120
- │ для кожного правила з whitelist:
121
-
122
- import { run } from 'npm/rules/<id>/fix.mjs'
123
-
124
-
125
- run(ctx)
126
-
127
-
128
- runStandardRule(import.meta.dirname, ctx)
129
-
130
-
131
- applies → JS-concerns → policy → mdc-refs
132
-
133
-
134
- Promise<0 | 1>
135
- ```
136
-
137
- Приклад програмного виклику:
138
-
139
- ```js
140
- import { run } from '@nitra/cursor/npm/rules/changelog/fix.mjs'
141
-
142
- const code = await run({ walkCache: new Map(), summary: [] })
143
- if (code !== 0) {
144
- // є порушення — обробити в caller
145
- }
146
- ```
147
-
148
- ### Standalone mode (ручний запуск/debug)
149
-
150
- ```bash
151
- bun npm/rules/changelog/fix.mjs
152
- # еквівалент:
153
- npx @nitra/cursor fix changelog
154
- ```
155
-
156
- Послідовність:
157
-
158
- 1. ESM-модуль завантажується як entry-point.
159
- 2. Виконуються імпорти.
160
- 3. Експорт `run` реєструється (але ніхто не викликає).
161
- 4. Виконується умова `isRunAsCli(import.meta.url)` → `true`.
162
- 5. `await runRuleCli(import.meta.dirname)` — завантажує конфіг, фільтрує whitelist (тут — лише поточне правило, бо `dirname` фіксує id), запускає `runStandardRule`, друкує summary.
163
- 6. `process.exit(<code>)` — повертає exit-code у shell.
164
-
165
- ### Чому два режими в одному файлі?
166
-
167
- - **DRY** — не дублювати entry-point на кожне правило.
168
- - **DevEx** — розробник може дебажити одне правило: `bun npm/rules/<id>/fix.mjs`.
169
- - **CI** — оркестратор `fix.mjs` імпортує `run` гуртом, ділить кеш обходу між правилами для прискорення.
170
-
171
- ## Rebuild Test (контекстна незалежність)
172
-
173
- Файл можна відтворити, маючи лише цю документацію:
174
-
175
- 1. Створіть `npm/rules/changelog/fix.mjs`.
176
- 2. Імпортуйте `isRunAsCli` та `runRuleCli` з `../../scripts/lib/run-rule-cli.mjs`.
177
- 3. Імпортуйте `runStandardRule` з `../../scripts/lib/run-standard-rule.mjs`.
178
- 4. Експортуйте функцію `run(ctx)`, яка повертає результат `runStandardRule(import.meta.dirname, ctx)`.
179
- 5. Додайте JSDoc до `run` з типом `RuleContext` (через `import('../../scripts/lib/run-standard-rule.mjs').RuleContext`) і `Promise<number>` на повернення.
180
- 6. Внизу додайте умовний блок `if (isRunAsCli(import.meta.url)) { process.exit(await runRuleCli(import.meta.dirname)) }`.
181
- 7. Поряд із `process.exit(...)` додайте eslint-disable коментар для `n/no-process-exit` та `unicorn/no-process-exit` із обґрунтуванням "standalone entry-point має повертати exit-code для CI/IDE".
182
-
183
- Результат має бути ідентичним за поведінкою оригіналу: library-імпорт безпечний, standalone-запуск завершує процес коректним exit-code.
37
+ - Read-only: файл не виконує операцій запису у файлову систему.
38
+ - Кешує результати в межах одного прогону.
39
+ - Не звертається до мережі.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  docgen:
3
3
  source: npm/rules/ci4/fix.mjs
4
- crc: 12fc1644
4
+ crc: 38cf876b
5
5
  score: 100
6
6
  ---
7
7
 
@@ -9,26 +9,23 @@ docgen:
9
9
 
10
10
  ## Огляд
11
11
 
12
- Модуль виконує бізнес-процес трансформації даних. Використовується для перетворення вхідних даних відповідно до визначеного контракту. Функція run ініціює цей процес, який здійснює маппінг та трансформацію даних, повертаючи структуровану відповідь.
12
+ Огляд
13
+ Файл надає функціонал для виконання визначених правил. Публічні методи забезпечують запуск цих правил, повертаючи отримані результати. Дозволяє запускати правила у режимі командного рядка, керуючи виходом процесу на основі отриманих даних.
13
14
 
14
15
  ## Поведінка
15
16
 
16
- 1. Виклик функції run передає контекст прогону для виконання правила.
17
+ 1. Запуск правила.
18
+ * Виклик runStandardRule з контекстом.
19
+ * Повернення результату.
17
20
 
18
- 2. Виконання правила відбувається через стандартний механізм перевірки.
19
-
20
- 3. У режимі бібліотеки функція викликає основну логіку перевірки, яка включає застосування правил, перевірку конфігурації та формування посилань.
21
-
22
- 4. Якщо виконання відбувається у режимі командного рядка, функція виконує повний еквівалент інструментального прогону.
23
-
24
- 5. У режимі командного рядка функція виконує команду, яка включає завантаження конфігурації, перевірку дозволених елементів та формування зведення.
25
-
26
- 6. У режимі командного рядка результат виконання передається для негайного завершення процесу, що використовується для інструментальних середовищ.
21
+ 2. Запуск правила у режимі CLI.
22
+ * Виклик runRuleCli з директорією модуля.
23
+ * Вихід з процесом залежно від результату.
27
24
 
28
25
  ## Публічний API
29
26
 
30
- run — Запускає послідовність перевірок: applies до mdc-refs через policy та JS-concerns.
31
- Library mode — Викликається через CLI оркестрацію за допомогою імпорту та функції run.
27
+ run — запускає правило: applies JS-concerns policy mdc-refs (через runStandardRule).
28
+ Library mode — викликається CLI orchestration через `import + run`.
32
29
 
33
30
  ## Гарантії поведінки
34
31
 
@@ -0,0 +1,60 @@
1
+ ---
2
+ description: Файлова документація — обовʼязковий крок задачі (як lint); детермінований детектор застарілості за CRC джерела (lint-doc-files), генерація local-only конвеєром (fix-doc-files)
3
+ globs: "**/*.{js,mjs,ts,vue,py,rs},**/docs/**"
4
+ alwaysApply: true
5
+ version: '1.0'
6
+ ---
7
+
8
+ Кожен кодовий файл (`.js .mjs .ts .vue .py .rs`, крім тестів і `.d.ts`) має **актуальну**
9
+ файлову доку поряд: `<dir>/docs/<stem>.md`. Це **обовʼязковий крок кожної задачі**, нарівні
10
+ з lint. Актуальність детермінується за **CRC** джерела, записаним у frontmatter доки.
11
+
12
+ ## Дві відповідальності — дві команди
13
+
14
+ - **`lint-doc-files`** — детермінований **детектор**: знаходить кодові файли без актуальної
15
+ доки. **0 викликів LLM**, працює локально, в hook'ах і в CI.
16
+ - **`fix-doc-files`** — **генератор**: створює/оновлює доки local-only конвеєром (omlx) зі
17
+ штампом CRC. Потребує локальної моделі; у CI **не** запускається.
18
+
19
+ Це та сама пара, що `/n-lint` (детект) проти `/n-fix` (закриття) у решті проєкту.
20
+
21
+ ## Stale = `missing` ∪ `crc-mismatch`
22
+
23
+ Дока застаріла, якщо її **немає** (`missing`) або `crc(джерело) ≠ crc` у frontmatter
24
+ (`crc-mismatch`). **Degraded** (низький score, але CRC свіжий) — **не** stale; це борг, видимий
25
+ через `lint-doc-files --degraded` і закривається `fix-doc-files --retry-degraded`.
26
+
27
+ Алгоритм детекту (кандидати, ignore-дерево, CRC, реверс-мапінг доки→джерело) повністю в
28
+ `js/docgen-scan.mjs` / `js/docgen-crc.mjs` / `js/docgen-ignore.mjs` і адаптері `js/lint.mjs`;
29
+ тут — лише людинозрозумілий контракт, без дублювання логіки.
30
+
31
+ ## Мапа команд
32
+
33
+ | Команда | Exit | Семантика |
34
+ | --- | --- | --- |
35
+ | `lint-doc-files` | 1 — є stale | повний детект, людиночитний список stale |
36
+ | `lint-doc-files [paths…]` | 1 | точковий детект заданих джерел |
37
+ | `lint-doc-files --missing-only` | 1 | лише `missing`, без `crc-mismatch` |
38
+ | `lint-doc-files --json` | 0 | JSON-лістинг усіх кандидатів зі станом |
39
+ | `lint-doc-files --hook` | 2 — stale | PostToolUse: stdin JSON, один файл |
40
+ | `lint-doc-files --git [--max N]` | 2 — stale | Stop-гейт: `git diff` HEAD; понад поріг (`N_CURSOR_DOC_FILES_GATE_MAX`, дефолт 50) — warn + exit 0 |
41
+ | `lint-doc-files --degraded` | 0 | звіт про доки зі score < порогу |
42
+ | `fix-doc-files [--limit/--from/--overwrite/--retry-degraded]` | 0/1 | local-only генерація зі штампом CRC |
43
+ | `fix-doc-files --stamp` | 0/1 | детерміноване перештампування `source`+`crc` без LLM |
44
+
45
+ Exit-коди: повний прогін — **1** (конвенція `lint-*`); `--hook`/`--git` — **2** (hook-протокол
46
+ Claude Code: blocking feedback).
47
+
48
+ ## Hook'и
49
+
50
+ PostToolUse (`lint-doc-files --hook`) **сигналить** про дрейф після правки кодового файлу;
51
+ Stop-гейт (`lint-doc-files --git`) **блокує завершення** задачі за наявності застарілих док
52
+ (виняток — масовий прогін понад поріг). Регенерація — `/doc-files` (JS-оркестрована, не диспатч
53
+ субагентів). Агрегуюча дока (module-summary, доменні) — окремий скіл `/doc-aggregate`.
54
+
55
+ ## Серіалізація
56
+
57
+ Повний `lint-doc-files` і `fix-doc-files` серіалізуються через `runStandardLint` /
58
+ `runStandardRule` (ключі `lint-doc-files` / `fix-doc-files`, виводяться зі шляху каталогу).
59
+ `--hook` / `--git` — окрема форма **без локу** (швидкий точковий вердикт). Деталі —
60
+ `.cursor/rules/scripts.mdc`, секція «Серіалізація важких CLI-команд».
@@ -0,0 +1,31 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/doc-files/fix.mjs
4
+ crc: 9df3e88d
5
+ score: 100
6
+ ---
7
+
8
+ # fix.mjs
9
+
10
+ ## Огляд
11
+
12
+ Точка входу правила doc-files для каналу `n-cursor fix doc-files`. Перевіряє структурні вимоги
13
+ правила (наявність потрібного GA-workflow і скрипта в `package.json` через policy-канал), не
14
+ чіпаючи вміст самих док.
15
+
16
+ ## Поведінка
17
+
18
+ Делегує стандартному оркестратору правил: applies → JS-concerns → policy → перевірка
19
+ markdown-посилань. Контентні порушення (відсутні чи застарілі файлові доки) свідомо поза цим
20
+ каналом — їх закриває окрема команда генерації `fix-doc-files`, а не загальний `fix`.
21
+
22
+ ## Публічний API
23
+
24
+ `run` — виконує перевірку правила і повертає код виходу (`0` — без зауважень, `1` — є порушення).
25
+ При прямому запуску файлу працює як повний еквівалент `npx @nitra/cursor fix doc-files` із
26
+ завантаженням конфігу та підсумком.
27
+
28
+ ## Гарантії поведінки
29
+
30
+ - Серіалізується спільним локом, тож паралельні запуски того самого правила дедуплікуються.
31
+ - Не виконує генерацію документації — лише структурну перевірку.
@@ -0,0 +1,19 @@
1
+ import { isRunAsCli, runRuleCli } from '../../scripts/lib/run-rule-cli.mjs'
2
+ import { runStandardRule } from '../../scripts/lib/run-standard-rule.mjs'
3
+
4
+ /**
5
+ * Запускає правило doc-files: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
6
+ * Структурні concerns (наявність workflow lint-doc-files.yml, скрипт у package.json) закриває
7
+ * policy-канал; контентні порушення (відсутні/застарілі доки) — поза `n-cursor fix`, їх закриває
8
+ * `fix-doc-files` (генерація). Library mode: викликається через `import + run(ctx)`.
9
+ * @param {import('../../scripts/lib/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону
10
+ * @returns {Promise<number>} 0 — OK, 1 — порушення
11
+ */
12
+ export function run(ctx) {
13
+ return runStandardRule(import.meta.dirname, ctx)
14
+ }
15
+
16
+ if (isRunAsCli(import.meta.url)) {
17
+ // Standalone: bun rules/doc-files/fix.mjs — еквівалент `npx @nitra/cursor fix doc-files`.
18
+ process.exitCode = await runRuleCli(import.meta.dirname)
19
+ }
@@ -213,26 +213,32 @@ function extractMarkers(src) {
213
213
 
214
214
  // ── Rust-екстрактор ──────────────────────────────────────────────────────────
215
215
 
216
- // Модульний //! doc-коментар (inner doc)
217
- const RS_MODULE_DOC_RE = /^(?:[ \t]*\/\/![ \t]?(.*)\n)*/m
218
-
219
216
  // pub fn / pub struct / pub enum / pub trait (та fn із exposure-атрибутом)
220
- const RS_PUB_ITEM_RE = /^[ \t]*(pub(?:\([^)]*\))?\s+)?(?:async\s+)?(?:unsafe\s+)?(fn|struct|enum|trait|type)\s+(\w+)/gm
217
+ // матчаться у два кроки по trim-нутому рядку — прості регекспи без бектрекінгу:
218
+ // спершу опційний pub(...)-префікс, потім сама декларація
219
+ const RS_PUB_PREFIX_RE = /^pub(?:\([^)]*\))?\s+/
220
+ const RS_ITEM_DECL_RE = /^(?:async\s+)?(?:unsafe\s+)?(fn|struct|enum|trait|type)\s+(\w+)/
221
+
222
+ // fn-декларація у trim-нутому рядку одразу після exposure-атрибута
223
+ const RS_FN_AFTER_ATTR_RE = /^(?:pub\s+)?(?:async\s+)?(?:unsafe\s+)?fn\s+/
224
+
225
+ // Будь-яка fn-декларація без pub (для приватних localSymbols)
226
+ const RS_PRIVATE_FN_RE = /^[ \t]*(?:async\s+)?(?:unsafe\s+)?fn\s+(\w+)/
221
227
 
222
228
  // Exposure-атрибути (#[tauri::command] тощо)
223
229
  const RS_EXPOSURE_ATTR_RE = /#\[(?:tauri::command|wasm_bindgen|uniffi::export|pyo3::pyfunction|napi)/gm
224
230
 
225
- // /// line-doc перед елементом
226
- const RS_LINE_DOC_RE = /(?:[ \t]*\/\/\/[ \t]?.*\n)*/
227
-
228
231
  // use crate::module::{A, B} або use std::..;
229
232
  const RS_USE_RE = /^[ \t]*use\s+([\w:]+(?:::\{[^}]+\})?(?:::\*)?(?:::\w+)?)\s*;/gm
230
233
 
231
234
  // Файловий запис: fs::write / File::create / remove_file / create_dir / write_all
232
235
  const RS_WRITE_RE = /fs::write|File::create|remove_file|create_dir|BufWriter::new|OpenOptions[^;]*\.write\s*\(\s*true/
233
236
 
234
- // Обробка помилок (але не просто `?`)
235
- const RS_CATCH_RE = /\.unwrap_or(?:_else|_default)?|if\s+let\s+Err\s*\(|match\s+\S+.*\{\s*[\s\S]*?Err\s*\(|\.map_err\s*\(|\.ok\s*\(\)/
237
+ // Обробка помилок (але не просто `?`): прості маркери; випадок
238
+ // «match з Err(-гілкою» — віконним обходом рядків у rsHasMatchWithErrArm
239
+ const RS_CATCH_SIMPLE_RES = [/\.unwrap_or(?:_else|_default)?/, /if\s+let\s+Err\s*\(/, /\.map_err\s*\(/, /\.ok\s*\(\)/]
240
+ const RS_MATCH_KW_RE = /\bmatch\s/
241
+ const RS_ERR_ARM_RE = /\bErr\s*\(/
236
242
 
237
243
  // Функції, що повертають Result або Option
238
244
  const RS_RESULT_RE = /->\s*(?:Result|Option)\s*</
@@ -243,6 +249,21 @@ const RS_NETWORK_RE = /reqwest|hyper::|TcpStream|UdpSocket|tokio::net/
243
249
  // Кешування
244
250
  const RS_CACHE_RE = /\bcache\b|\bCache\b|lazy_static!|OnceCell|OnceLock|DashMap/i
245
251
 
252
+ /**
253
+ * Чи містить джерело `match`-вираз із `Err(`-гілкою неподалік (вікно 12 рядків).
254
+ * Замінює бектрекінг-вразливу регулярку детермінованим обходом рядків.
255
+ * @param {string[]} srcLines рядки файлу
256
+ * @returns {boolean} true, якщо за `match` слідує `Err(`
257
+ */
258
+ function rsHasMatchWithErrArm(srcLines) {
259
+ for (let i = 0; i < srcLines.length; i++) {
260
+ if (!RS_MATCH_KW_RE.test(srcLines[i])) continue
261
+ const end = Math.min(i + 12, srcLines.length)
262
+ for (let j = i; j < end; j++) if (RS_ERR_ARM_RE.test(srcLines[j])) return true
263
+ }
264
+ return false
265
+ }
266
+
246
267
  /**
247
268
  * Видобуває `///` doc-рядки перед рядком `lineIdx` (назад через `#[...]` та пусті рядки).
248
269
  * @param {string[]} lines рядки файлу
@@ -254,8 +275,9 @@ function rsDocBefore(lines, lineIdx) {
254
275
  for (let i = lineIdx - 1; i >= 0; i--) {
255
276
  const t = lines[i].trim()
256
277
  if (t.startsWith('///')) doc.unshift(t.slice(3).trim())
257
- else if (t.startsWith('#[') || t.startsWith('#![') || t === '') { /* skip */ }
258
- else break
278
+ else if (t.startsWith('#[') || t.startsWith('#![') || t === '') {
279
+ /* skip */
280
+ } else break
259
281
  }
260
282
  return doc.join(' ').trim()
261
283
  }
@@ -289,7 +311,7 @@ function extractFactsRust(src, relPath) {
289
311
  for (let nli = li + 1; nli < Math.min(li + 5, srcLines.length); nli++) {
290
312
  const t = srcLines[nli].trim()
291
313
  if (t.startsWith('#[') || t === '') continue
292
- if (/^(?:pub\s+)?(?:async\s+)?(?:unsafe\s+)?fn\s+/.test(t)) exposedLineSet.add(nli)
314
+ if (RS_FN_AFTER_ATTR_RE.test(t)) exposedLineSet.add(nli)
293
315
  break
294
316
  }
295
317
  break
@@ -303,12 +325,14 @@ function extractFactsRust(src, relPath) {
303
325
  let lineOffset = 0
304
326
  for (let li = 0; li < srcLines.length; li++) {
305
327
  const line = srcLines[li]
306
- const m = line.match(/^[ \t]*(pub(?:\([^)]*\))?\s+)?(?:async\s+)?(?:unsafe\s+)?(fn|struct|enum|trait|type)\s+(\w+)/)
328
+ const trimmed = line.trimStart()
329
+ const pubM = trimmed.match(RS_PUB_PREFIX_RE)
330
+ const m = (pubM ? trimmed.slice(pubM[0].length) : trimmed).match(RS_ITEM_DECL_RE)
307
331
  if (m) {
308
- const isPub = Boolean(m[1]) || exposedLineSet.has(li)
332
+ const isPub = Boolean(pubM) || exposedLineSet.has(li)
309
333
  if (isPub) {
310
334
  const desc = rsDocBefore(srcLines, li)
311
- exports.push({ name: m[3], kind: m[2], desc })
335
+ exports.push({ name: m[2], kind: m[1], desc })
312
336
  }
313
337
  }
314
338
  lineOffset += line.length + 1
@@ -316,9 +340,8 @@ function extractFactsRust(src, relPath) {
316
340
 
317
341
  // localSymbols — приватні fn (не pub і не exposed) — не документуємо як публічний API
318
342
  const localSymbols = []
319
- for (let li = 0; li < srcLines.length; li++) {
320
- const line = srcLines[li]
321
- const m = line.match(/^[ \t]*(?:async\s+)?(?:unsafe\s+)?fn\s+(\w+)/)
343
+ for (const line of srcLines) {
344
+ const m = line.match(RS_PRIVATE_FN_RE)
322
345
  if (m && !exports.some(e => e.name === m[1])) localSymbols.push(m[1])
323
346
  }
324
347
 
@@ -336,7 +359,7 @@ function extractFactsRust(src, relPath) {
336
359
  // markers
337
360
  const markers = {
338
361
  readOnly: !RS_WRITE_RE.test(src),
339
- catchesErrors: RS_CATCH_RE.test(src),
362
+ catchesErrors: RS_CATCH_SIMPLE_RES.some(re => re.test(src)) || rsHasMatchWithErrArm(srcLines),
340
363
  returnsFalsyOnFail: RS_RESULT_RE.test(src),
341
364
  network: RS_NETWORK_RE.test(src),
342
365
  caches: RS_CACHE_RE.test(src),
@@ -18,7 +18,8 @@ export const DOCGEN_IGNORE_GLOBS = Object.freeze([
18
18
  '**/demo/**',
19
19
  '**/docs/**',
20
20
  'npm/reports/**',
21
- 'npm/bin/**'
21
+ 'npm/bin/**',
22
+ 'npm/rules/k8s/js/manifests.mjs'
22
23
  ])
23
24
 
24
25
  const IGNORE_MATCHERS = DOCGEN_IGNORE_GLOBS.map(glob => picomatch(glob, { dot: true }))
@@ -265,8 +265,16 @@ export async function runDocFilesCheckCli(argv) {
265
265
  } else if (gitMode) {
266
266
  sources = gitChangedSources(root)
267
267
  } else {
268
+ // Значення прапорців виключаємо за індексом: порівняння за значенням при
269
+ // відсутньому `--max` (maxIdx = -1) викидало argv[0] — перший шлях губився
270
+ const flagValueIdxs = new Set(
271
+ ['--max', '--root']
272
+ .map(f => argv.indexOf(f))
273
+ .filter(i => i !== -1)
274
+ .map(i => i + 1)
275
+ )
268
276
  sources = argv
269
- .filter(a => !a.startsWith('--') && a !== argv[maxIdx + 1])
277
+ .filter((a, i) => !a.startsWith('--') && !flagValueIdxs.has(i))
270
278
  .map(a => toRelSource(root, a))
271
279
  .filter(rel => rel && isDocCandidate(root, rel) && existsSync(join(root, rel)))
272
280
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  docgen:
3
- source: npm/skills/doc-files/js/docgen-crc.mjs
3
+ source: npm/rules/doc-files/js/docgen-crc.mjs
4
4
  crc: 54e8e12b
5
5
  ---
6
6
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  docgen:
3
- source: npm/skills/doc-files/js/docgen-extract-anchors.mjs
3
+ source: npm/rules/doc-files/js/docgen-extract-anchors.mjs
4
4
  crc: 49749e9c
5
5
  score: 80
6
6
  ---
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  docgen:
3
- source: npm/skills/doc-files/js/docgen-extract.mjs
4
- crc: 1592076b
3
+ source: npm/rules/doc-files/js/docgen-extract.mjs
4
+ crc: e790ff64
5
5
  score: 100
6
6
  ---
7
7
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  docgen:
3
- source: npm/skills/doc-files/js/docgen-files-batch.mjs
3
+ source: npm/rules/doc-files/js/docgen-files-batch.mjs
4
4
  crc: 5c9b8d72
5
5
  score: 95
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  docgen:
3
- source: npm/skills/doc-files/js/docgen-gen.mjs
3
+ source: npm/rules/doc-files/js/docgen-gen.mjs
4
4
  crc: e2af04d6
5
5
  score: 100
6
6
  ---
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  docgen:
3
- source: npm/skills/doc-files/js/docgen-ignore.mjs
4
- crc: f9206fe0
3
+ source: npm/rules/doc-files/js/docgen-ignore.mjs
4
+ crc: c17cd785
5
5
  score: 100
6
6
  ---
7
7
 
@@ -13,7 +13,7 @@ DOCGEN_IGNORE_GLOBS
13
13
  Список шляхів, які docgen повинен ігнорувати.
14
14
 
15
15
  isDocgenIgnored
16
- Перевіряє, чи вказаний шлях знаходиться у списку ігнорованих шляхів. Повертає булеве значення.
16
+ Перевіряє, чи шлях знаходиться у списку ігнорованих шляхів.
17
17
 
18
18
  ## Поведінка
19
19
 
@@ -25,7 +25,7 @@ isDocgenIgnored
25
25
 
26
26
  ## Публічний API
27
27
 
28
- DOCGEN_IGNORE_GLOBS — Базовий список glob-ів для ігнорування у `docgen`.
28
+ DOCGEN_IGNORE_GLOBS — Список glob-ів для ігнорування у `docgen`.
29
29
  isDocgenIgnored — Визначає, чи шлях повинен бути пропущений `docgen`. Для `kind = 'dir'` працює і на підкаталоги, наприклад, `**\\/demo/**` спрацьовує на `demo/x` під час рекурсивного обходу.
30
30
 
31
31
  ## Гарантії поведінки
@@ -0,0 +1,39 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/doc-files/js/docgen-prompts.mjs
4
+ crc: 72ac304f
5
+ score: 100
6
+ ---
7
+
8
+ # docgen-prompts.mjs
9
+
10
+ ## Огляд
11
+
12
+ Файл надає інструкції для створення лаконічної поведінкової документації українською мовою. Він містить інструменти для формування, перевірки та виправлення тексту документації, а також для визначення гарантій щодо роботи файлу
13
+
14
+ ## Поведінка
15
+
16
+ Поведінка:
17
+ - STYLE: Надає інструкцію для генерації лаконічної поведінкової документації українською мовою.
18
+ - sectionMessages: Генерує секційні промпти для різних частин документації.
19
+ - overviewMessages: Формує текст для узагальнення ролі та призначення файлу.
20
+ - criticMessages: Створює запити для перевірки чорновиків документації на наявність дефектів.
21
+ - refineMessages: Переписує та виправляє чорновки документації відповідно до критики.
22
+ - guaranteesFromMarkers: Формує список гарантій щодо поведінки файлу на основі маркерів.
23
+ - oneShotMessages: Створює універсальний запит для генерації повної документації.
24
+
25
+ ## Публічний API
26
+
27
+ STYLE — Формулює стиль файлу.
28
+ sectionMessages — Збирає повідомлення з мінімальним контекстом для кожної секції.
29
+ overviewMessages — Надає узагальнення поведінки файлу.
30
+ criticMessages — Виявляє дефекти в чорнетці секції.
31
+ refineMessages — Виправляє чорнетку, усуваючи виявлені дефекти.
32
+ guaranteesFromMarkers — Створює детермінований шаблон гарантій поведінки з фактів.
33
+
34
+ ## Гарантії поведінки
35
+
36
+ - Read-only: файл не виконує операцій запису у файлову систему.
37
+ - За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
38
+ - Кешує результати в межах одного прогону.
39
+ - Не звертається до мережі.