@nitra/cursor 1.13.83 → 1.13.85

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 (96) hide show
  1. package/.claude-template/commands/n-check.md +2 -2
  2. package/CHANGELOG.md +56 -27
  3. package/README.md +10 -10
  4. package/bin/n-cursor.js +40 -60
  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/lint/lint.mjs +10 -3
  22. package/rules/docker/policy/package_json/package_json.rego +1 -1
  23. package/rules/efes/efes.mdc +1 -1
  24. package/rules/efes/fix.mjs +5 -1
  25. package/rules/feedback/feedback.mdc +2 -2
  26. package/rules/feedback/fix.mjs +5 -1
  27. package/rules/ga/fix.mjs +5 -1
  28. package/rules/ga/lint/lint.mjs +5 -5
  29. package/rules/ga/policy/workflow_common/workflow_common.rego +1 -1
  30. package/rules/graphql/fix.mjs +5 -1
  31. package/rules/graphql/policy/vscode_extensions/vscode_extensions.rego +2 -2
  32. package/rules/hasura/fix.mjs +5 -1
  33. package/rules/image-avif/fix.mjs +5 -1
  34. package/rules/image-avif/image-avif.mdc +1 -1
  35. package/rules/image-avif/js/avif_generation/check.mjs +1 -1
  36. package/rules/image-compress/fix.mjs +5 -1
  37. package/rules/image-compress/js/package_setup/check.mjs +1 -1
  38. package/rules/js-bun-db/fix.mjs +5 -1
  39. package/rules/js-bun-redis/fix.mjs +5 -1
  40. package/rules/js-lint/fix.mjs +5 -1
  41. package/rules/js-lint/js/tooling/check.mjs +2 -2
  42. package/rules/js-lint/js-lint.mdc +1 -1
  43. package/rules/js-mssql/fix.mjs +5 -1
  44. package/rules/js-mssql/policy/package_json/package_json.rego +2 -2
  45. package/rules/js-run/fix.mjs +5 -1
  46. package/rules/js-run/js/runtime/check.mjs +3 -3
  47. package/rules/k8s/fix.mjs +5 -1
  48. package/rules/k8s/js/manifests/check.mjs +1 -1
  49. package/rules/k8s/k8s.mdc +12 -12
  50. package/rules/k8s/lint/lint.mjs +12 -5
  51. package/rules/k8s/policy/base_kustomization/base_kustomization.rego +3 -3
  52. package/rules/k8s/policy/base_manifest/base_manifest.rego +2 -2
  53. package/rules/k8s/policy/gateway/gateway.rego +2 -2
  54. package/rules/k8s/policy/hasura_configmap/hasura_configmap.rego +3 -3
  55. package/rules/k8s/policy/hasura_httproute/hasura_httproute.rego +1 -1
  56. package/rules/k8s/policy/hpa_pdb/hpa_pdb.rego +1 -1
  57. package/rules/k8s/policy/kustomization/kustomization.rego +2 -2
  58. package/rules/k8s/policy/manifest/manifest.rego +4 -4
  59. package/rules/k8s/policy/svc_hl_yaml/svc_hl_yaml.rego +2 -2
  60. package/rules/k8s/policy/svc_yaml/svc_yaml.rego +2 -2
  61. package/rules/nginx-default-tpl/fix.mjs +5 -1
  62. package/rules/nginx-default-tpl/policy/vscode_extensions/vscode_extensions.rego +2 -2
  63. package/rules/nginx-default-tpl/policy/vscode_settings/vscode_settings.rego +1 -1
  64. package/rules/npm-module/fix.mjs +5 -1
  65. package/rules/npm-module/js/package_structure/check.mjs +2 -2
  66. package/rules/php/fix.mjs +5 -1
  67. package/rules/php/js/tooling/check.mjs +2 -2
  68. package/rules/rego/fix.mjs +5 -1
  69. package/rules/rego/lint/lint.mjs +12 -2
  70. package/rules/security/fix.mjs +5 -1
  71. package/rules/security/security.mdc +1 -1
  72. package/rules/style-lint/fix.mjs +5 -1
  73. package/rules/style-lint/js/tooling/check.mjs +2 -2
  74. package/rules/tauri/fix.mjs +5 -1
  75. package/rules/tauri/js/tooling/check.mjs +1 -1
  76. package/rules/tauri/policy/vscode_extensions/vscode_extensions.rego +2 -2
  77. package/rules/test/fix.mjs +5 -1
  78. package/rules/test/test.mdc +1 -1
  79. package/rules/text/fix.mjs +5 -1
  80. package/rules/text/js/formatting/check.mjs +2 -2
  81. package/rules/text/lint/lint.mjs +9 -2
  82. package/rules/text/text.mdc +1 -1
  83. package/rules/vue/fix.mjs +5 -1
  84. package/rules/vue/js/packages/check.mjs +1 -1
  85. package/rules/vue/policy/package_json/package_json.rego +1 -1
  86. package/rules/vue/vue.mdc +1 -1
  87. package/schemas/n-cursor.json +1 -1
  88. package/scripts/build-agents-commands.mjs +1 -1
  89. package/scripts/claude-stop-hook.mjs +1 -1
  90. package/scripts/utils/discover-check-rules-from-cursor.mjs +1 -1
  91. package/scripts/utils/read-n-cursor-config-lite.mjs +59 -0
  92. package/scripts/utils/run-rule-cli.mjs +37 -0
  93. package/scripts/utils/run-standard-rule.mjs +12 -3
  94. package/scripts/utils/with-lock.mjs +2 -2
  95. package/skills/fix/SKILL.md +5 -5
  96. 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
  }
