@nitra/cursor 1.13.83 → 1.13.84

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 (91) hide show
  1. package/.claude-template/commands/n-check.md +2 -2
  2. package/CHANGELOG.md +41 -27
  3. package/README.md +10 -10
  4. package/bin/n-cursor.js +34 -58
  5. package/package.json +1 -1
  6. package/rules/abie/abie.mdc +2 -2
  7. package/rules/abie/fix.mjs +5 -1
  8. package/rules/adr/fix.mjs +5 -1
  9. package/rules/adr/js/hooks/check.mjs +1 -1
  10. package/rules/bun/bun.mdc +1 -1
  11. package/rules/bun/fix.mjs +5 -1
  12. package/rules/bun/js/layout/check.mjs +1 -1
  13. package/rules/capacitor/fix.mjs +5 -1
  14. package/rules/capacitor/policy/package_json/package_json.rego +3 -3
  15. package/rules/changelog/changelog.mdc +1 -1
  16. package/rules/changelog/fix.mjs +5 -1
  17. package/rules/ci4/ci4.mdc +1 -1
  18. package/rules/ci4/fix.mjs +5 -1
  19. package/rules/docker/docker.mdc +6 -6
  20. package/rules/docker/fix.mjs +5 -1
  21. package/rules/docker/policy/package_json/package_json.rego +1 -1
  22. package/rules/efes/efes.mdc +1 -1
  23. package/rules/efes/fix.mjs +5 -1
  24. package/rules/feedback/feedback.mdc +2 -2
  25. package/rules/feedback/fix.mjs +5 -1
  26. package/rules/ga/fix.mjs +5 -1
  27. package/rules/ga/lint/lint.mjs +5 -5
  28. package/rules/ga/policy/workflow_common/workflow_common.rego +1 -1
  29. package/rules/graphql/fix.mjs +5 -1
  30. package/rules/graphql/policy/vscode_extensions/vscode_extensions.rego +2 -2
  31. package/rules/hasura/fix.mjs +5 -1
  32. package/rules/image-avif/fix.mjs +5 -1
  33. package/rules/image-avif/image-avif.mdc +1 -1
  34. package/rules/image-avif/js/avif_generation/check.mjs +1 -1
  35. package/rules/image-compress/fix.mjs +5 -1
  36. package/rules/image-compress/js/package_setup/check.mjs +1 -1
  37. package/rules/js-bun-db/fix.mjs +5 -1
  38. package/rules/js-bun-redis/fix.mjs +5 -1
  39. package/rules/js-lint/fix.mjs +5 -1
  40. package/rules/js-lint/js/tooling/check.mjs +2 -2
  41. package/rules/js-lint/js-lint.mdc +1 -1
  42. package/rules/js-mssql/fix.mjs +5 -1
  43. package/rules/js-mssql/policy/package_json/package_json.rego +2 -2
  44. package/rules/js-run/fix.mjs +5 -1
  45. package/rules/js-run/js/runtime/check.mjs +3 -3
  46. package/rules/k8s/fix.mjs +5 -1
  47. package/rules/k8s/js/manifests/check.mjs +1 -1
  48. package/rules/k8s/k8s.mdc +12 -12
  49. package/rules/k8s/lint/lint.mjs +2 -2
  50. package/rules/k8s/policy/base_kustomization/base_kustomization.rego +3 -3
  51. package/rules/k8s/policy/base_manifest/base_manifest.rego +2 -2
  52. package/rules/k8s/policy/gateway/gateway.rego +2 -2
  53. package/rules/k8s/policy/hasura_configmap/hasura_configmap.rego +3 -3
  54. package/rules/k8s/policy/hasura_httproute/hasura_httproute.rego +1 -1
  55. package/rules/k8s/policy/hpa_pdb/hpa_pdb.rego +1 -1
  56. package/rules/k8s/policy/kustomization/kustomization.rego +2 -2
  57. package/rules/k8s/policy/manifest/manifest.rego +4 -4
  58. package/rules/k8s/policy/svc_hl_yaml/svc_hl_yaml.rego +2 -2
  59. package/rules/k8s/policy/svc_yaml/svc_yaml.rego +2 -2
  60. package/rules/nginx-default-tpl/fix.mjs +5 -1
  61. package/rules/nginx-default-tpl/policy/vscode_extensions/vscode_extensions.rego +2 -2
  62. package/rules/nginx-default-tpl/policy/vscode_settings/vscode_settings.rego +1 -1
  63. package/rules/npm-module/fix.mjs +5 -1
  64. package/rules/npm-module/js/package_structure/check.mjs +2 -2
  65. package/rules/php/fix.mjs +5 -1
  66. package/rules/php/js/tooling/check.mjs +2 -2
  67. package/rules/rego/fix.mjs +5 -1
  68. package/rules/security/fix.mjs +5 -1
  69. package/rules/security/security.mdc +1 -1
  70. package/rules/style-lint/fix.mjs +5 -1
  71. package/rules/style-lint/js/tooling/check.mjs +2 -2
  72. package/rules/tauri/fix.mjs +5 -1
  73. package/rules/tauri/js/tooling/check.mjs +1 -1
  74. package/rules/tauri/policy/vscode_extensions/vscode_extensions.rego +2 -2
  75. package/rules/test/fix.mjs +5 -1
  76. package/rules/test/test.mdc +1 -1
  77. package/rules/text/fix.mjs +5 -1
  78. package/rules/text/js/formatting/check.mjs +2 -2
  79. package/rules/text/text.mdc +1 -1
  80. package/rules/vue/fix.mjs +5 -1
  81. package/rules/vue/js/packages/check.mjs +1 -1
  82. package/rules/vue/policy/package_json/package_json.rego +1 -1
  83. package/rules/vue/vue.mdc +1 -1
  84. package/schemas/n-cursor.json +1 -1
  85. package/scripts/build-agents-commands.mjs +1 -1
  86. package/scripts/claude-stop-hook.mjs +1 -1
  87. package/scripts/utils/discover-check-rules-from-cursor.mjs +1 -1
  88. package/scripts/utils/read-n-cursor-config-lite.mjs +59 -0
  89. package/scripts/utils/run-rule-cli.mjs +37 -0
  90. package/skills/fix/SKILL.md +5 -5
  91. package/skills/lint/SKILL.md +1 -1
