@nitra/cursor 12.8.0 → 12.8.2

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 (72) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +1 -1
  3. package/rules/doc-files/js/docgen-scan.mjs +4 -2
  4. package/rules/doc-files/js/docs/docgen-extract.md +10 -10
  5. package/rules/doc-files/js/docs/docgen-judge-measure.md +10 -10
  6. package/rules/doc-files/js/docs/docgen-judge.md +13 -11
  7. package/rules/doc-files/js/docs/docgen-scan.md +28 -27
  8. package/rules/doc-files/js/docs/index.md +15 -16
  9. package/rules/feedback/feedback.mdc +3 -3
  10. package/rules/ga/ga.mdc +1 -1
  11. package/rules/ga/policy/workflow_common/workflow_common.rego +3 -3
  12. package/rules/{js-lint → js}/coverage/coverage.mjs +7 -7
  13. package/rules/{js-lint → js}/docs/fix.md +1 -1
  14. package/rules/{js-lint → js}/docs/index.md +3 -3
  15. package/rules/{js-lint → js}/docs/main.md +1 -1
  16. package/rules/{js-lint → js}/js/check.mjs +10 -10
  17. package/rules/{js-lint → js}/js/docs/check.md +3 -3
  18. package/rules/{js-lint → js}/js/docs/index.md +3 -3
  19. package/rules/{js-lint → js}/js/docs/lint-findings.md +1 -1
  20. package/rules/{js-lint → js}/js/docs/tooling.md +1 -1
  21. package/rules/{js-lint → js}/js/docs/utils_imports.md +8 -8
  22. package/rules/{js-lint → js}/js/tooling.mjs +1 -1
  23. package/rules/{js-lint → js}/js/utils_imports.mjs +3 -3
  24. package/rules/{js-lint/js-lint.mdc → js/js.mdc} +30 -6
  25. package/rules/{js-lint → js}/main.mjs +22 -5
  26. package/rules/{js-lint → js}/policy/jscpd/jscpd.rego +4 -4
  27. package/rules/{js-lint → js}/policy/jscpd/target.json +1 -1
  28. package/rules/{js-lint → js}/policy/lint_js_yml/lint_js_yml.rego +6 -6
  29. package/rules/{js-lint → js}/policy/lint_js_yml/template/lint-js.yml.snippet.yml +1 -1
  30. package/rules/{js-lint → js}/policy/package_json/package_json.rego +7 -7
  31. package/rules/{js-lint → js}/policy/vscode_extensions/target.json +1 -1
  32. package/rules/{js-lint → js}/policy/vscode_extensions/vscode_extensions.rego +2 -2
  33. package/rules/js-run/lib/docs/conn-file-rules.md +1 -1
  34. package/rules/npm-module/js/docs/header_doc_pointer.md +23 -13
  35. package/rules/python/docs/main.md +10 -10
  36. package/rules/rust/docs/main.md +7 -7
  37. package/rules/style-lint/js/tooling.mjs +1 -1
  38. package/rules/test/js/docs/stryker_config.md +1 -1
  39. package/rules/test/js/stryker_config.mjs +4 -4
  40. package/rules/test/js/vitest-config-pool-forks.mjs +1 -1
  41. package/rules/test/test.mdc +4 -4
  42. package/rules/text/docs/main.md +8 -8
  43. package/rules/text/js/docs/cspell-fix.md +8 -8
  44. package/rules/text/js/docs/index.md +0 -1
  45. package/scripts/lib/docs/discover-checkable-rules.md +2 -2
  46. package/scripts/lib/docs/run-lint.md +6 -6
  47. package/scripts/lib/fix/docs/analyze-escalation.md +28 -15
  48. package/scripts/lib/fix/docs/orchestrator.md +14 -15
  49. package/scripts/lib/fix/docs/t0.md +8 -7
  50. package/scripts/lib/gha-workflow.mjs +1 -1
  51. package/scripts/lib/timing-summary.mjs +1 -1
  52. package/scripts/sync-setup-bun-deps-action.mjs +1 -1
  53. package/scripts/utils/resolve-js-root.mjs +1 -1
  54. package/skills/coverage-fix/meta.json +1 -1
  55. package/skills/lint/SKILL.md +2 -2
  56. package/skills/llm-patch/SKILL.md +1 -1
  57. package/rules/js-lint-ci/docs/fix.md +0 -28
  58. package/rules/js-lint-ci/docs/index.md +0 -12
  59. package/rules/js-lint-ci/docs/main.md +0 -27
  60. package/rules/js-lint-ci/js/docs/index.md +0 -11
  61. package/rules/js-lint-ci/js-lint-ci.mdc +0 -45
  62. package/rules/js-lint-ci/main.mjs +0 -33
  63. package/rules/js-lint-ci/meta.json +0 -1
  64. /package/rules/{js-lint → js}/js/data/tooling/knip-canonical.json +0 -0
  65. /package/rules/{js-lint → js}/js/data/tooling/oxlint-canonical.json +0 -0
  66. /package/rules/{js-lint → js}/js/lint-findings.mjs +0 -0
  67. /package/rules/{js-lint → js}/meta.json +0 -0
  68. /package/rules/{js-lint → js}/policy/jscpd/template/.jscpd.json.snippet.json +0 -0
  69. /package/rules/{js-lint → js}/policy/lint_js_yml/target.json +0 -0
  70. /package/rules/{js-lint → js}/policy/package_json/target.json +0 -0
  71. /package/rules/{js-lint → js}/policy/package_json/template/package.json.snippet.json +0 -0
  72. /package/rules/{js-lint → js}/policy/vscode_extensions/template/extensions.json.snippet.json +0 -0
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  type: JS Module
3
3
  title: utils_imports.mjs
4
- resource: npm/rules/js-lint/js/utils_imports.mjs
4
+ resource: npm/rules/js/js/utils_imports.mjs
5
5
  docgen:
6
6
  crc: 7eaeaf96
7
7
  ---
8
8
 
9
- Модуль `npm/rules/js-lint/js/utils_imports.mjs` реалізує одну з перевірок правила `js-lint.mdc`: жоден файл усередині будь-якого каталогу з ім'ям `utils/` не має імпортувати щось за межами цього самого каталогу через відносні шляхи з префіксом `..`.
9
+ Модуль `npm/rules/js/js/utils_imports.mjs` реалізує одну з перевірок правила `js.mdc`: жоден файл усередині будь-якого каталогу з ім'ям `utils/` не має імпортувати щось за межами цього самого каталогу через відносні шляхи з префіксом `..`.
10
10
 