package/rules/adr/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
  }
@@ -116,7 +116,7 @@ async function checkHookScript(reporter, scriptName) {
116
116
  function checkProjectSettings(reporter) {
117
117
  const { pass, fail } = reporter
118
118
  if (existsSync(PROJECT_SETTINGS_PATH)) {
119
- pass(`${PROJECT_SETTINGS_PATH} є (Stop-hook перевіряє npx @nitra/cursor check → adr.settings_json)`)
119
+ pass(`${PROJECT_SETTINGS_PATH} є (Stop-hook перевіряє npx @nitra/cursor fix → adr.settings_json)`)
120
120
  } else {
121
121
  fail(`${PROJECT_SETTINGS_PATH} не існує — запусти \`npx @nitra/cursor\``)
122
122
  }
package/rules/bun/bun.mdc CHANGED
@@ -72,4 +72,4 @@ FROM oven/bun:alpine AS build-env
72
72
 
73
73
  Якщо в **`.n-cursor.json`** у масиві **`rules`** є **`docker`**, у кореневому `package.json` **обов'язково** скрипт **`lint-docker`** (див. **`docker.mdc`**) і рядок **`bun run lint-docker`** у **`lint`**. Якщо є **`k8s`** — **обов'язково** **`lint-k8s`** і **`bun run lint-k8s`** у **`lint`** (див. **`k8s.mdc`**).
74
74
 
75
- **Зворотній інваріант:** якщо правила **немає** в `rules` (або воно явно перенесене в **`disable-rules`**), скрипту **`lint-<id>`** у кореневому `package.json` бути **не може**, і ланцюжок агрегованого **`scripts.lint`** не має містити **`bun run lint-<id>`**. Інакше `bun run lint` падатиме на вимкненому правилі — `n-cursor lint-<id>` ігнорує `.n-cursor.json` і обходить дерево незалежно від `rules`/`disable-rules`. Для скриптів із кількома власниками (як **`lint-image`** — обслуговує і **`image-avif`**, і **`image-compress`**) скрипт лишається дозволеним, поки активний **хоч один** власник; зворотній інваріант тригериться лише коли в `rules` немає **жодного** з них. Перевірка — **`npx @nitra/cursor check bun`**.
75
+ **Зворотній інваріант:** якщо правила **немає** в `rules` (або воно явно перенесене в **`disable-rules`**), скрипту **`lint-<id>`** у кореневому `package.json` бути **не може**, і ланцюжок агрегованого **`scripts.lint`** не має містити **`bun run lint-<id>`**. Інакше `bun run lint` падатиме на вимкненому правилі — `n-cursor lint-<id>` ігнорує `.n-cursor.json` і обходить дерево незалежно від `rules`/`disable-rules`. Для скриптів із кількома власниками (як **`lint-image`** — обслуговує і **`image-avif`**, і **`image-compress`**) скрипт лишається дозволеним, поки активний **хоч один** власник; зворотній інваріант тригериться лише коли в `rules` немає **жодного** з них. Перевірка — **`npx @nitra/cursor fix bun`**.
package/rules/bun/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
  }
@@ -183,7 +183,7 @@ export async function check() {
183
183
  }
184
184
 
185
185
  if (existsSync('bunfig.toml')) {
186
- pass('bunfig.toml є (структуру перевіряє npx @nitra/cursor check → bun.bunfig)')
186
+ pass('bunfig.toml є (структуру перевіряє npx @nitra/cursor fix → bun.bunfig)')
187
187
  } else {
188
188
  fail('Відсутній bunfig.toml — створи з [install] linker = "hoisted" (bun.mdc)')
189
189
  }
@@ -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
  }