@@ -2,6 +2,7 @@ import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
2
2
 
3
3
  /**
4
4
  * Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
5
+ * Library mode: викликається CLI orchestration через `import + run(ctx)`.
5
6
  * @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
6
7
  * @returns {Promise<number>} 0 — OK, 1 — порушення
7
8
  */
@@ -10,6 +11,9 @@ export function run(ctx) {
10
11
  }
11
12
 
12
13
  if (import.meta.main) {
14
+ // Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
15
+ // (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
16
+ const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
13
17
  // eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
14
- process.exit(await run())
18
+ process.exit(await runRuleCli(import.meta.dirname))
15
19
  }
@@ -12,7 +12,7 @@
12
12
  * 3. Інакше — для `.vscode/extensions.json` зробити FS-existence + делегувати
13
13
  * content `rego.tauri.vscode_extensions` через `runConftestBatch`.
14
14
  *
15
- * Rego-полісі глобально без `target.json` поруч (не auto-discoverable через `n-cursor check`) — це conditional
15
+ * Rego-полісі глобально без `target.json` поруч (не auto-discoverable через `n-cursor fix`) — це conditional
16
16
  * правило. Plan B: Rego-authoritative + JS-orchestrator з `runConftestBatch`.
17
17
  */
18
18
  import { existsSync, statSync } from 'node:fs'
@@ -1,9 +1,9 @@
1
1
  # Перевірка `.vscode/extensions.json` для tauri (tauri.mdc).
2
2
  #
3
- # Викликається з `check-tauri.mjs` через `runConftestBatch` лише ПІСЛЯ того,
3
+ # Викликається з `rules/tauri/fix.mjs` через `runConftestBatch` лише ПІСЛЯ того,
4
4
  # як JS виявив маркер Tauri-проєкту (`src-tauri/` каталог, `tauri.conf.json`