11
11
  Філософія перевірки:
12
12
 
@@ -150,7 +150,7 @@ docgen:
150
150
 
151
151
  ### Інтеграція в перевірочний рантайм
152
152
 
153
- Модуль викликається check-runner-ом правила `js-lint.mdc` (зазвичай із `npm/rules/js-lint/js/`). Runner імпортує named export `check` і чекає на її resolved-значення як на process exit-code. Сам файл **не** має top-level executable коду — лише визначення; це дозволяє безпечно імпортувати його у тестах.
153
+ Модуль викликається check-runner-ом правила `js.mdc` (зазвичай із `npm/rules/js/js/`). Runner імпортує named export `check` і чекає на її resolved-значення як на process exit-code. Сам файл **не** має top-level executable коду — лише визначення; це дозволяє безпечно імпортувати його у тестах.
154
154
 
155
155
  Типовий виклик (псевдокод):
156
156
 
@@ -167,7 +167,7 @@ process.exit(exitCode)
167
167
  2. `check()` знаходить `utils/` каталоги в усіх package-roots.
168
168
  3. Для кожного non-test source файлу витягає імпорти.
169
169
  4. Жоден імпорт не починається з `..`.
170
- 5. `reporter.pass('utils-каталогів: N, перевірено M файлів — domain-bound імпортів немає (js-lint.mdc)')`.
170
+ 5. `reporter.pass('utils-каталогів: N, перевірено M файлів — domain-bound імпортів немає (js.mdc)')`.
171
171
  6. `getExitCode() → 0`.
172
172
 
173
173
  ### Сценарій "є порушення"
@@ -175,7 +175,7 @@ process.exit(exitCode)
175
175
  1. Знайдено файл `packages/foo/utils/helper.mjs`.
176
176
  2. У ньому є `import bar from '../lib/bar.mjs'`.
177
177
  3. `PARENT_RELATIVE_RE` матчить `../lib/bar.mjs`.
178
- 4. `reporter.fail('packages/foo/utils/helper.mjs: заборонений імпорт \'../lib/bar.mjs\' — utils/-файли мають бути generic (js-lint.mdc)')`.
178
+ 4. `reporter.fail('packages/foo/utils/helper.mjs: заборонений імпорт \'../lib/bar.mjs\' — utils/-файли мають бути generic (js.mdc)')`.
179
179
  5. `violations` інкрементується.
180
180
  6. По завершенню `getExitCode() → 1`.
181
181
 
@@ -183,7 +183,7 @@ process.exit(exitCode)
183
183
 
184
184
  1. У жодному package немає каталогу `utils/`.
185
185
  2. `utilsDirSet.size === 0`.
186
- 3. `reporter.pass('utils-каталогів немає — перевірку пропущено (js-lint.mdc)')`.
186
+ 3. `reporter.pass('utils-каталогів немає — перевірку пропущено (js.mdc)')`.
187
187
  4. `getExitCode() → 0`.
188
188
 
189
189
  ### Сценарій "файл із синтаксичною помилкою"
@@ -207,6 +207,6 @@ process.exit(exitCode)
207
207
  - **De-duplication** через `Set`: якщо monorepo-структура повертає однаковий `utils/`-шлях двічі (наприклад, `.`-root і назва вкладеного пакета перетинаються), він обробиться лише раз.
208
208
  - **Помилки `readdir`** глушаться — недоступний каталог просто пропускається без падіння всієї перевірки.
209
209
 
210
- ### Залежність від конвенцій правила `js-lint.mdc`
210
+ ### Залежність від конвенцій правила `js.mdc`
211
211
 
212
- Файл є технічною реалізацією одного з пунктів правила `js-lint.mdc`. Усі повідомлення `reporter.pass/fail` посилаються на `(js-lint.mdc)`, щоб користувач знав, де читати про сам принцип розділу `utils/` ↔ `lib/`.
212
+ Файл є технічною реалізацією одного з пунктів правила `js.mdc`. Усі повідомлення `reporter.pass/fail` посилаються на `(js.mdc)`, щоб користувач знав, де читати про сам принцип розділу `utils/` ↔ `lib/`.
@@ -141,7 +141,7 @@ export function verifyOxlintRcAgainstCanonical(cfg, canonical) {
141
141
 
142
142
  if (!deepEqualOxlintCanonical(actual, expected)) {
143
143
  failures.push(
144
- `.oxlintrc.json: поле "${key}" має збігатися з каноном пакета @nitra/cursor (npm/rules/js-lint/js/data/tooling/oxlint-canonical.json)`
144
+ `.oxlintrc.json: поле "${key}" має збігатися з каноном пакета @nitra/cursor (npm/rules/js/js/data/tooling/oxlint-canonical.json)`
145
145
  )
146
146
  }
147
147
  }
@@ -153,7 +153,7 @@ export async function check() {
153
153
  }
154
154
  }
155
155
  if (utilsDirSet.size === 0) {
156
- reporter.pass('utils-каталогів немає — перевірку пропущено (js-lint.mdc)')
156
+ reporter.pass('utils-каталогів немає — перевірку пропущено (js.mdc)')
157
157
  return reporter.getExitCode()
158
158
  }
159
159
  let violations = 0