@@ -1,4 +1,4 @@
1
- # Порт перевірки версії `@capacitor/core` з `npm/scripts/check-capacitor.mjs`
1
+ # Порт перевірки версії `@capacitor/core` з `npm/scripts/rules/capacitor/fix.mjs`
2
2
  # (capacitor.mdc) — мінімальна мажорна версія = 8.
3
3
  #
4
4
  # Запуск (локально, у пакеті з Capacitor):
@@ -10,8 +10,8 @@
10
10
  # Підтримує `^8.0.0`, `>=8`, `8.x`, `workspace:*` тощо.
11
11
  #
12
12
  # Цей порт спрощує JS-логіку — повна семантика OR-діапазонів (`a || b`) і нижня
13
- # межа діапазону лишається в JS (`check-capacitor.mjs`: `capacitorVersionRangeMinMajor`).
14
- # JS-перевірка лишилась authoritative й бігає через `npx @nitra/cursor check capacitor`;
13
+ # межа діапазону лишається в JS (`rules/capacitor/fix.mjs`: `capacitorVersionRangeMinMajor`).
14
+ # JS-перевірка лишилась authoritative й бігає через `npx @nitra/cursor fix capacitor`;
15
15
  # ця Rego — швидкий gate для одиничного `package.json` (наприклад через IDE).
16
16
  #
17
17
  # FS-сканування пакетів через workspaces, iOS-специфічна логіка (Podfile), вибір
@@ -10,7 +10,7 @@ alwaysApply: true
10
10
 
11
11
  1. **`version`** у `<ws>/package.json` (або `[project].version` у `pyproject.toml`) → **patch +1** відносно `git show HEAD:<ws>/package.json`, якщо ще не піднято.
12
12
  2. **`CHANGELOG.md`** того workspace → **нова** секція `## [версія] - YYYY-MM-DD` **зверху** (не bullet-и в стару версію).
13
- 3. **`npx @nitra/cursor check changelog`** (у репо `@nitra/cursor`: `bun ./npm/bin/n-cursor.js check changelog`) → exit **`0`**.
13
+ 3. **`npx @nitra/cursor fix changelog`** (у репо `@nitra/cursor`: `bun ./npm/bin/n-cursor.js check changelog`) → exit **`0`**.
14
14
 
15
15
  **Тригер шляхів (приклади):** `npm/**`, `packages/foo/**`, будь-який каталог з власним `package.json` / `pyproject.toml`, куди потрапили правки.
16
16
 
@@ -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
  }
package/rules/ci4/ci4.mdc CHANGED
@@ -30,7 +30,7 @@ RAG витягує **фрагменти**, не цілі документи. Т
30
30
 
31
31
  ## Docs-as-Code
32
32
 
33
- Документація живе у Git поруч із кодом, проходить **той самий Code Review**, версіонується і автоматично перевіряється у CI (лінтери Markdown, валідатори посилань, `npx @nitra/cursor check`). Биті посилання й документація, що «не компілюється», — **блокуючий баг**, не косметика.
33
+ Документація живе у Git поруч із кодом, проходить **той самий Code Review**, версіонується і автоматично перевіряється у CI (лінтери Markdown, валідатори посилань, `npx @nitra/cursor fix`). Биті посилання й документація, що «не компілюється», — **блокуючий баг**, не косметика.
34
34
 