5
5
  # у будь-якому пакеті, або залежність `@tauri-apps/*`). Без `target.json` поруч
6
- # (не auto-discoverable через `n-cursor check`) — інакше false-positive порушення на не-Tauri проєктах.
6
+ # (не auto-discoverable через `n-cursor fix`) — інакше false-positive порушення на не-Tauri проєктах.
7
7
  #
8
8
  # Canonical (tauri.mdc): `recommendations` має містити обидва записи —
9
9
  # - tauri-apps.tauri-vscode
@@ -2,6 +2,7 @@ import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
2
2
 
3
3
  /**
4
4
  * Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
5
+ * Library mode: викликається CLI orchestration через `import + run(ctx)`.
5
6
  * @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
6
7
  * @returns {Promise<number>} 0 — OK, 1 — порушення
7
8
  */
@@ -10,6 +11,9 @@ export function run(ctx) {
10
11
  }
11
12
 
12
13
  if (import.meta.main) {
14
+ // Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
15
+ // (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
16
+ const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
13
17
  // eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
14
- process.exit(await run())
18
+ process.exit(await runRuleCli(import.meta.dirname))
15
19
  }
@@ -53,7 +53,7 @@ Recursive globs ловлять файли всередині `tests/` так с
53
53
 
54
54
  ## Що перевіряє правило
55
55
 
56
- `npx @nitra/cursor check test` (concern `location`) проходить деревом пакета й перевіряє: **кожен `*.test.mjs` файл лежить усередині каталогу з ім'ям `tests`** (точне співпадіння басенейму батьківської директорії). Файли поза цим каталогом репортуються з порадою куди їх перенести.
56
+ `npx @nitra/cursor fix test` (concern `location`) проходить деревом пакета й перевіряє: **кожен `*.test.mjs` файл лежить усередині каталогу з ім'ям `tests`** (точне співпадіння басенейму батьківської директорії). Файли поза цим каталогом репортуються з порадою куди їх перенести.
57
57
 
58
58
  `*_test.rego` перевіркою **не охоплюються** — вони не переміщуються.
59
59
 
@@ -2,6 +2,7 @@ import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
2
2
 
3
3
  /**
4
4
  * Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
5
+ * Library mode: викликається CLI orchestration через `import + run(ctx)`.
5
6
  * @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
6
7
  * @returns {Promise<number>} 0 — OK, 1 — порушення
7
8
  */
@@ -10,6 +11,9 @@ export function run(ctx) {
10
11
  }
11
12
 
12
13
  if (import.meta.main) {
14
+ // Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
15
+ // (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
16
+ const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
13
17
  // eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
14
- process.exit(await run())
18
+ process.exit(await runRuleCli(import.meta.dirname))
15
19
  }
@@ -11,7 +11,7 @@
11
11
  * - абзац про український апостроф у `.cursor/rules/n-text.mdc` /
12
12
  * `npm/mdc/text.mdc` (markdown-текст, не JSON/YAML);
13
13
  * - складна валідація скрипта `lint-text` (cspell, markdownlint, v8r у трьох
14
- * варіантах, run-shellcheck-text.mjs, обовʼязкові glob-и);
14
+ * варіантах, run-shellrules/text/fix.mjs, обовʼязкові glob-и);
15
15
  * - workflow `lint-text.yml` має крок `bun run lint-text` (структура — rego `text.lint_text`).
16
16
  *
17
17
  * **Що покрила Rego** (`npx \@nitra/cursor check`):