@@ -167,7 +167,7 @@ export async function check() {
167
167
  for (const src of imports) {
168
168
  if (PARENT_RELATIVE_RE.test(src)) {
169
169
  const rel = relative(root, file)
170
- reporter.fail(`${rel}: заборонений імпорт '${src}' — utils/-файли мають бути generic (js-lint.mdc)`)
170
+ reporter.fail(`${rel}: заборонений імпорт '${src}' — utils/-файли мають бути generic (js.mdc)`)
171
171
  violations += 1
172
172
  }
173
173
  }
@@ -175,7 +175,7 @@ export async function check() {
175
175
  }
176
176
  if (violations === 0) {
177
177
  reporter.pass(
178
- `utils-каталогів: ${utilsDirSet.size}, перевірено ${checkedFiles} файлів — domain-bound імпортів немає (js-lint.mdc)`
178
+ `utils-каталогів: ${utilsDirSet.size}, перевірено ${checkedFiles} файлів — domain-bound імпортів немає (js.mdc)`
179
179
  )
180
180
  }
181
181
  return reporter.getExitCode()
@@ -5,7 +5,7 @@ alwaysApply: false
5
5
  version: '1.30'
6
6
  ---
7
7
 
8
- **oxlint**, **ESLint**, **jscpd**, **knip**. Запуск — **`n-cursor lint js-lint js-lint-ci`** (локально; у CI — `--read-only`, без **`--fix`** для oxlint/eslint — див. приклад workflow нижче). Без **prettier** і **@nitra/prettier-config**. У **`devDependencies`** має бути **`@nitra/eslint-config`** — версія не нижче канонічного мінімуму зі snippet нижче (semver-поріг, єдине джерело істини) (з **3.8.0** правило `no-restricted-syntax` забороняє `for...in`; з **3.9.2** у `getConfig` вбудовано ignore для **`**/adr/**`** — ADR-документи не валідуються ESLint, локально цей glob додавати не потрібно; також транзитивно йде **`@e18e/eslint-plugin`** для oxlint). Dependency-політику CI-етапу (`@e18e/eslint-plugin` і oxlint/eslint/jscpd/knip окремо не додавати) винесено в `js-lint-ci`.
8
+ **oxlint**, **ESLint**, **jscpd**, **knip**. Запуск — **`n-cursor lint js`** (локально; у CI — `--read-only`, без **`--fix`** для oxlint/eslint — див. приклад workflow нижче). Без **prettier** і **@nitra/prettier-config**. У **`devDependencies`** має бути **`@nitra/eslint-config`** — версія не нижче канонічного мінімуму зі snippet нижче (semver-поріг, єдине джерело істини) (з **3.8.0** правило `no-restricted-syntax` забороняє `for...in`; з **3.9.2** у `getConfig` вбудовано ignore для **`**/adr/**`** — ADR-документи не валідуються ESLint, локально цей glob додавати не потрібно; також транзитивно йде **`@e18e/eslint-plugin`** для oxlint). Dependency-політика CI-етапу: `@e18e/eslint-plugin` і oxlint/eslint/jscpd/knip окремо не додавати.
9
9
 
10
10
  У кожному **`package.json`** проєкту (корінь і всі workspace-пакети) має бути **`"type": "module"`** — весь код у ESM.
11
11
 
@@ -18,7 +18,7 @@ version: '1.30'
18
18
  }
19
19
  ```
20
20
 
21
- Канон `type` і мінімальна `@nitra/eslint-config` (semver-поріг `devDependencies`): [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json). Окремого `lint-js` скрипта немає — лінт через **`n-cursor lint js-lint js-lint-ci`** (CI — `--read-only`).
21
+ Канон `type` і мінімальна `@nitra/eslint-config` (semver-поріг `devDependencies`): [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json). Окремого `lint-js` скрипта немає — лінт через **`n-cursor lint js`** (CI — `--read-only`).
22
22
 
23
23
  ## Розширення нових файлів — `.mjs` / `.cjs`, не `.js`
24
24
 
@@ -35,7 +35,7 @@ version: '1.30'
35
35
 
36
36
  У `.vscode/extensions.json` `recommendations` мають містити `dbaeumer.vscode-eslint`, `github.vscode-github-actions`, `oxc.oxc-vscode`: [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
37
37
 
38
- У корені має бути **`.oxlintrc.json`**, який **збігається з каноном** oxlint з пакета **`@nitra/cursor`**: файл **`npm/rules/js-lint/js/data/tooling/oxlint-canonical.json`** (plugins, jsPlugins з **`@e18e/eslint-plugin`**, categories, повний набір **rules** із канону — додаткові записи в **`rules`** дозволені; також **`settings`**, **`env`**, **`globals`**). Поле **`ignorePatterns`** працює як **`rules`**: канонічні патерни з **`oxlint-canonical.json`** (наразі **`**/schema.graphql`**, **`**/auto-imports.d.ts`**) мають бути присутні, додаткові локальні glob-и дозволені. Канон **`oxlint-canonical.json`** — source-of-truth, редагується напряму; у споживачі оновлюється копіюванням файлу з репозиторію пакета. Модуль **`@e18e/eslint-plugin`** не оголошуй окремо в **`package.json`** — він уже в залежностях **`@nitra/eslint-config`** (з **3.8.0**), oxlint підвантажує його з **`node_modules`**.
38
+ У корені має бути **`.oxlintrc.json`**, який **збігається з каноном** oxlint з пакета **`@nitra/cursor`**: файл **`npm/rules/js/js/data/tooling/oxlint-canonical.json`** (plugins, jsPlugins з **`@e18e/eslint-plugin`**, categories, повний набір **rules** із канону — додаткові записи в **`rules`** дозволені; також **`settings`**, **`env`**, **`globals`**). Поле **`ignorePatterns`** працює як **`rules`**: канонічні патерни з **`oxlint-canonical.json`** (наразі **`**/schema.graphql`**, **`**/auto-imports.d.ts`**) мають бути присутні, додаткові локальні glob-и дозволені. Канон **`oxlint-canonical.json`** — source-of-truth, редагується напряму; у споживачі оновлюється копіюванням файлу з репозиторію пакета. Модуль **`@e18e/eslint-plugin`** не оголошуй окремо в **`package.json`** — він уже в залежностях **`@nitra/eslint-config`** (з **3.8.0**), oxlint підвантажує його з **`node_modules`**.
39
39
 
40
40
  Мінімум для розуміння структури (реальний корінь конфігу має збігатися з каноном повністю):
41
41
 
@@ -70,9 +70,33 @@ version: '1.30'
70
70
  .claude/worktrees/
71
71
  ```
72
72
 
73
+ ## Залежнісна політика (що не додавати)
74
+
75
+ `@e18e/eslint-plugin` окремо не додавай — він уже в залежностях `@nitra/eslint-config` (з **3.8.0**), oxlint підвантажує його з `node_modules`. Пакети oxlint/eslint/jscpd/knip теж не додавай у `devDependencies` без потреби монорепо — `bunx` тягне їх ad-hoc.
76
+
73
77
  ## knip
74
78
 