35
35
  ## Трасування як документація недетермінованої поведінки
36
36
 
package/rules/ci4/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
  }
@@ -7,7 +7,7 @@ alwaysApply: false
7
7
 
8
8
  # Docker — hadolint
9
9
 
10
- Для образів з Docker Hub — **`oven/bun`**, **`alpine`**, **`nginxinc/nginx-unprivileged`**, **`node`** — у **`FROM`** треба вказувати дзеркало GCR, а не pull напряму з Hub: **`mirror.gcr.io/oven/bun`**, **`mirror.gcr.io/library/alpine`**, **`mirror.gcr.io/nginxinc/nginx-unprivileged`**, **`mirror.gcr.io/library/node`**. Перевіряє **`check-docker.mjs`**, деталі в **`npm/rules/docker/js/lint/docker-mirror.mjs`**.
10
+ Для образів з Docker Hub — **`oven/bun`**, **`alpine`**, **`nginxinc/nginx-unprivileged`**, **`node`** — у **`FROM`** треба вказувати дзеркало GCR, а не pull напряму з Hub: **`mirror.gcr.io/oven/bun`**, **`mirror.gcr.io/library/alpine`**, **`mirror.gcr.io/nginxinc/nginx-unprivileged`**, **`mirror.gcr.io/library/node`**. Перевіряє **`rules/docker/fix.mjs`**, деталі в **`npm/rules/docker/js/lint/docker-mirror.mjs`**.
11
11
 
12
12
  Також Dockerfile/Containerfile **має бути multistage build**: окремий build stage (залежності/компіляція) і окремий runtime stage. У фінальному stage дозволені лише мінімальні базові образи:
13
13
 
@@ -90,20 +90,20 @@ CMD ["./app"]
90
90
 
91
91
  ## Область
92
92
 
93
- - Усі файли з іменем **`Dockerfile`** або **`Dockerfile.*`** (наприклад `Dockerfile.prod`) у репозиторії, крім ігнорованих каталогів (`node_modules`, `.git`, `dist`, …) — як у **`check-docker.mjs`**.
93
+ - Усі файли з іменем **`Dockerfile`** або **`Dockerfile.*`** (наприклад `Dockerfile.prod`) у репозиторії, крім ігнорованих каталогів (`node_modules`, `.git`, `dist`, …) — як у **`rules/docker/fix.mjs`**.
94
94
  - Також скрипт перевірки обробляє **`Containerfile`** та **`Containerfile.*`** (Podman / альтернативні імена), навіть якщо glob правила спрацьовує переважно на `Dockerfile*`.
95
95
 
96
96
  ## lint-docker
97
97
 
98
98
  CLI **`hadolint`** приймає лише **явні шляхи** (`[DOCKERFILE...]` у **`hadolint --help`**); обхід репозиторію робить CLI **`n-cursor lint-docker`** (реалізація — **`npm/rules/docker/js/run.mjs`**).
99
99
 
100
- **Область lint-docker (вужча, ніж `check docker`):** лише файли з іменем **`Dockerfile`** та **`*.Dockerfile`** (суфікс **`.dockerfile`** без урахування регістру, наприклад **`api.Dockerfile`**). Файли **`Dockerfile.prod`**, **`Containerfile`** тощо **не** входять у **`lint-docker`**; їх ловить **`check docker`** (`check-docker.mjs`).
100
+ **Область lint-docker (вужча, ніж `check docker`):** лише файли з іменем **`Dockerfile`** та **`*.Dockerfile`** (суфікс **`.dockerfile`** без урахування регістру, наприклад **`api.Dockerfile`**). Файли **`Dockerfile.prod`**, **`Containerfile`** тощо **не** входять у **`lint-docker`**; їх ловить **`check docker`** (`rules/docker/fix.mjs`).
101
101
 