@@ -111,7 +111,7 @@ function checkTextConfigsExistence(passFn, failFn) {
111
111
  ['.vscode/settings.json', 'text.vscode_settings']
112
112
  ]) {
113
113
  if (existsSync(path)) {
114
- passFn(`${path} є (структуру перевіряє npx @nitra/cursor check → ${mdcRef})`)
114
+ passFn(`${path} є (структуру перевіряє npx @nitra/cursor fix → ${mdcRef})`)
115
115
  } else {
116
116
  failFn(`${path} не існує — створи згідно n-text.mdc`)
117
117
  }
@@ -260,4 +260,4 @@ kebab-case
260
260
 
261
261
  ## Перевірка
262
262
 
263
- `npx @nitra/cursor check text` (охоплює oxfmt, cspell, shellcheck у `lint-text`, markdownlint, v8r, CI для `lint-text`)
263
+ `npx @nitra/cursor fix text` (охоплює oxfmt, cspell, shellcheck у `lint-text`, markdownlint, v8r, CI для `lint-text`)
package/rules/vue/fix.mjs CHANGED
@@ -2,6 +2,7 @@ import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
2
2
 
3
3
  /**
4
4
  * Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
5
+ * Library mode: викликається CLI orchestration через `import + run(ctx)`.
5
6
  * @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
6
7
  * @returns {Promise<number>} 0 — OK, 1 — порушення
7
8
  */
@@ -10,6 +11,9 @@ export function run(ctx) {
10
11
  }
11
12
 
12
13
  if (import.meta.main) {
14
+ // Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
15
+ // (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
16
+ const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
13
17
  // eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
14
- process.exit(await run())
18
+ process.exit(await runRuleCli(import.meta.dirname))
15
19
  }
@@ -413,7 +413,7 @@ async function checkVueImportViolations(rootDir, absPackageRoot, ignorePaths, ha
413
413
  */
414
414
  async function checkVuePackage(rootDir, ignorePaths, fail, passFn) {
415
415
  const prefix = `[${packageLabel(rootDir)}] `
416
- passFn(`${prefix}package.json залежності перевіряє npx @nitra/cursor check → vue.package_json`)
416
+ passFn(`${prefix}package.json залежності перевіряє npx @nitra/cursor fix → vue.package_json`)
417
417
 
418
418
  await checkViteClientEnvAndEditorConfig(rootDir, prefix, passFn, fail)
419
419
 
@@ -1,5 +1,5 @@
1
1
  # Порт перевірки версій з `package.json` для Vue+Vite пакетів з
2
- # `npm/scripts/check-vue.mjs` (vue.mdc).
2
+ # `npm/scripts/rules/vue/fix.mjs` (vue.mdc).
3
3
  #
4
4
  # Запуск (локально, у Vue+Vite-пакеті):
5
5
  # conftest test path/to/package.json -p npm/policy/vue \
package/rules/vue/vue.mdc CHANGED
@@ -341,4 +341,4 @@ import path from 'node:path'
341
341
 
342
342
  ## Перевірка
343
343
 
344
- `npx @nitra/cursor check vue` — перевіряє залежності, `vite.config`, наявність **`src/vite-env.d.ts`** з `/// <reference types="vite/client" />` та **`jsconfig.json`** у корені Vue-пакета; обходить джерела Vue-пакета (`.vue`, `.ts`, `.js` тощо) на заборонені value-імпорти з модуля `vue` (дозволені лише type-only та side-effect `import 'vue'`) і додатково сканує `.vue` SFC на імпорти Node-нативних модулів (`node:*` префікс або bare-ім’я вбудованого модуля Node — `fs`, `path`, `timers/promises` тощо). Імпорти аналізуються через **oxc-parser** (`module.staticImports`); для `.vue` вміст `<script>` витягується з SFC, далі той самий парсер (логіка в `npm/rules/vue/js/packages/vue-forbidden-imports.mjs`).
344
+ `npx @nitra/cursor fix vue` — перевіряє залежності, `vite.config`, наявність **`src/vite-env.d.ts`** з `/// <reference types="vite/client" />` та **`jsconfig.json`** у корені Vue-пакета; обходить джерела Vue-пакета (`.vue`, `.ts`, `.js` тощо) на заборонені value-імпорти з модуля `vue` (дозволені лише type-only та side-effect `import 'vue'`) і додатково сканує `.vue` SFC на імпорти Node-нативних модулів (`node:*` префікс або bare-ім’я вбудованого модуля Node — `fs`, `path`, `timers/promises` тощо). Імпорти аналізуються через **oxc-parser** (`module.staticImports`); для `.vue` вміст `<script>` витягується з SFC, далі той самий парсер (логіка в `npm/rules/vue/js/packages/vue-forbidden-imports.mjs`).
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "ignore": {
47
47
  "type": "array",
48
- "description": "Директорії, що повністю виключаються з обходу check-скриптів CLI (npx @nitra/cursor check ...) і AI-модифікацій (AI не редагує, не видаляє, не створює файли). Шляхи відносно кореня репозиторію (posix). Приклади: vendored Helm-чарти, генеровані маніфести, legacy-дерева. Стандартні виключення (node_modules, .git, dist, coverage, .turbo, .next) застосовуються завжди — додавати їх не треба.",
48
+ "description": "Директорії, що повністю виключаються з обходу check-скриптів CLI (npx @nitra/cursor fix ...) і AI-модифікацій (AI не редагує, не видаляє, не створює файли). Шляхи відносно кореня репозиторію (posix). Приклади: vendored Helm-чарти, генеровані маніфести, legacy-дерева. Стандартні виключення (node_modules, .git, dist, coverage, .turbo, .next) застосовуються завжди — додавати їх не треба.",
49
49
  "items": {
50
50
  "type": "string",
51
51
  "minLength": 1
@@ -81,7 +81,7 @@ export async function buildAgentsCommandBulletItems(projectRoot) {
81
81
  {
82
82
  name: `- **Оновити правила та ${AGENTS_MD}** (після змін у правилах/шаблоні CLI): \`npx ${PACKAGE_NAME}\``
83
83
  },
84
- { name: `- **Перевірки правил (programmatic)**: \`npx ${PACKAGE_NAME} check\`` },
84
+ { name: `- **Перевірки правил (programmatic)**: \`npx ${PACKAGE_NAME} fix\`` },
85
85
  { name: `- **knip (невикористані залежності та експорти)**: \`bunx knip\`` }
86
86
  )
87
87
 
@@ -68,7 +68,7 @@ export async function runStopHookCli() {
68
68
  const [code] = await once(child, 'exit')
69
69
  return code ?? 1
70
70
  } catch (error) {
71
- process.stderr.write(`stop-hook: не вдалося запустити npx @nitra/cursor check — ${error.message}\n`)
71
+ process.stderr.write(`stop-hook: не вдалося запустити npx @nitra/cursor fix — ${error.message}\n`)
72
72
  return 1
73
73
  }
74
74
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Визначає список id правил для `npx @nitra/cursor check` без аргументів:
2
+ * Визначає список id правил для `npx @nitra/cursor fix` без аргументів:
3
3
  * зчитує базові імена `*.mdc` у `.cursor/rules/` і залишає лише ті id,
4
4
  * для яких у пакеті є programmatic перевірка (JS-концерн або policy з target.json).
5
5
  */
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Light read-only `.n-cursor.json` reader для standalone `fix.mjs` invocation.
3
+ *
4
+ * НЕ робить auto-rules detection, merge, schema sync — це справа повного `readConfig` у CLI.
5
+ * Тут лише: прочитати файл (якщо є), повернути `{ rules: string[], disableRules: string[] }`.
6
+ *
7
+ * Спостереження whitelist:
8
+ * - якщо `.n-cursor.json` НЕМАЄ → правило вважається enabled (поведінка "open by default"),
9
+ * щоб `bun rules/<id>/fix.mjs` з будь-якої тимчасової директорії працювало для debug.
10
+ * - якщо файл є з `rules:[…]`, але правила там немає → правило не enabled.
11
+ * - якщо правило в `disable-rules` → не enabled, навіть якщо у `rules:[…]`.
12
+ */
13
+ import { existsSync } from 'node:fs'
14
+ import { readFile } from 'node:fs/promises'
15
+ import { join } from 'node:path'
16
+
17
+ const CONFIG_FILE = '.n-cursor.json'
18
+
19
+ /**
20
+ * @typedef {object} LiteConfig
21
+ * @property {boolean} exists чи існує .n-cursor.json у поточному каталозі
22
+ * @property {string[]} rules id правил з whitelist (порожній якщо файл відсутній)
23
+ * @property {string[]} disableRules id правил, явно вимкнених у `disable-rules`
24
+ */
25
+
26
+ /**
27
+ * @param {string} [cwd] корінь, у якому шукати .n-cursor.json (default — `process.cwd()`)
28
+ * @returns {Promise<LiteConfig>} стан конфігу
29
+ */
30
+ export async function readNCursorConfigLite(cwd = process.cwd()) {
31
+ const configPath = join(cwd, CONFIG_FILE)
32
+ if (!existsSync(configPath)) {
33
+ return { exists: false, rules: [], disableRules: [] }
34
+ }
35
+ const raw = await readFile(configPath, 'utf8')
36
+ /** @type {{ rules?: unknown, ['disable-rules']?: unknown }} */
37
+ const parsed = JSON.parse(raw)
38
+ const rules = Array.isArray(parsed.rules) ? parsed.rules.filter(r => typeof r === 'string') : []
39
+ const disableRules = Array.isArray(parsed['disable-rules'])
40
+ ? parsed['disable-rules'].filter(r => typeof r === 'string')
41
+ : []
42
+ return { exists: true, rules, disableRules }
43
+ }
44
+
45
+ /**
46
+ * Чи активне правило згідно з конфігом.
47
+ * - файл відсутній → true (open by default для debug);
48
+ * - правило явно в `disable-rules` → false;
49
+ * - правило у `rules` → true;
50
+ * - інакше → false.
51
+ * @param {LiteConfig} config розпарсений lite-конфіг
52
+ * @param {string} ruleId id правила (= basename каталогу)
53
+ * @returns {boolean} чи запускати правило
54
+ */
55
+ export function isRuleEnabled(config, ruleId) {
56
+ if (!config.exists) return true
57
+ if (config.disableRules.includes(ruleId)) return false
58
+ return config.rules.includes(ruleId)
59
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Standalone CLI runner для одного правила. Викликається з `rules/<id>/fix.mjs`
3
+ * у блоці `if (import.meta.main)` — це робить `bun rules/<id>/fix.mjs` повним
4
+ * еквівалентом старого `npx @nitra/cursor fix <id>`: читає `.n-cursor.json`,
5
+ * перевіряє whitelist, друкує summary, повертає aggregated exit-code.
6
+ *
7
+ * Library-mode виклик з CLI orchestration — інше: див. `runStandardRule` + `fix.mjs::run(ctx)`.
8
+ */
9
+ import { basename } from 'node:path'
10
+
11
+ import { isRuleEnabled, readNCursorConfigLite } from './read-n-cursor-config-lite.mjs'
12
+ import { runStandardRule } from './run-standard-rule.mjs'
13
+ import { getOrCreateWalkCache } from './walk-cache.mjs'
14
+
15
+ const PACKAGE_NAME = '@nitra/cursor'
16
+
17
+ /**
18
+ * @param {string} ruleDir абсолютний шлях до `rules/<id>/`
19
+ * @returns {Promise<number>} 0 — OK або правило не enabled; 1 — порушення
20
+ */
21
+ export async function runRuleCli(ruleDir) {
22
+ const ruleId = basename(ruleDir)
23
+ const config = await readNCursorConfigLite()
24
+
25
+ if (!isRuleEnabled(config, ruleId)) {
26
+ console.log(`\n🔍 ${PACKAGE_NAME} fix ${ruleId} — правило не в \`.n-cursor.json:rules\`. Пропущено.\n`)
27
+ return 0
28
+ }
29
+
30
+ console.log(`\n🔍 ${PACKAGE_NAME} fix ${ruleId} — перевірка правила\n`)
31
+
32
+ const walkCache = getOrCreateWalkCache()
33
+ const exitCode = await runStandardRule(ruleDir, { walkCache })
34
+ const ok = exitCode === 0
35
+ console.log(`\n✨ Результат: ${ok ? 1 : 0}/1 правил без зауважень\n`)
36
+ return exitCode
37
+ }
@@ -8,14 +8,14 @@ description: >-
8
8
 
9
9
  ## Scope
10
10
 
11
- Цей скіл відповідає **лише за структуру** проєкту: щоб `.cursor/rules/` + `npx @nitra/cursor check` були задоволені (наявність конфігів, залежностей, скриптів, GitHub workflows, відсутність заборонених файлів). **Лінт-порушення у самому коді** (ESLint, oxlint, jscpd, cspell, knip, sonarjs, stylelint тощо) — **поза скоупом**; їх діагностує й виправляє **`/n-lint`** (`bun run lint`). Не запускай `bun run lint` із цього скілу і не намагайся виправляти його порушення тут — це задача `/n-lint`. Якщо `npx @nitra/cursor check` чистий, а `bun run lint` лишився червоним — запусти `/n-lint` окремо.
11
+ Цей скіл відповідає **лише за структуру** проєкту: щоб `.cursor/rules/` + `npx @nitra/cursor fix` були задоволені (наявність конфігів, залежностей, скриптів, GitHub workflows, відсутність заборонених файлів). **Лінт-порушення у самому коді** (ESLint, oxlint, jscpd, cspell, knip, sonarjs, stylelint тощо) — **поза скоупом**; їх діагностує й виправляє **`/n-lint`** (`bun run lint`). Не запускай `bun run lint` із цього скілу і не намагайся виправляти його порушення тут — це задача `/n-lint`. Якщо `npx @nitra/cursor fix` чистий, а `bun run lint` лишився червоним — запусти `/n-lint` окремо.
12
12
 
13
13
  ## Workflow
14
14
 
15
- 1. **Діагностика** — запусти перевірку (за замовчуванням лише правила з `.cursor/rules/*.mdc`, для яких у пакеті є programmatic check; повний набір — явні аргументи: `npx @nitra/cursor check bun ga …`):
15
+ 1. **Діагностика** — запусти перевірку (за замовчуванням лише правила з `.cursor/rules/*.mdc`, для яких у пакеті є programmatic check; повний набір — явні аргументи: `npx @nitra/cursor fix bun ga …`):
16
16
 
17
17
  ```bash
18
- npx @nitra/cursor check
18
+ npx @nitra/cursor fix
19
19
  ```
20
20
 
21
21
  2. **Аналіз** — зчитай вивід, знайди всі `❌` та визнач які правила порушено
@@ -43,7 +43,7 @@ oxfmt .
43
43
  6. **Верифікація** — перевір що все виправлено:
44
44
 
45
45
  ```bash
46
- npx @nitra/cursor check
46
+ npx @nitra/cursor fix
47
47
  ```
48
48
 
49
- 7. **Результат** — всі `❌` від `npx @nitra/cursor check` мають стати `✅`. Якщо залишились `❌` — повтори кроки 3-6. Лінт-помилки від `bun run lint` тут **не виправляй** — вони на скіл `/n-lint`.
49
+ 7. **Результат** — всі `❌` від `npx @nitra/cursor fix` мають стати `✅`. Якщо залишились `❌` — повтори кроки 3-6. Лінт-помилки від `bun run lint` тут **не виправляй** — вони на скіл `/n-lint`.
@@ -114,4 +114,4 @@ bun run lint
114
114
 
115
115
  ## Примітка
116
116
 
117
- Цей скіл **не** замінює **`npx @nitra/cursor check`**: **`lint`** перевіряє лінтери/формат у **`package.json`**, а **`check`** — програмні правила пакета **`@nitra/cursor`**. За потреби запускай обидва.
117
+ Цей скіл **не** замінює **`npx @nitra/cursor fix`**: **`lint`** перевіряє лінтери/формат у **`package.json`**, а **`check`** — програмні правила пакета **`@nitra/cursor`**. За потреби запускай обидва.