75
- Залежнісний аналіз (knip — невикористані залежності/експорти, `knip.json` канон) крос-файловий, тож винесений у правило `js-lint-ci` (`lint: full`). Див. `js-lint-ci`.
79
+ Залежнісний аналіз (knip — невикористані залежності/експорти, `knip.json` канон) крос-файловий; запускається автоматично у `lint --full` разом з jscpd.
80
+
81
+ У корені проєкту має бути **`knip.json`**, який стартує з канонічного baseline з пакета `@nitra/cursor` — файл [`npm/rules/js/js/tooling/knip-canonical.json`](./js/tooling/knip-canonical.json). Він покриває типові false-positives для наших правил: `entry` зі CLI-конфігами (eslint, stylelint, oxlint, jscpd, markdownlint-cli2, `commitlint`), `project` для `**/*.{js,mjs,cjs,jsx,ts,tsx,mts,cts}`, `ignore` для `**/__fixtures__/**`, `ignoreDependencies` для пакетів, посилання на які є лише в не-JS-конфігах (`@nitra/cspell-dict`, `/@cspell\/dict-.+/`, `graphql`), і `ignoreBinaries` для CLI, які канон вимагає викликати через `npx`/`bunx` і яких заборонено додавати в `devDependencies` (`actionlint`, `cspell`, `eslint`, `git-ai`, `jscpd`, `markdownlint-cli2`, `oxfmt`, `oxlint`, `shellcheck`, `uvx`, `v8r`, `zizmor`).
82
+
83
+ Якщо `knip.json` відсутній — `npx @nitra/cursor fix js` копіює канон у корінь проєкту (side effect). Після створення модифікуй файл під свій проєкт як завгодно: перевіряємо лише наявність, зміст подальших змін не валідується.
84
+
85
+ Пакет `knip` окремо в `devDependencies` не додавай — `bunx knip` тягне його ad-hoc, як oxlint/eslint/jscpd.
86
+
87
+ ## Заборона `@nitra/as-integrations-fastify`
88
+
89
+ Пакет **`@nitra/as-integrations-fastify`** заборонений у **`dependencies`**, **`peerDependencies`** та в import-specifier-ах. Це чистий републіш upstream, застряглий на peer `@apollo/server: "^4.0.0"`, тож на Apollo 5 `bun install` дає `warn: incorrect peer dependency`. Заміна — upstream **`@as-integrations/fastify`** (**`^3.1.0`**): peer `@apollo/server: "^4.0.0 || ^5.0.0"` + `fastify: "^5.3.0"`.
90
+
91
+ Міграція — лише specifier у трьох місцях: залежність у `package.json`, `import`, та `vi.mock(...)` / `await import(...)` у тестах. **Код не міняється**, експорти ті самі: `default` → `fastifyApollo`, named → `fastifyApolloDrainPlugin`.
92
+
93
+ ```javascript title="❌ до"
94
+ import fastifyApollo, { fastifyApolloDrainPlugin } from '@nitra/as-integrations-fastify'
95
+ ```
96
+
97
+ ```javascript title="✅ після"
98
+ import fastifyApollo, { fastifyApolloDrainPlugin } from '@as-integrations/fastify'
99
+ ```
76
100
 
77
101
  ## jscpd: рефакторинг і структура
78
102
 
@@ -95,7 +119,7 @@ version: '1.30'
95
119
 
96
120
  Швидкий тест: якщо файл завтра можна опублікувати окремим npm-пакетом без переписування — це `utils/`; якщо він тримає domain-state, читає конфіг проєкту або викликає зовнішні сервіси/файли — це `lib/`. Не плутай із чужими каталогами на кшталт `shared/` чи `common/`: канонічні назви — лише `utils/` і `lib/`.
97
121
 
98
- Автоматично гарантується: `npx @nitra/cursor fix js-lint` (концерн `utils_imports`) обходить кожен `utils/`-каталог у воркспейсах і падає, якщо знаходить relative-імпорт з `..` (вихід за межі каталогу) у будь-якому не-тестовому файлі. Це механічне втілення правила «utils не знає про домен»: тільки same-dir (`./X`), bare-пакети та `node:*` дозволені; cross-rule, конфіги проєкту чи sibling-utils — fail. Якщо потрібна domain-залежність — перенеси файл у `lib/`.
122
+ Автоматично гарантується: `npx @nitra/cursor fix js` (концерн `utils_imports`) обходить кожен `utils/`-каталог у воркспейсах і падає, якщо знаходить relative-імпорт з `..` (вихід за межі каталогу) у будь-якому не-тестовому файлі. Це механічне втілення правила «utils не знає про домен»: тільки same-dir (`./X`), bare-пакети та `node:*` дозволені; cross-rule, конфіги проєкту чи sibling-utils — fail. Якщо потрібна domain-залежність — перенеси файл у `lib/`.
99
123
 
100
124
  Додай workflow:
101
125
 