102
- Обхід: **`walkDir`** з тими самими пропусками каталогів, що й **`check-docker.mjs`**. Виклик **`hadolint`**: **`PATH`**, інакше **`docker run`** — спільна логіка **`npm/rules/docker/js/lint/docker-hadolint.mjs`**.
102
+ Обхід: **`walkDir`** з тими самими пропусками каталогів, що й **`rules/docker/fix.mjs`**. Виклик **`hadolint`**: **`PATH`**, інакше **`docker run`** — спільна логіка **`npm/rules/docker/js/lint/docker-hadolint.mjs`**.
103
103
 
104
104
  - Канон `package.json#scripts.lint-docker`: [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
105
105
 
106
- Якщо правило **`docker`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json` **обов'язково** мають бути скрипт **`lint-docker`** і виклик **`bun run lint-docker`** у агрегованому **`lint`** (див. **`bun.mdc`**). Це перевіряє **`npx @nitra/cursor check bun`**.
106
+ Якщо правило **`docker`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json` **обов'язково** мають бути скрипт **`lint-docker`** і виклик **`bun run lint-docker`** у агрегованому **`lint`** (див. **`bun.mdc`**). Це перевіряє **`npx @nitra/cursor fix bun`**.
107
107
 
108
108
  Додай workflow **`.github/workflows/lint-docker.yml`** (гілки **`dev`** і **`main`**, лише **`.yml`**, узгоджено з **`ga.mdc`**):
109
109
 
@@ -116,7 +116,7 @@ CLI **`hadolint`** приймає лише **явні шляхи** (`[DOCKERFILE
116
116
  ## Запуск
117
117
 
118
118
  1. **`bun run lint-docker`** — **`run-docker.mjs`**: **`Dockerfile`** та **`*.Dockerfile`** (див. **`lint-docker`**); у CI встанови hadolint (приклад у workflow).
119
- 2. **`npx @nitra/cursor check docker`** — **`check-docker.mjs`**, виклик hadolint як у **`docker-hadolint.mjs`** (**`PATH`** або **`docker run`** з **`hadolint/hadolint:v2.12.0`**).
119
+ 2. **`npx @nitra/cursor fix docker`** — **`rules/docker/fix.mjs`**, виклик hadolint як у **`docker-hadolint.mjs`** (**`PATH`** або **`docker run`** з **`hadolint/hadolint:v2.12.0`**).
120
120
  3. Кореневий **`.hadolint.yaml`**: вимкнення правил, trusted registries — [документація](https://github.com/hadolint/hadolint#configure). Щоб не додавати **`# hadolint ignore=DL3007`** у кожному **`FROM`** з **`:latest`**, у корені репозиторію задати глобально:
121
121
 
122
122
  ```yaml title=".hadolint.yaml"
@@ -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
  }
@@ -14,6 +14,7 @@ import { lintDockerfileWithHadolint, posixRel } from '../js/lint/docker-hadolint
14
14
  import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
15
15
  import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
16
16
  import { walkDir } from '../../../scripts/utils/walkDir.mjs'
17
+ import { withLock } from '../../../scripts/utils/with-lock.mjs'
17
18
 
18
19
  /**
19
20
  * Чи входить файл до набору lint-docker: Dockerfile або *.Dockerfile (*.dockerfile).
@@ -46,11 +47,10 @@ export async function findLintDockerfilePaths(root, ignorePaths = []) {
46
47
  }
47
48
 
48
49
  /**
49
- * Запуск hadolint по Dockerfile та *.Dockerfile.
50
- * Експортовано як `runLintDocker` — використовується з `bin/n-cursor.js` як підкоманда `lint-docker`.
50
+ * Внутрішні кроки `lint-docker` без локу: hadolint по Dockerfile та *.Dockerfile.
51
51
  * @returns {Promise<number>} 0 — OK, 1 — зауваження або помилка
52
52
  */
53
- export async function runLintDocker() {
53
+ async function runLintDockerSteps() {
54
54
  const reporter = createCheckReporter()
55
55
  const { pass, fail } = reporter
56
56
 
@@ -80,6 +80,13 @@ export async function runLintDocker() {
80
80
  return reporter.getExitCode()
81
81
  }
82
82
 
83
+ /**
84
+ * Публічна CLI-форма: серіалізує через `withLock('lint-docker')` + дедуп за станом git-дерева.
85
+ * Експортовано як `runLintDocker` — використовується з `bin/n-cursor.js` як підкоманда `lint-docker`.
86
+ * @returns {Promise<number>} код виходу
87
+ */
88
+ export const runLintDocker = () => withLock('lint-docker', runLintDockerSteps)
89
+
83
90
  if (isRunAsCli()) {
84
91
  process.exitCode = await runLintDocker()
85
92
  }
@@ -3,7 +3,7 @@
3
3
  # Канон надходить через --data: { "template": { "snippet": ... } }
4
4
  # Перевіряє ЛИШЕ зміст значення `scripts.lint-docker`, якщо ключ присутній.
5
5
  # Умовну обовʼязковість (правило `docker` у `.n-cursor.json` → `scripts.lint-docker`
6
- # зобовʼязаний існувати) перевіряє `check-bun.mjs` через cross-file логіку.
6
+ # зобовʼязаний існувати) перевіряє `rules/bun/fix.mjs` через cross-file логіку.
7
7
  package docker.package_json
8
8
 
9
9
  import rego.v1
@@ -16,7 +16,7 @@ bun add -d @nitra/efes-docs
16
16
 
17
17
  ## Швидкий gate через conftest (Rego)
18
18
 
19
- Пер-документні перевірки efes — rego-полісі у **`npm/rules/efes/policy/`** (запускається через **`npx @nitra/cursor check efes`**; синтаксичний lint — через **`bun run lint-rego`**). Деталі шаблону — у **conftest.mdc** / **n-rego.mdc**.
19
+ Пер-документні перевірки efes — rego-полісі у **`npm/rules/efes/policy/`** (запускається через **`npx @nitra/cursor fix efes`**; синтаксичний lint — через **`bun run lint-rego`**). Деталі шаблону — у **conftest.mdc** / **n-rego.mdc**.
20
20
 
21
21
  Пакети (директорія в **`npm/rules/efes/policy/`** → namespace → що перевіряє):
22
22
 
@@ -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
  }
@@ -4,7 +4,7 @@ alwaysApply: true
4
4
  version: '1.0'
5
5
  ---
6
6
 
7
- Правило про **зворотний звʼязок до пакета `@nitra/cursor`**. Виконуючи скіл пакета (`n-lint`, `n-fix`, `n-taze`, `n-adr-normalize`, `n-llm-patch`, `n-publish-telegram`, `mdc-check`), агент проходить крізь правила `.cursor/rules/`, інструкції `SKILL.md` і програмні перевірки `npx @nitra/cursor check`. Саме тут видно, що в пакеті недопрацьовано: неоднозначна інструкція, відсутня перевірка, хибне спрацювання, порушення без автофіксу. Ця інформація цінна для розробників пакета, але без явного кроку зникає разом із сесією.
7
+ Правило про **зворотний звʼязок до пакета `@nitra/cursor`**. Виконуючи скіл пакета (`n-lint`, `n-fix`, `n-taze`, `n-adr-normalize`, `n-llm-patch`, `n-publish-telegram`, `mdc-check`), агент проходить крізь правила `.cursor/rules/`, інструкції `SKILL.md` і програмні перевірки `npx @nitra/cursor fix`. Саме тут видно, що в пакеті недопрацьовано: неоднозначна інструкція, відсутня перевірка, хибне спрацювання, порушення без автофіксу. Ця інформація цінна для розробників пакета, але без явного кроку зникає разом із сесією.
8
8
 
9
9
  ## Коли застосовувати
10
10
 
@@ -17,7 +17,7 @@ version: '1.0'
17
17
  **Тертя** — усе, що ускладнило роботу скілу й стосується самого пакета `@nitra/cursor`, а не коду користувацького проєкту:
18
18
 
19
19
  - неоднозначна чи неповна інструкція в `SKILL.md` або `.mdc`;
20
- - правило вимагає поведінку, яку можна перевірити програмно, але `check-*.mjs` для неї немає;
20
+ - правило вимагає поведінку, яку можна перевірити програмно, але програмної перевірки (`rules/<id>/js/<concern>/check.mjs` або `rules/<id>/policy/<concern>/*.rego`) для неї немає;
21
21
  - хибне спрацювання перевірки (false positive);
22
22
  - порушення, яке правило вимагає виправляти вручну, хоча реальний автофікс можливий;
23
23
  - повторюваний патерн, який варто закодувати в правило чи скіл.
@@ -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
  }
package/rules/ga/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
  }
@@ -2,13 +2,13 @@
2
2
  * CLI-обгортка над канонічним `lint-ga` (ga.mdc): робить preflight на `shellcheck`, `uv` (для `uvx`)
3
3
  * і `conftest` (для rego-полісі у `check-ga`),
4
4
  * тоді послідовно виконує `bunx github-actionlint`, `uvx zizmor --offline --collect=workflows .` і
5
- * делегує до `check-ga.mjs::check()` — там і Rego-частина (через `runConftestBatch`),
5
+ * делегує до `rules/ga/fix.mjs::check()` — там і Rego-частина (через `runConftestBatch`),
6
6
  * і JS cross-file перевірки правил `ga.mdc`.
7
7
  *
8
8
  * Plan B-патерн (rego-authoritative): Rego-полісі (`npm/policy/ga/`) запускає вже сам
9
- * `check-ga.mjs::check()` як перший крок — `lint-ga.mjs` про це не знає. Раніше `lint-ga.mjs` сам
9
+ * `rules/ga/fix.mjs::check()` як перший крок — `lint-ga.mjs` про це не знає. Раніше `lint-ga.mjs` сам
10
10
  * спавнив conftest для `ga.<name>` per-workflow і `ga.workflow_common` (PoC); тепер ця логіка
11
- * централізована у `check-ga.mjs`, тож одне джерело істини, без дублювання між
11
+ * централізована у `rules/ga/fix.mjs`, тож одне джерело істини, без дублювання між
12
12
  * `lint-ga` і `npx \@nitra/cursor check ga`.
13
13
  *
14
14
  * Без preflight `actionlint` (через `bunx github-actionlint`) мовчки пропускає shell-перевірки в
@@ -18,7 +18,7 @@
18
18
  * `uv` потрібен для `uvx zizmor`. Якщо його нема — `uvx zizmor` падає неінформативно («command not
19
19
  * found»); підказка з командою встановлення коротша й корисніша.
20
20
  *
21
- * `conftest` потрібен для `check-ga.mjs::runAllGaRego` (`runConftestBatch`). Без preflight крок
21
+ * `conftest` потрібен для `rules/ga/fix.mjs::runAllGaRego` (`runConftestBatch`). Без preflight крок
22
22
  * check-ga кидає виняток, який глобальний `catch` у `bin/n-cursor.js` раніше ковтав без логу —
23
23
  * локально це виглядало як мовчазний exit 1.
24
24
  *
@@ -137,7 +137,7 @@ function preflight(dep) {
137
137
  * 1) preflight: `shellcheck`, `uv` (для `uvx zizmor`) і `conftest` (для check-ga); відсутній → exit 1;
138
138
  * 2) `bunx github-actionlint`;
139
139
  * 3) `uvx zizmor --offline --collect=workflows .`;
140
- * 4) `check-ga.mjs::check()` — Rego-полісі (батч conftest з `npm/policy/ga/`) + JS cross-file
140
+ * 4) `rules/ga/fix.mjs::check()` — Rego-полісі (батч conftest з `npm/policy/ga/`) + JS cross-file
141
141
  * перевірки правил `ga.mdc`. Це **те саме**, що робить `npx \@nitra/cursor check ga`, тож
142
142
  * `lint-ga` тепер є суперсетом перевірки правила: external-tools + check.
143
143
  *
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Порт `verifyNoDirectBunOrCache`, `verifyNoRunShellLineContinuationBackslash`,
4
4
  # `verifyCheckoutBeforeLocalSetupBunDeps` та `validateConcurrencyOnRoot` з
5
- # `npm/scripts/check-ga.mjs`. На відміну від `lint_ga`/`clean_ga_workflows`/
5
+ # `npm/scripts/rules/ga/fix.mjs`. На відміну від `lint_ga`/`clean_ga_workflows`/
6
6
  # `clean_merged_branch`/`git_ai`, цей пакет не привʼязаний до конкретного
7
7
  # workflow — `conftest test` запускається на кожному файлі окремо з
8
8
  # `--namespace ga.workflow_common`, і `input` — це окремий розпарсений YAML.
@@ -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
  }
@@ -1,8 +1,8 @@
1
1
  # Перевірка `.vscode/extensions.json` для graphql (graphql.mdc).
2
2
  #
3
- # Викликається з `check-graphql.mjs` через `runConftestBatch` лише ПІСЛЯ того,
3
+ # Викликається з `rules/graphql/fix.mjs` через `runConftestBatch` лише ПІСЛЯ того,
4
4
  # як JS виявив `gql\`…\`` tagged template literal у джерелах (умовне правило).
5
- # Тому без `target.json` поруч (не auto-discoverable через `n-cursor check`) —
5
+ # Тому без `target.json` поруч (не auto-discoverable через `n-cursor fix`) —
6
6
  # інакше були б false-positive порушення на проєктах без gql.
7
7
  #
8
8
  # Canonical (graphql.mdc):
@@ -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
  }
@@ -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
  }
@@ -5,7 +5,7 @@ globs: "**/*.{png,jpg,jpeg,gif,avif,vue,html}"
5
5
  alwaysApply: false
6
6
  ---
7
7
 
8
- AVIF-двійники (`<name>.<ext>.avif`) генерує **виключно** `npx @nitra/cursor check image-avif` — у `lint-image` прапорець `--avif` заборонений (це валідує правило `image-compress`). Перевірка робить чотири кроки в порядку:
8
+ AVIF-двійники (`<name>.<ext>.avif`) генерує **виключно** `npx @nitra/cursor fix image-avif` — у `lint-image` прапорець `--avif` заборонений (це валідує правило `image-compress`). Перевірка робить чотири кроки в порядку:
9
9
 
10
10
  1. **Pre-scan**: шукає у `.vue`/`.html` хоча б одне raster-посилання, яке потенційно треба переписати на AVIF-двійник (`import x from '...png'` або `<img src="...png" />`). Пакети з opt-out `disable-avif: true` пропускаються. **Якщо жодного raster-посилання не знайдено — `check image-avif` завершується успіхом одразу: ні `npx --avif`, ні rewrite, ні cleanup-сиріт не виконуються** (нічого було б змінювати). Так уникаємо дорогого `npx @nitra/minify-image` у проєктах, де AVIF не вживається.
11
11
  2. Запускає `npx @nitra/minify-image --src=. --write --avif` (≥ **3.3.1**) — генерує `<name>.<ext>.avif` поряд з кожним PNG/JPEG/GIF. CLI порівнює sha1 кожного raster-сорсу зі збереженим у `.n-minify-image.tsv` і перезаписує `<source>.avif` при зміні оригіналу.
@@ -218,7 +218,7 @@ async function checkVueAvifImportsInPackage(packageRoot, otherRootsAbs, ignorePa
218
218
  VUE_RASTER_IMPORT_RE,
219
219
  importPath =>
220
220
  `[${label}] ${rel}: import з '${importPath}' має посилатись на AVIF-двійник '${importPath}.avif' ` +
221
- `(\`npx @nitra/cursor check image-avif\` створює його поряд, якщо оригінал є на диску). Вимкнути локально: "@nitra/minify-image": { "disable-avif": true } у package.json пакета`
221
+ `(\`npx @nitra/cursor fix image-avif\` створює його поряд, якщо оригінал є на диску). Вимкнути локально: "@nitra/minify-image": { "disable-avif": true } у package.json пакета`
222
222
  )
223
223
  processMatches(
224
224
  VUE_RASTER_STATIC_SRC_RE,
@@ -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
  }
@@ -100,7 +100,7 @@ export async function check() {
100
100
  fail('package.json не знайдено в корені — додай (image-compress.mdc)')
101
101
  return reporter.getExitCode()
102
102
  }
103
- pass('package.json є (структуру перевіряє npx @nitra/cursor check → image_compress.package_json)')
103
+ pass('package.json є (структуру перевіряє npx @nitra/cursor fix → image_compress.package_json)')
104
104
 
105
105
  await checkHashCacheNotIgnored(pass, fail)
106
106
  await checkLegacyCacheRemoved(pass, fail)
@@ -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
  }
@@ -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
  }