@@ -209,4 +233,4 @@ for (const item of arr) {
209
233
 
210
234
  ## Покриття + мутаційне тестування JS
211
235
 
212
- Покриття + мутаційне тестування JS постачаються через `n-cursor coverage` (правило `test.mdc`). Реалізація провайдера — у `npm/rules/js-lint/coverage/coverage.mjs`: `bun test --coverage --coverage-reporter=lcov` + `bunx stryker run`. Stryker конфігурується в `stryker.config.mjs` у JS-корені (single-package або `workspaces[0]`).
236
+ Покриття + мутаційне тестування JS постачаються через `n-cursor coverage` (правило `test.mdc`). Реалізація провайдера — у `npm/rules/js/coverage/coverage.mjs`: `bun test --coverage --coverage-reporter=lcov` + `bunx stryker run`. Stryker конфігурується в `stryker.config.mjs` у JS-корені (single-package або `workspaces[0]`).
@@ -77,6 +77,20 @@ function lintFullProject(cwd, readOnly) {
77
77
  return runInherit(readOnly ? ['eslint', '.'] : ['eslint', '--fix', '.'], cwd)
78
78
  }
79
79
 
80
+ /**
81
+ * Крос-файловий аналіз: jscpd (дублікати) + knip (невикористані залежності/експорти).
82
+ * Ігнорує `files` — завжди по всьому репо.
83
+ * @param {string} cwd корінь репо
84
+ * @returns {number} exit code
85
+ */
86
+ function lintFullCi(cwd) {
87
+ const jscpd = spawnSync('bunx', ['jscpd', '.'], { cwd, stdio: 'inherit' })
88
+ const jc = typeof jscpd.status === 'number' ? jscpd.status : 1
89
+ if (jc !== 0) return jc
90
+ const knip = spawnSync('bunx', ['knip', '--no-config-hints'], { cwd, stdio: 'inherit' })
91
+ return typeof knip.status === 'number' ? knip.status : 1
92
+ }
93
+
80
94
  /**
81
95
  * Quick-режим: авто-фікс змінених файлів, тоді класифікація лишених findings
82
96
  * на introduced / pre-existing (беклог #6/A). Блокування на будь-якому finding.
@@ -102,7 +116,7 @@ function lintChangedClassified(js, cwd, readOnly) {
102
116
  // Краш інструмента (ненульовий exit + непарсабельний json) НЕ можна тихо пропустити
103
117
  // як «чисто» — це регресія проти старого fail-fast. Фейлимо явно.
104
118
  if ((ox === null && oxRes.status !== 0) || (es === null && esRes.status !== 0)) {
105
- process.stderr.write('❌ js-lint: інструмент завершився з помилкою (не lint-порушення) — json не розпарсено\n')
119
+ process.stderr.write('❌ js: інструмент завершився з помилкою (не lint-порушення) — json не розпарсено\n')
106
120
  return 1
107
121
  }
108
122
 
@@ -110,13 +124,14 @@ function lintChangedClassified(js, cwd, readOnly) {
110
124
  if (findings.length === 0) return 0
111
125
 
112
126
  const classified = classifyFindings(findings, addedLinesByFile(js, cwd), cwd)
113
- const header = `❌ js-lint: ${findings.length} порушень (introduced ${classified.introduced.length}, pre-existing ${classified.preExisting.length})`
127
+ const header = `❌ js: ${findings.length} порушень (introduced ${classified.introduced.length}, pre-existing ${classified.preExisting.length})`
114
128
  process.stdout.write(`${header}\n${renderFindings(classified, cwd)}\n`)
115
129
  return 1
116
130
  }
117
131
 
118
132
  /**
119
- * Запускає oxlint+eslint. За замовчуванням з автофіксом; `opts.readOnly` — лише детект.
133
+ * Запускає oxlint+eslint (per-file або full) + jscpd+knip (лише full).
134
+ * За замовчуванням — з автофіксом; `opts.readOnly` — лише детект.
120
135
  * @param {string[] | undefined} files per-file: лише ці файли; undefined: весь проєкт (--full)
121
136
  * @param {string} [cwd] корінь репо
122
137
  * @param {{ readOnly?: boolean }} [opts] readOnly → без `--fix` (нуль мутацій)
@@ -125,7 +140,9 @@ function lintChangedClassified(js, cwd, readOnly) {
125
140
  export function lint(files, cwd = process.cwd(), opts = {}) {
126
141
  const readOnly = opts.readOnly === true
127
142
  if (files === undefined) {
128
- return Promise.resolve(lintFullProject(cwd, readOnly))
143
+ const esCode = lintFullProject(cwd, readOnly)
144
+ if (esCode !== 0) return Promise.resolve(esCode)
145
+ return Promise.resolve(lintFullCi(cwd))
129
146
  }
130
147
  const js = filterJsFiles(files)
131
148
  if (js.length === 0) return Promise.resolve(0)
@@ -133,6 +150,6 @@ export function lint(files, cwd = process.cwd(), opts = {}) {
133
150
  }
134
151
 
135
152
  if (isRunAsCli(import.meta.url)) {
136
- // Standalone: bun rules/js-lint/main.mjs — повний еквівалент `npx @nitra/cursor check js-lint`.
153
+ // Standalone: bun rules/js/main.mjs — повний еквівалент `npx @nitra/cursor check js`.
137
154
  process.exitCode = await runRuleCli(import.meta.dirname)
138
155
  }
@@ -1,4 +1,4 @@
1
- # Перевірка `.jscpd.json` (js-lint.mdc).
1
+ # Перевірка `.jscpd.json` (js.mdc).
2
2
  #
3
3
  # Канон надходить через --data: { "template": { "snippet": ... } }
4
4
  # Структура --data сформована з template/.jscpd.json.snippet.json.
@@ -17,7 +17,7 @@ deny contains msg if {
17
17
  not is_array(expected_value)
18
18
  actual := object.get(input, key, null)
19
19
  actual != expected_value
20
- msg := sprintf(".jscpd.json має містити \"%s\": %v (js-lint.mdc)", [key, expected_value])
20
+ msg := sprintf(".jscpd.json має містити \"%s\": %v (js.mdc)", [key, expected_value])
21
21
  }
22
22
 
23
23
  # Array subset-of для reporters.
@@ -27,7 +27,7 @@ deny contains msg if {
27
27
  actual_set := {v | some v in object.get(input, field, [])}
28
28
  some required in expected_values
29
29
  not required in actual_set
30
- msg := sprintf(".jscpd.json має містити \"%s\": [\"%s\"] (js-lint.mdc)", [field, required])
30
+ msg := sprintf(".jscpd.json має містити \"%s\": [\"%s\"] (js.mdc)", [field, required])
31
31
  }
32
32
 
33
33
  # minLines: must be number and >= expected.
@@ -35,7 +35,7 @@ deny contains msg if {
35
35
  expected := data.template.snippet.minLines
36
36
  actual := object.get(input, "minLines", null)
37
37
  not is_valid_min_lines(actual, expected)
38
- msg := sprintf(".jscpd.json має містити \"minLines\" як число >= %d (js-lint.mdc)", [expected])
38
+ msg := sprintf(".jscpd.json має містити \"minLines\" як число >= %d (js.mdc)", [expected])
39
39
  }
40
40
 
41
41
  is_valid_min_lines(actual, expected) if {
@@ -4,5 +4,5 @@
4
4
  "single": ".jscpd.json",
5
5
  "required": true
6
6
  },
7
- "missingMessage": ".jscpd.json не існує — створи з полями згідно js-lint.mdc"
7
+ "missingMessage": ".jscpd.json не існує — створи з полями згідно js.mdc"
8
8
  }
@@ -1,4 +1,4 @@
1
- # Перевірка `.github/workflows/lint-js.yml` (js-lint.mdc).
1
+ # Перевірка `.github/workflows/lint-js.yml` (js.mdc).
2
2
  #
3
3
  # Канон надходить через --data: { "template": { "snippet": ... } }
4
4
  # Структура --data сформована з template/lint-js.yml.snippet.yml.
@@ -50,7 +50,7 @@ all_run_blob := concat("\n", [r |
50
50
  deny contains msg if {
51
51
  some required_use in expected_uses_set
52
52
  not contains(all_uses_blob, required_use)
53
- msg := sprintf("lint-js.yml: відсутній крок uses: %s (js-lint.mdc)", [required_use])
53
+ msg := sprintf("lint-js.yml: відсутній крок uses: %s (js.mdc)", [required_use])
54
54
  }
55
55
 
56
56
  # ── deny: required run substrings ───────────────────────────────────────
@@ -58,26 +58,26 @@ deny contains msg if {
58
58
  deny contains msg if {
59
59
  some required_run in expected_run_substrings
60
60
  not contains(all_run_blob, required_run)
61
- msg := sprintf("lint-js.yml: у run немає %q (js-lint.mdc)", [required_run])
61
+ msg := sprintf("lint-js.yml: у run немає %q (js.mdc)", [required_run])
62
62
  }
63
63
 
64
64
  # ── deny: actions/checkout@v6 has persist-credentials: false (inverse) ──
65
65
 
66
66
  deny contains msg if {
67
67
  not has_checkout_persist_credentials_false
68
- msg := "lint-js.yml: actions/checkout@v6 має бути з with.persist-credentials: false (js-lint.mdc)"
68
+ msg := "lint-js.yml: actions/checkout@v6 має бути з with.persist-credentials: false (js.mdc)"
69
69
  }
70
70
 
71
71
  # ── deny: --fix у CI заборонено (inverse) ───────────────────────────────
72
72
 
73
73
  deny contains msg if {
74
74
  regex.match(`bunx\s+oxlint[^\n]*--fix`, all_run_blob)
75
- msg := "lint-js.yml: у run є oxlint з `--fix` (у CI заборонено) (js-lint.mdc)"
75
+ msg := "lint-js.yml: у run є oxlint з `--fix` (у CI заборонено) (js.mdc)"
76
76
  }
77
77
 
78
78
  deny contains msg if {
79
79
  contains(all_run_blob, "eslint --fix")
80
- msg := "lint-js.yml: у run є `eslint --fix` (у CI заборонено) (js-lint.mdc)"
80
+ msg := "lint-js.yml: у run є `eslint --fix` (у CI заборонено) (js.mdc)"
81
81
  }
82
82
 
83
83
  # ── helpers ─────────────────────────────────────────────────────────────
@@ -37,4 +37,4 @@ jobs:
37
37
  - uses: ./.github/actions/setup-bun-deps
38
38
 
39
39
  - name: Eslint
40
- run: n-cursor lint js-lint js-lint-ci --read-only
40
+ run: n-cursor lint js --read-only
@@ -1,4 +1,4 @@
1
- # Перевірка `package.json` (js-lint.mdc).
1
+ # Перевірка `package.json` (js.mdc).
2
2
  #
3
3
  # Канон надходить через --data: { "template": { "snippet": ... } }
4
4
  # Структура --data сформована з template/package.json.snippet.json
@@ -20,7 +20,7 @@ deny contains msg if {
20
20
  not is_object(expected_value)
21
21
  actual := object.get(input, key, null)
22
22
  actual != expected_value
23
- msg := sprintf("package.json: \"%s\" має бути %q (js-lint.mdc)", [key, expected_value])
23
+ msg := sprintf("package.json: \"%s\" має бути %q (js.mdc)", [key, expected_value])
24
24
  }
25
25
 
26
26
  # ── deny: scripts (nested) — exact match із normalize ──────────────────
@@ -29,7 +29,7 @@ deny contains msg if {
29
29
  some script_name, expected in data.template.snippet.scripts
30
30
  actual := object.get(object.get(input, "scripts", {}), script_name, "")
31
31
  normalize_script(actual) != expected
32
- msg := sprintf("package.json: scripts.%s має бути %q (js-lint.mdc)", [script_name, expected])
32
+ msg := sprintf("package.json: scripts.%s має бути %q (js.mdc)", [script_name, expected])
33
33
  }
34
34
 
35
35
  # ── deny: engines.node >= 24 (inverse, у rego) ──────────────────────────
@@ -37,13 +37,13 @@ deny contains msg if {
37
37
  deny contains msg if {
38
38
  engines := object.get(input, "engines", {})
39
39
  not engines_node_meets(object.get(engines, "node", ""))
40
- msg := "package.json: engines.node має бути >= 24 (js-lint.mdc)"
40
+ msg := "package.json: engines.node має бути >= 24 (js.mdc)"
41
41
  }
42
42
 
43
43
  deny contains msg if {
44
44
  engines := object.get(input, "engines", {})
45
45
  not engines_bun_meets(object.get(engines, "bun", ""))
46
- msg := "package.json: engines.bun має бути >= 1.3 (js-lint.mdc)"
46
+ msg := "package.json: engines.bun має бути >= 1.3 (js.mdc)"
47
47
  }
48
48
 
49
49
  # ── deny: @nitra/eslint-config >= snippet-поріг ─────────────────────────
@@ -51,14 +51,14 @@ deny contains msg if {
51
51
  deny contains msg if {
52
52
  dev := object.get(input, "devDependencies", {})
53
53
  not "@nitra/eslint-config" in object.keys(dev)
54
- msg := "package.json: відсутній @nitra/eslint-config у devDependencies (js-lint.mdc)"
54
+ msg := "package.json: відсутній @nitra/eslint-config у devDependencies (js.mdc)"
55
55
  }
56
56
 
57
57
  deny contains msg if {
58
58
  range := object.get(object.get(input, "devDependencies", {}), "@nitra/eslint-config", "")
59
59
  range != ""
60
60
  not eslint_config_meets_min(range)
61
- msg := sprintf("package.json: @nitra/eslint-config має бути >= %s (зараз %q) (js-lint.mdc)", [eslint_min_display, range])
61
+ msg := sprintf("package.json: @nitra/eslint-config має бути >= %s (зараз %q) (js.mdc)", [eslint_min_display, range])
62
62
  }
63
63
 
64
64
  # ── helpers ──────────────────────────────────────────────────────────────
@@ -4,5 +4,5 @@
4
4
  "single": ".vscode/extensions.json",
5
5
  "required": true
6
6
  },
7
- "missingMessage": ".vscode/extensions.json не існує — додай recommendations з js-lint.mdc"
7
+ "missingMessage": ".vscode/extensions.json не існує — додай recommendations з js.mdc"
8
8
  }
@@ -1,4 +1,4 @@
1
- # Перевірка `.vscode/extensions.json` для js-lint (js-lint.mdc).
1
+ # Перевірка `.vscode/extensions.json` для js (js.mdc).
2
2
  #
3
3
  # Канон надходить через --data: { "template": { "snippet": ... } }
4
4
  package js_lint.vscode_extensions
@@ -8,5 +8,5 @@ import rego.v1
8
8
  deny contains msg if {
9
9
  some rec in data.template.snippet.recommendations
10
10
  not rec in {r | some r in object.get(input, "recommendations", [])}
11
- msg := sprintf(".vscode/extensions.json: recommendations має містити %q (js-lint.mdc)", [rec])
11
+ msg := sprintf(".vscode/extensions.json: recommendations має містити %q (js.mdc)", [rec])
12
12
  }
@@ -29,7 +29,7 @@ docgen:
29
29
 
30
30
  ## Експорти / API
31
31
 
32
- Модуль експортує тільки named-exports (узгоджено з `n-js-lint` / `js-run.mdc`):
32
+ Модуль експортує тільки named-exports (узгоджено з `n-js` / `js-run.mdc`):
33
33
 
34
34
  | Експорт | Тип | Призначення |
35
35
  | -------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------- |
@@ -3,28 +3,38 @@ type: JS Module
3
3
  title: header_doc_pointer.mjs
4
4
  resource: npm/rules/npm-module/js/header_doc_pointer.mjs
5
5
  docgen:
6
- crc: d96a2957
6
+ crc: 90fc46dc
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
7
8
  score: 100
8
9
  ---
9
10
 
10
- Файл виконує перевірку документації для модулів. Сканує директорії npm/rules та npm/skills. Перевіряє наявність файлів docs/<stem>.md у піддиректоріях правил/скілів. Перевіряє, чи містить відповідні js-файли не більше одного рядка JSDoc. У разі перевищення ліміту, генерує звіт про порушення.
11
+ ## Огляд
12
+
13
+ Модуль валідує відповідність контракту документації для файлів `.mjs` у сегментах `npm/rules` та `npm/skills`. Він виявляє порушення, якщо для файлу `.mjs` існує відповідний файл `docs/<ім'я>.md`, а його JSDoc-блок містить більше одного непорожнього рядка.
11
14
 
12
15
  ## Поведінка
13
16
 
14
- 1. Сканувати директорії npm/rules та npm/skills.
15
- 2. Для кожної директорії перевіряти піддиректорії правил/скілів.
16
- 3. Для кожного знайденого js-файлу перевіряти наявність файлу docs/<stem>.md.
17
- 4. Якщо файл docs/<stem>.md існує, перевіряти, чи містить module-level JSDoc не більше одного непорожного рядка.
18
- 5. У разі перевищення ліміту, зарепортувати порушення.
19
- 6. Повертати код виходу репортера.
17
+ 1. Викликається функція check з корінням репозиторію як аргументом.
18
+ 2. Ініціалізується репортер для фіксації порушень.
19
+ 3. Для кожного з сегментів 'npm/rules' та 'npm/skills' виконується наступне:
20
+ а. Перевіряється існування відповідного базового сегмента.
21
+ б. Для кожного підсегмента (правила/скіла) у базовому сегменті:
22
+ i. Перевіряється існування каталогу `js/` у підсегменті.
23
+ ii. Для кожного файлу `.mjs` у каталозі `js/`:
24
+ а. Перевіряється, чи є файл звичайним вихідним файлом (не тест).
25
+ б. Визначається ім'я без розширення файлу.
26
+ в. Перевіряється існування файлу `docs/<ім'я>.md` у каталозі `js/docs/`.
27
+ г. Якщо файл `docs/<ім'я>.md` існує:
28
+ i. Зчитується вміст файлу `.mjs`.
29
+ ii. Визначається перша не-жадібна JSDoc-блока в файлі.
30
+ iii. Підраховується кількість непорожніх рядків у тілі цього JSDoc-блока.
31
+ iv. Якщо кількість непорожніх рядків перевищує 1, фіксується порушення, оскільки `docs/<ім'я>.md` вже описує поведінку, а JSDoc має бути лише вказівником.
32
+ 4. Повертається код виходу репортера.
20
33
 
21
34
  ## Публічний API
22
35
 
23
- - check — сканує файли `npm/rules/*/js/*.mjs` та `npm/skills/*/js/*.mjs`.
24
- - Якщо існує `docs/<stem>.md`, модуль повинен мати посилання на JSDoc (не наратив).
25
- - Якщо `docs` відсутній, обмеження не застосовуються.
36
+ check — перевіряє файли `.mjs` у директоріях `npm/rules/*\/js/` та `npm/skills/*\/js/`. Якщо поруч є відповідний файл `docs/<stem>.md`, вимагає, щоб JSDoc на рівні модуля був посиланням (не описом); якщо `docs` відсутній, обмежень немає.
26
37
 
27
38
  ## Гарантії поведінки
28
39
 
29
- - Read-only: файл не виконує операцій запису у файлову систему.
30
- - Не звертається до мережі.
40
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -3,28 +3,28 @@ type: JS Module
3
3
  title: main.mjs
4
4
  resource: npm/rules/python/main.mjs
5
5
  docgen:
6
- crc: 8ceba96a
6
+ crc: d8a3aa1f
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 90
9
9
  ---
10
10
 
11
11
  ## Огляд
12
12
 
13
- Виконує логіку `lint-python` за правилом `python.mdc` для забезпечення якості коду Python. Якщо файл `pyproject.toml` відсутній у корені, виконання завершується з кодом 0. Якщо файл присутній, але `uv` не знайдено у системному шляху, це вважається помилкою, оскільки `uv` є єдиним дозволеним пакет-менеджером (без Poetry). Для роботи необхідно виконати `uv lock --check` для підтвердження актуальності файлу блокування та `uv sync --frozen` для створення середовища, що відповідає `uv.lock` (детальніше про `uv` на https://docs.astral.sh/uv/). Опціональні лінтери запускаються лише за умови їх доступності через `uv run`. Запускаються `ruff` у режимі автоматичного виправлення (`--fix`) та форматування, а також `mypy` для статичного аналізу коду, використовуючи канонічний патерн серіалізації через `runStandardLint`.
13
+ Реалізує логіку запуску `lint-python` за правилом `python.mdc` на базі [uv](https://docs.astral.sh/uv/). Якщо `pyproject.toml` у корені відсутній, процес завершується з кодом виходу 0. Якщо файл присутній, але інструмент `uv` не знайдено в PATH, це розглядається як помилка. Обов'язкові кроки включають перевірку актуальності lock-файлу (`uv lock --check`) та синхронізацію середовища (`uv sync --frozen`). Опційні лінтери (`ruff`, `mypy`) запускаються лише за умови їх доступності через `uv run`. `ruff` виконується у режимі автоматичного виправлення (`--fix`) для мутації робочого дерева та для форматування. Цей підхід відповідає канону патерну `lint-*` (серіалізація через `runStandardLint`, без прямого `withLock`).
14
14
 
15
15
  ## Поведінка
16
16
 
17
- run виконує стандартну перевірку на основі контексту.
18
- runLintPythonSteps виконує послідовність кроків лінтування Python, включаючи перевірку `pyproject.toml`, виконання `uv lock --check` та `uv sync --frozen`, а також запуск опціональних лінтерів (`ruff`, `mypy`) через `uv run`.
19
- runLintPython запускає послідовність кроків лінтування Python, використовуючи механізм стандартного лінтування.
20
- lint оркеструє запуск `runLintPython` для аналізу всього проєкту.
17
+ run виконує стандартну перевірку для правила, використовуючи контекст прогону.
18
+ runLintPythonSteps виконує послідовність кроків лінтування Python, перевіряючи наявність `pyproject.toml` та виконуючи команди `uv lock --check` та `uv sync --frozen`, а також запускаючи опціональні лінтери (`ruff`, `mypy`) через `uv run` на базі https://docs.astral.sh/uv/.
19
+ runLintPython запускає послідовність кроків лінтування Python, серіалізуючи її через стандартний механізм перевірки.
20
+ lint делегує виклик до `runLintPython`, забезпечуючи можливість запуску в режимі, що не мутує робоче дерево.
21
21
 
22
22
  ## Публічний API
23
23
 
24
- run — Основна точка входу для виконання правил, що включає перевірку логіки застосування (JS-concerns policy mdc-refs) та виконання лінтингу.
25
- runLintPythonSteps — Виконує внутрішні етапи лінтингу для Python без збереження логів.
26
- runLintPython — Публічний інтерфейс для запуску лінтингу Python, що забезпечує унікальність виконання через блокування та аналіз стану репозиторію.
27
- lint — Координатор, який ініціює запуск лінтингу Python, делегуючи це `runLintPython`.
24
+ run — Основна точка входу для виконання правил, яка перевіряє логіку застосування (JS-занепокложення $\rightarrow$ політика $\rightarrow$ mdc-посилання) та запускає перевірку коду (uv/ruff/mypy).
25
+ runLintPythonSteps — Виконує внутрішні етапи перевірки Python-коду без збереження логу.
26
+ runLintPython — Публічний інтерфейс для запуску перевірки Python-коду, який гарантує унікальність виконання через блокування та аналіз стану Git-дерева.
27
+ lint — Адаптер, що керує запуском перевірки Python-коду, делегуючи цю роботу `runLintPython`.
28
28
 
29
29
  ## Гарантії поведінки
30
30
 
@@ -3,24 +3,24 @@ type: JS Module
3
3
  title: main.mjs
4
4
  resource: npm/rules/rust/main.mjs
5
5
  docgen:
6
- crc: a3060168
6
+ crc: 93c44fd7
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 90
8
+ score: 100
9
9
  ---
10
10
 
11
11
  ## Огляд
12
12
 
13
- Модуль надає функції для роботи з кодом Rust. Функція `run` виконує повний аналіз коду, включаючи перевірку відповідності політиці MDC. Функція `lint` здійснює статичний аналіз коду. Обидві функції можуть ініціювати форматування та аналіз за допомогою `cargo`.
13
+ Модуль надає інструменти для забезпечення якості коду Rust. Він дозволяє виконати перевірку коду на відповідність заданим Lint-правилам або запустити повну оркестрацію форматування та аналізу коду через `cargo`. Функціонал реалізується через публічні функції `run` та `lint`.
14
14
 
15
15
  ## Поведінка
16
16
 
17
- run виконує перевірку коду Rust, застосовуючи політику та посилання MDC.
18
- lint запускає оркестрацію перевірки Rust, виконуючи `rustfmt` та `clippy` через `cargo`.
17
+ run виконує перевірку коду Rust відповідно до політик.
18
+ lint запускає оркестрацію перевірки коду Rust, використовуючи `cargo` для виконання `rustfmt` та `clippy`.
19
19
 
20
20
  ## Публічний API
21
21
 
22
- run — точка входу для виконання правила, що перевіряє логіку, пов'язану з JS-зацікавленостями, політикою та посиланнями MDC.
23
- lint — точка входу для запуску лінтера Rust-коду.
22
+ run — виконує основну логіку правила, включаючи перевірку аспектів застосування, логіки та посилань.
23
+ lint — забезпечує точку входу для статичного аналізу коду Rust.
24
24
 
25
25
  ## Гарантії поведінки
26
26
 
@@ -6,7 +6,7 @@ import { join } from 'node:path'
6
6
  import { createCheckReporter } from '../../../scripts/lib/check-reporter.mjs'
7
7
 
8
8
  // Зовнішні файли конфігу stylelint, які підхоплює cosmiconfig. Канон нових
9
- // JS-конфігів — `.mjs`/`.cjs` (js-lint.mdc), legacy `.js` лишається валідним.
9
+ // JS-конфігів — `.mjs`/`.cjs` (js.mdc), legacy `.js` лишається валідним.
10
10
  const STYLELINT_CONFIG_FILES = [
11
11
  '.stylelintrc.json',
12
12
  '.stylelintrc.js',
@@ -11,7 +11,7 @@ docgen:
11
11
 
12
12
  ## Поведінка
13
13
 
14
- 1. Перевірити наявність `js-lint` у конфігурації.
14
+ 1. Перевірити наявність `js` у конфігурації.
15
15
  2. Зібрати кореневі пакети.
16
16
  3. Перевірити наявність базових конфігурацій.
17
17
  4. Перевірити наявність базлайн-файлів.